user-0 提问: #define B_PTR(var)  ((unsigned char*)(void *) &(var))

回复:
user: user-1
content: 引用 34 楼 lwouyang 的回复:两位前辈的激烈辩论触发我等强烈的学习动力，正开动马达高速旋转学习ing。 争论的焦点很明确，是否有必要经过 void* 这层中间转换，或者说在中间插入 void* 这层转换有没有什么用处？ sholber 前辈引的 6.3.2.3 条款1讲的是 void* 和其他指针之间的关系，充分表明了 void* 作为通用指针的本质。可与任何类型的指针互换，任何指针转换成 void* 后再转回去时值不变。说明 void* 是万能的粘合剂，具备容纳所有指针类型的各种细节的能力，说明 void* 的大小不会比任何一种指针类型小。但标准没有说 void* 转成一种具体类型的指针后再转回 void* 时值不变，想了想，我认为这儿是问题。这种关系我能用 unsigned long long 之于所有整型类型的关系作参考吗？ 而条款7，英文不好，啃起来老费力了，条款7中间两句话，如果无法准确对齐，行为未定义，否则。。我把否则倒过来，就变成说，如果对齐方面OK的话，那结果就皆大欢喜了，只有没法对齐，才行为未定义。这样理解是否有误？ 另外，我看过《C语言参考手册》提到一种高难度计算机，字长36位，而字节是7位的。面对这种诡异情形，假设 int 的大小是字长，字符类型大小是字节的话，中间有一层 void* 中介的转换和直接从 int 转换到字节类型，两者有什么不同。两位前辈如何理解？  首先，可以肯定的是，通过void *进行中转的必要性纯属子虚乌有，臆想出来的。你在任何现成的书中，任何现成的程序中，包括Linux源代码中，看不到(char *)(void *)p，通常都是(char *)p。产生这种臆想的原因，是因为他们误解了void *引入的动机，只看到各种对象指针被转换为void *传入库函数，又在库函数内转换为char *，完全忘了这些库函数的形参原先本来就是char *。前面已经有所解释。 其次，void *并不是真正的“通用指针”。标准只是保证它可以转换为对象指针，对象指针也可以转换为void指针。但是，标准并没有说void *和函数指针之间的转换关系。void 指针和函数指针之间的转换依然是不能保证安全的。因此，void *并不是万能粘合剂。不过，这倒可以做为将void *作为中间层的反例。 这种关系不能用 unsigned long long 之于所有整型类型的关系作参考。学C没要求你必须了解底层太多。所以，所谓的 “void *具备容纳所有指针类型的各种细节的能力”也不必较真，有种说法是函数指针比void *指针复杂。标准只要求对齐正确就可以，但是你用int指针访问char类型的对象，那是你自己愚蠢，不关C的事。其它没有要求，至于内存分段、分页之类的，完全是学杂了纯粹多虑。 标准只保证void指针和对象指针之间、不同的对象指针之间、不同的函数指针之间可以互相转换，“可以互相转换”的意思毕竟是不会产生某些同学所谓的“精度问题”，在这几种转换之间所谓的精度损失之说是最近才发现的胡扯。 不对齐当然是未定义的，但即使对齐了，也未必是安全的，将指向char的指针转换为int指针并解引用就是不安全的。 C要求的字节长度至少是8位。你那最后一段的意思不甚了了。

user: user-1
content: 引用 32 楼 supermegaboy 的回复:算了，你去坚持你自己的想法吧，改变别人的想法不是偶的责任，更不是我的义务。我在CSDN这十年来见到的你这类人太多了，这类人来到CSDN的目的并不是为了寻找真相，而只是固执地宣称自己才是正确的，无论别人举出多少正面、反面的证据。  以上引用的部分，也是我想说的。 还是让那些通过google看到这个帖子的人来评论吧。

