char *和void *的对象表示

时间:2019-03-27 07:19:44

标签: c pointers language-lawyer

标准中有6.2.5(p28)处的声明:

  

指向void的指针应具有相同的表示形式和对齐方式   要求作为字符类型的指针。

我不太了解。对象表示被定义为由unsigned char[sizeof(the_type)]获得的memcpy的内容。

因此,取两个任意的char *void *像这样:

int i = 10;
char * test1 = (char *) &i;

int j = 20;
void * test2 = &j;
printf("%d\n", test2 == test1); // prints 0

上面的代码显示0,暗示test2test1的对象表示形式不相同,6.2.6(p4)

  

两个具有相同对象表示形式的值(除NaN之外)   比较相等。

问题: 该子句是否假定指向void 从指针转换为字符类型的指针应该具有相同的表示形式和对齐方式要求作为指向字符类型转换来源的指针

2 个答案:

答案 0 :(得分:2)

printf("%d\n", test2 == test1);

指针test2与test1不同,因为您比较它们的值,这些值代表i和j的位置。 I和J是不同的变量,代表它们的对象的位置不同。

所以将输出设为0是正确的。

如果您这样做:

int i = 10;
char * test1 = (char *) &i;
void * test2 = &i;
printf("%d\n", test2 == test1);

输出将为1。

答案 1 :(得分:2)

“表示”大致表示事物如何存储在内存中。引用的部分6.2.5§28规定某些指针类型必须以相同的方式存储。同一段对其他各种指针类型有更多要求。

除了列出的那些指针类型之外,C还为实现提供了一些自由,以便以奇异且不一定兼容的方式存储指针。但是实际上,这是被误导的,因为我认为任何现实世界的实现都没有做到这一点。相反,需要不同指针表示形式的系统似乎总是为指针限定符发明了非标准关键字:farnear


  

上面的代码打印0表示test2和test1的对象表示形式不相同,即6.2.6(p4)

它们指向不同的变量,因此当然不会相同-指针包含不同的值,而与表示形式无关。要检查其对象表示形式是否相同,您必须执行以下操作:

int i = 10;
char * test1 = (char *) &i;
void * test2 = &i;
printf("%d\n", test2 == test1); // prints 1

或更优:printf("%d\n", memcmp(test1, test2, sizeof test1));。哪个打印0(等于)。


  

问题:该子句是否假定从指向字符类型的指针转​​换为void的指针与指向从其转换字符类型的指针具有相同的表示和对齐要求?

是,因为这是6.2.5§28所必需的。指针转换章节6.3.2.3§7中也有一个要求:

  

指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针未针对引用类型正确对齐,则该行为未定义。否则,再次转换时,结果应等于   原始指针。

这也意味着在实践中,所有对象指针在内部都必须具有相同的格式,否则上面的方法将无法实现。