user: user-2
content: 两位前辈的激烈辩论触发我等强烈的学习动力，正开动马达高速旋转学习ing。 争论的焦点很明确，是否有必要经过 void* 这层中间转换，或者说在中间插入 void* 这层转换有没有什么用处？ sholber 前辈引的 6.3.2.3 条款1讲的是 void* 和其他指针之间的关系，充分表明了 void* 作为通用指针的本质。可与任何类型的指针互换，任何指针转换成 void* 后再转回去时值不变。说明 void* 是万能的粘合剂，具备容纳所有指针类型的各种细节的能力，说明 void* 的大小不会比任何一种指针类型小。但标准没有说 void* 转成一种具体类型的指针后再转回 void* 时值不变，想了想，我认为这儿是问题。这种关系我能用 unsigned long long 之于所有整型类型的关系作参考吗？ 而条款7，英文不好，啃起来老费力了，条款7中间两句话，如果无法准确对齐，行为未定义，否则。。我把否则倒过来，就变成说，如果对齐方面OK的话，那结果就皆大欢喜了，只有没法对齐，才行为未定义。这样理解是否有误？ 另外，我看过《C语言参考手册》提到一种高难度计算机，字长36位，而字节是7位的。面对这种诡异情形，假设 int 的大小是字长，字符类型大小是字节的话，中间有一层 void* 中介的转换和直接从 int 转换到字节类型，两者有什么不同。两位前辈如何理解？

user: user-3
content: 引用 28 楼 sholber 的回复:你应该好好再读一遍那一整段话，看看它是不是讲严格对齐这件事。再说了，void *和字符指针都是单字节对齐的，void *没有对齐问题，字符指针何来对齐问题？ 其实我没想到问题的症结居然在于为什么标准要引入void *这个上面。 void *是在C89引入。在此之前，memcpy的声明类似于char * memcpy(char * dest, const char * src, size_t n);char *可以对齐于任何内存位置，所以，在C89之前它经常用于充当通用指针。但这样的声明问题多多不说，也很别扭，因为我们传入的参数可能是其它类型的指针，还要转换为char *。所以，引入void *之后，声明就可以变成void *memcpy(void*dest, const void *src, size_t n);你引用的那句话，实际上是说，void *与char *在对齐和值的表示上相同，否则，改变原型之后的memcpy将不能工作。 所以说，这本来与我们当前讨论的主题无关，我早在刚开始的时候就说过。你却抓住这一点不放，偶真的感觉很无奈。  你不断重复地列举已被上面帖子引用的标准条款无论从正面还是反面均证明为错误的内容有什么用？这说明什么呢？黔驴技穷？算了，你去坚持你自己的想法吧，改变别人的想法不是偶的责任，更不是我的义务。我在CSDN这十年来见到的你这类人太多了，这类人来到CSDN的目的并不是为了寻找真相，而只是固执地宣称自己才是正确的，无论别人举出多少正面、反面的证据。  尽管如此，我还是希望你能长期在CSDN待下去，因为现在C/C++版懂语言标准的人太少了，五、六年前还有几个，现在几乎绝迹，各种关于语言标准的缺位和五花八门的误解倒是越来越多。看起来你不熟悉C++，有空可以学习一下，这里有另一片广阔的天地，不过如果你属于那种语言优劣论者，可以当我无讲过。

user: user-3
content: 引用 30 楼 sholber 的回复:[quote=引用 25 楼 supermegaboy 的回复:]  亲爱的，让我来猜一下，你这次将会说什么。 你肯定会说，C89之前，memcpy用char *作为参数类型，是不安全的，所以，改成了void *。 果真如此，你赢了，我对标准的理解不如你。[/quote]  哈，怕了么？？

user: user-3
content: 引用 21 楼 sholber 的回复:看不出你引用的那些东西对解释我的问题有任何帮助，我只是不想离题太远。你觉得我熟视无睹，可能是我们对标准的理解不同。那这样好了，请你正面回答我的问题，我再帖一遍： 标准有没有说，指向任何一个对象的指针和指向void的指针有相同的对齐要求和值的表示？ ——如果标准说了，那么，既然(void *)&(VAR)是可以的，(unsigned char *)&(VAR)自然也是可以的，因为“void *和指向字符类型的指针具有相同的对齐要求和值的表示”； ——如果标准没有说，那么(void *)&(VAR)从你的观点来看必然是不安全的。因为你的安全观是“有相同的对齐要求和值的表示”。既然(void *)&(VAR)都不安全，(unsigned char *)(void *)&(VAR)反而是安全的？难道(unsigned char *)有自动纠错功能？ 你可以引用标准来回答，一定要正面回答，比如，你可以说，“那么(void *)&(VAR)从你的观点来看必然是不安全的”是一派胡言，因为标准说了，“…………”，等等，不要列出个标准完事。总之要观众都能看得懂，我也可以知道自己是不是对标准理解有误。 还有，任何人都可以说我是胡说八道或者一派胡言，我不介意的。  你这人的性格，楼主结就结了，管他呢。  标准有没有说，指向任何一个对象的指针和指向void的指针有相同的对齐要求和值的表示？ -------------------------------------------------------------------------------------------------------------------------- 标准对除void*与pointer to character、结构指针、联合指针外其它指针不进行保证。偶在15楼贴的标准内容已经说了：  A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) ...........Pointers to other types need not have the same representation or alignment requirements.  除了void*与pointer to character、结构指针、联合指针之间外，其余指针不需要具有同一的表示和对齐要求。  我给你举两个例：  第一个例子在符合标准规定的范围内，但为了突出典型性和便于说理，不考虑现实是否真有编译器设计者存在类似做法。  假设存在某个编译器设计，指针的实现仅考虑偏移量（representation of types还包括很多其它内容，为便于描述，我这里仅使用数值这一个属性），但因为环境因素等某些原因，pointer to character需要考虑SD（段描述符），这是符合Pointers to other types need not have the same representation or alignment requirements的规定的，但同时由于A pointer to void shall have the same representation and alignment requirements as a pointer to a character type的原因，void*显然也得考虑SD。  好了，当发生( void* )int*时，由于标准规定到void*的转换是保证without loss of information以及void*需要SD的现实状况，int*转换到void*的结果需要补充int*所在的SD，然后再根据void*与char*之间表示和对齐的同一性，可以再安全转换到char*。  但是，如果( char* )int*，会发生什么事情？由于标准没有规定转换到char*必须without loss of information，该编译器的设计人员对于SD是否补充以及如何补充的问题，可考虑也可以不考虑。如果设计人员认为补全这个SD不对编译器的设计目标产生影响，他可以做做好人，允许安全转换；不这样做的话，当然也无可非议，这样SD就丢失了，使用这个char*时所指向的线性地址空间可能与int*原来的指向根本不同！  第二个例子我直接举标准库memcpy在VS上的实现：   void * __cdecl memcpy (         void * dst,         const void * src,         size_t count         ) {         void * ret = dst;  #if defined (_M_IA64)          {           __declspec(dllimport)           void RtlCopyMemory( void *, const void *, size_t count );          RtlCopyMemory( dst, src, count );          }  #else  /* defined (_M_IA64) */         /*          * copy from lower addresses to higher addresses          */         while (count--) {                 *(char *)dst = *(char *)src;                 dst = (char *)dst + 1;                 src = (char *)src + 1;         } #endif  /* defined (_M_IA64) */          return(ret); }   在memcpy的内部，需要进行(void*)到(char*)的转换，偶在15楼贴出的条款，保证了这个转换的安全性，而memcpy的形参类型是void*，可以接受来自其它pointer to other object的arg，这个过程其实跟楼主所举代码的过程一样的嘛。  所以，基本上所有书籍都会建议尽量不要进行显式转换。大家平时没有发现什么问题只不过因为绝大多数编译器都把指针的表示和对齐设计成同一的而已。

user: user-1
content: 引用 25 楼 supermegaboy 的回复:  亲爱的，让我来猜一下，你这次将会说什么。 你肯定会说，C89之前，memcpy用char *作为参数类型，是不安全的，所以，改成了void *。 果真如此，你赢了，我对标准的理解不如你。

user: user-1
content: 你一会儿对齐，一会儿值的表示，翻葫芦倒水，我讲对齐，你讲值的表示，我讲值的表示，你又讲对齐，我引用标准，你给我讲底层实现，你到底要怎样？C就是C，汇编就是汇编，硬件就是硬件，标准就是标准，SD什么的，既然是臆想，也不能作数。不要像欧阳锋，学的太多太杂，以致于……算了，我不说了。 Regards !

user: user-1
content: 引用 27 楼 supermegaboy 的回复:[quote=引用 26 楼 sholber 的回复:]  在第一段，你认为(void *)&(VAR)是安全的，也承认void *和unsigned char *具有相同的对齐要求和值的表示。但是却不承认(unsigned char *)&(VAR)也是安全的。至于原因，你在第二段做了解释，你认为标准没有规定它是安全的。事实上，标准对此专门做了规定“When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object.” 底层的事情交给C的实现就好了，操那么多心干嘛。因为字符类型是单字节的，所以，字符类型可以对齐于任何内存位置，它的指针同样如此。void指针出现之前，大家都用char *来传递各种不同类型的参数，就是因为这个特点，坏处是容易引起误解，毕竟在函数内部，char *类型的参数要转换回原来的类型，引入void *可以解决这种尴尬（所以标准明确规定void *和字符指针有相同的对齐要求和值的表示），至于段描述符之类的，我相信你是想多了。 Regards !  你就是在“When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object”这一条规定上理解错了！这一条规定讲的是严格对齐这个事，这个偶在第7楼和15楼已经说过了。  作为一个反证，假设这条规定就足以保证char*和T*之间的转换的话，那么标准根本就不需要说A pointer to void shall have the same representation and alignment requirements as a pointer to a character type，这根本就不是因为什么“误解”！因为标准给出的理由是：A pointer to void must have the same representation and alignment as a pointer to char; the intent of this rule is to allow existing programs that call library functions such as memcpy and free to continue to work.  意思是只有这一条存在，memcpy之类的函数才能continue to work！没有了就不能work了！  偶在第二段所讲的不安全的情况指的是指针的representation，这与对齐不是一回事！[/quote]  你应该好好再读一遍那一整段话，看看它是不是讲严格对齐这件事。再说了，void *和字符指针都是单字节对齐的，void *没有对齐问题，字符指针何来对齐问题？ 其实我没想到问题的症结居然在于为什么标准要引入void *这个上面。 void *是在C89引入。在此之前，memcpy的声明类似于char * memcpy(char * dest, const char * src, size_t n);char *可以对齐于任何内存位置，所以，在C89之前它经常用于充当通用指针。但这样的声明问题多多不说，也很别扭，因为我们传入的参数可能是其它类型的指针，还要转换为char *。所以，引入void *之后，声明就可以变成void *memcpy(void*dest, const void *src, size_t n);你引用的那句话，实际上是说，void *与char *在对齐和值的表示上相同，否则，改变原型之后的memcpy将不能工作。 所以说，这本来与我们当前讨论的主题无关，我早在刚开始的时候就说过。你却抓住这一点不放，偶真的感觉很无奈。

user: user-3
content: 引用 26 楼 sholber 的回复:在第一段，你认为(void *)&(VAR)是安全的，也承认void *和unsigned char *具有相同的对齐要求和值的表示。但是却不承认(unsigned char *)&(VAR)也是安全的。至于原因，你在第二段做了解释，你认为标准没有规定它是安全的。事实上，标准对此专门做了规定“When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object.” 底层的事情交给C的实现就好了，操那么多心干嘛。因为字符类型是单字节的，所以，字符类型可以对齐于任何内存位置，它的指针同样如此。void指针出现之前，大家都用char *来传递各种不同类型的参数，就是因为这个特点，坏处是容易引起误解，毕竟在函数内部，char *类型的参数要转换回原来的类型，引入void *可以解决这种尴尬（所以标准明确规定void *和字符指针有相同的对齐要求和值的表示），至于段描述符之类的，我相信你是想多了。 Regards !  你就是在“When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object”这一条规定上理解错了！这一条规定讲的是严格对齐这个事，这个偶在第7楼和15楼已经说过了。  作为一个反证，假设这条规定就足以保证char*和T*之间的转换的话，那么标准根本就不需要说A pointer to void shall have the same representation and alignment requirements as a pointer to a character type，这根本就不是因为什么“误解”！因为标准给出的理由是：A pointer to void must have the same representation and alignment as a pointer to char; the intent of this rule is to allow existing programs that call library functions such as memcpy and free to continue to work.  意思是只有这一条存在，memcpy之类的函数才能continue to work！没有了就不能work了！  偶在第二段所讲的不安全的情况指的是指针的representation，这与对齐不是一回事！

user: user-1
content: 引用 25 楼 supermegaboy 的回复:好了，当发生( void* )int*时，由于标准规定到void*的转换是保证without loss of information以及void*需要SD的现实状况，int*转换到void*的结果需要补充int*所在的SD，然后再根据void*与char*之间表示和对齐的同一性，可以再安全转换到char*。   但是，如果( char* )int*，会发生什么事情？由于标准没有规定转换到char*必须without loss of information，该编译器的设计人员对于SD是否补充以及如何补充的问题，可考虑也可以不考虑。如果设计人员认为补全这个SD不对编译器的设计目标产生影响，他可以做做好人，允许安全转换；不这样做的话，当然也无可非议，这样SD就丢失了，使用这个char*时所指向的线性地址空间可能与int*原来的指向根本不同！  在第一段，你认为(void *)&(VAR)是安全的，也承认void *和unsigned char *具有相同的对齐要求和值的表示。但是却不承认(unsigned char *)&(VAR)也是安全的。至于原因，你在第二段做了解释，你认为标准没有规定它是安全的。事实上，标准对此专门做了规定“When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object.” 底层的事情交给C的实现就好了，操那么多心干嘛。因为字符类型是单字节的，所以，字符类型可以对齐于任何内存位置，它的指针同样如此。void指针出现之前，大家都用char *来传递各种不同类型的参数，就是因为这个特点，坏处是容易引起误解，毕竟在函数内部，char *类型的参数要转换回原来的类型，引入void *可以解决这种尴尬（所以标准明确规定void *和字符指针有相同的对齐要求和值的表示），至于段描述符之类的，我相信你是想多了。 Regards !

user: user-1
content: 搞什么嘛，没讨论出个结果就结帖，你这样平均分配分数要不得…… 强烈要求版主将状态退回到结帖之前！

user: user-0
content: 本来我都认为我懂了，经过你们两人的一番见解，我发现我读的书实在是太少了，两位大神看待问题都能有自己的独特的见解，很厉害

user: user-1
content: 再：不用给我补课，捡重要的说，紧扣当前问题。至于别的知识，如果我没掌握或者理解错了，就让我错一辈子好了。不怪别人。

user: user-1
content: 引用 20 楼 supermegaboy 的回复:[quote=引用 19 楼 sholber 的回复:] 好吧，鉴于你又开始重新狡辩“值的表示”，那么，标准有没有说，指向任何一个对象的指针和指向void的指针有相同的对齐要求和值的表示？ ——如果标准说了，那么，既然(void *)&(VAR)是可以的，(unsigned char *)&(VAR)自然也是可以的，因为“void *和指向字符类型的指针具有相同的对齐要求和值的表示”； ——如果标准没有说，那么(void *)&(VAR)从你的观点来看必然是不安全的。因为你的安全观是“有相同的对齐要求和值的表示”。既然(void *)&(VAR)都不安全，(unsigned char *)(void *)&(VAR)反而是安全的？难道(unsigned char *)有自动纠错功能？  PS：别夸我，我会心软的。关于写书，那实在不算什么，现在随便一个人都能写书，真的。你说我不尊重人，说实话，这个版块里的很多人不值得尊重，就象版主所说的，二半吊子，上来就胡说八道，自己错了无关紧要，关键是误导很多人。版主也是不象话，要是在stackoverflow，百分之七十的帖子都应该删除。  说来说去你就是拐不过弯来，而且对别人帖子的内容似乎熟视无睹（也可能是不理解），你这里所说的问题在偶15楼和18楼贴出来的标准和rational的内容已经说得很明白。  另：对别人的尊重是一种个人素质，与别人无关。论坛是个自由讨论问题的地方，谁都可以发表自己的意见，不管对还是错，你可以认为别人在胡说八道，但不代表你就是对的，同样地，别人一样认为你在胡说八道。[/quote]  看不出你引用的那些东西对解释我的问题有任何帮助，我只是不想离题太远。你觉得我熟视无睹，可能是我们对标准的理解不同。那这样好了，请你正面回答我的问题，我再帖一遍： 标准有没有说，指向任何一个对象的指针和指向void的指针有相同的对齐要求和值的表示？ ——如果标准说了，那么，既然(void *)&(VAR)是可以的，(unsigned char *)&(VAR)自然也是可以的，因为“void *和指向字符类型的指针具有相同的对齐要求和值的表示”； ——如果标准没有说，那么(void *)&(VAR)从你的观点来看必然是不安全的。因为你的安全观是“有相同的对齐要求和值的表示”。既然(void *)&(VAR)都不安全，(unsigned char *)(void *)&(VAR)反而是安全的？难道(unsigned char *)有自动纠错功能？ 你可以引用标准来回答，一定要正面回答，比如，你可以说，“那么(void *)&(VAR)从你的观点来看必然是不安全的”是一派胡言，因为标准说了，“…………”，等等，不要列出个标准完事。总之要观众都能看得懂，我也可以知道自己是不是对标准理解有误。 还有，任何人都可以说我是胡说八道或者一派胡言，我不介意的。

user: user-3
content: 引用 19 楼 sholber 的回复:好吧，鉴于你又开始重新狡辩“值的表示”，那么，标准有没有说，指向任何一个对象的指针和指向void的指针有相同的对齐要求和值的表示？ ——如果标准说了，那么，既然(void *)&(VAR)是可以的，(unsigned char *)&(VAR)自然也是可以的，因为“void *和指向字符类型的指针具有相同的对齐要求和值的表示”； ——如果标准没有说，那么(void *)&(VAR)从你的观点来看必然是不安全的。因为你的安全观是“有相同的对齐要求和值的表示”。既然(void *)&(VAR)都不安全，(unsigned char *)(void *)&(VAR)反而是安全的？难道(unsigned char *)有自动纠错功能？  PS：别夸我，我会心软的。关于写书，那实在不算什么，现在随便一个人都能写书，真的。你说我不尊重人，说实话，这个版块里的很多人不值得尊重，就象版主所说的，二半吊子，上来就胡说八道，自己错了无关紧要，关键是误导很多人。版主也是不象话，要是在stackoverflow，百分之七十的帖子都应该删除。  说来说去你就是拐不过弯来，而且对别人帖子的内容似乎熟视无睹（也可能是不理解），你这里所说的问题在偶15楼和18楼贴出来的标准和rational的内容已经说得很明白。  另：对别人的尊重是一种个人素质，与别人无关。论坛是个自由讨论问题的地方，谁都可以发表自己的意见，不管对还是错，你可以认为别人在胡说八道，但不代表你就是对的，同样地，别人一样认为你在胡说八道。

user: user-1
content: 引用 18 楼 supermegaboy 的回复:[quote=引用 17 楼 sholber 的回复:] 关于从pointer to an object  到  pointer to a character type 的转换，这里说的是对齐的要求，而非值表示，representation of types具有与此不同的语意。  好吧，鉴于你又开始重新狡辩“值的表示”，那么，标准有没有说，指向任何一个对象的指针和指向void的指针有相同的对齐要求和值的表示？ ——如果标准说了，那么，既然(void *)&(VAR)是可以的，(unsigned char *)&(VAR)自然也是可以的，因为“void *和指向字符类型的指针具有相同的对齐要求和值的表示”； ——如果标准没有说，那么(void *)&(VAR)从你的观点来看必然是不安全的。因为你的安全观是“有相同的对齐要求和值的表示”。既然(void *)&(VAR)都不安全，(unsigned char *)(void *)&(VAR)反而是安全的？难道(unsigned char *)有自动纠错功能？  PS：别夸我，我会心软的。关于写书，那实在不算什么，现在随便一个人都能写书，真的。你说我不尊重人，说实话，这个版块里的很多人不值得尊重，就象版主所说的，二半吊子，上来就胡说八道，自己错了无关紧要，关键是误导很多人。版主也是不象话，要是在stackoverflow，百分之七十的帖子都应该删除。

user: user-3
content: 引用 17 楼 sholber 的回复:PS：如果你看了上面一段之后，依然不承认&(VAR)直接转换到unsigned char *是安全——你我之间的讨论就此打住，因为无话可说，没有共同语言。  呵呵，想逃了么？当然你可以逃，不就是讨论个问题而已嘛，又不是赌身家，用不着过于认真，你随时可以想溜就溜。  关于代码安全性，这已是个人尽皆知的普通概念，不需作特别说明。  关于从pointer to an object  到  pointer to a character type 的转换，这里说的是对齐的要求，而非值表示，representation of types具有与此不同的语意。  关于你所说的“一派胡言”，我就再举证吧，除非你认为WG14也是一派胡言，那我无话可说。C标准在rational中解释了这个问题：  A “pointer to void,” void*, is a generic pointer capable of pointing to any object (except for bit-fields and objects declared with the register storage class and functions) without loss of information. A pointer to void must have the same representation and alignment as a pointer to char; the intent of this rule is to allow existing programs that call library functions such as memcpy and free to continue to work.  其实我去年就读过你写的书，那本书写得不错，有不少优点，缺点是绝大多数内容以前甚至十几二十年前就已经有很多书写过了，新意不够，所以我是把它当作一个复习过程来读的。但是，你在这个帖子中的言行，例如什么“一派胡言”、“还给我上课呢！”等等与我相像中的写书人的形象相差太远了，其它帖子有没有类似的行为我暂时不知道，没功夫去找，也不想把时间浪费在这里。难道，尊重一下别人有这么难吗？其实，我也是个写书人，正在写一本涵盖C与C++两方面的书，只是我的出发点与你和你的partner有点不同，我想写一点还没有书谈及的东西，也许，别人读来，会更加有兴趣一点。

user: user-3
content: 引用 8 楼 sholber 的回复:1，不要扯开话题，这个问题重点不在对齐。就算是和对齐有关，标准也说得很清楚了：“A pointer to an object type may be converted to a pointer to a different object type”。你是觉得标准还不如你从野路子上来的知识吗？ 2，你所说的安全性，好象是指数据截断之类的。话说，A放不下B，先转换为void *，然后A居然又能放下了？这意味着，蛇吞不下象，先转换为void *，然后就可以吞下了？这听起来咋象天方夜谭呢？如果我对你的“安全性”理解有误，请务必解释清楚，我好继续深入讨论。  什么扯开话题啊，应该是你在扯开话题吧。本来我以为你懂这个问题，但是从上面两点看来其实你不懂。  指针间的转换受到两方面的影响，一是对齐，二是指针表示。关于对齐，一开始我看了你在2楼引用的条款，以为你明白对齐的影响，但是从你在第1点的描述看来，其实你不明白。在一些RISC平台上，例如MIPS、POWERPC等等，对数据对齐有严格要求，这要求指向这些数据的指针值是对齐的，以8字节double和4字节int为例，double*可以8倍地址对齐，int*可以4倍地址对齐，当发生( double* )int*时，转换结果可能不在double*的对齐地址上，可能会引发CPU异常。这就是为什么标准在6.3.2.3的第7子条款中说：If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.的原因所在（在note68中进一步解释这种对齐是可传递的）。但是，我说但是了，标准在这一条款的后半部规定了一个特例，就是转换到character 指针是严格对齐的，所以，楼主的问题不受对齐问题的影响。  于是，偶在1楼的回答不从对齐因素这个角度来解释，而从第二个因素：指针表示这个角度去解释。因为，标准规定：  6.2.5 types的第28子条款：  A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.  除void*与character*、结构指针、联合指针之间外，标准对其它指针均不予以保证。为什么标准要特别说明void*与character*具有相同表示及对齐要求？因为有些库函数（例如memcpy）的内部可能会发生从void*到character*的转换，不如此规定的话，这种转换可能是不安全的，这些库函数是无保证的。楼主的代码巧妙地利用了这条规则，从而保证最大的安全性。

user: user-1
content: PS：如果你看了上面一段之后，依然不承认&(VAR)直接转换到unsigned char *是安全——你我之间的讨论就此打住，因为无话可说，没有共同语言。