char*和void的对象表示*

char*和void的对象表示*,c,pointers,language-lawyer,C,Pointers,Language Lawyer,标准6.2.5p28中有一项要求: 指向void的指针应具有相同的表示和对齐方式 作为字符类型指针的需求 我真的不明白。对象表示被定义为memcpy获得的无符号char[sizeofthe_type]的内容 取两个任意的char*和void*比如说: int i = 10; char * test1 = (char *) &i; int j = 20; void * test2 = &j; printf("%d\n", test2 == test1); // prints 0

标准6.2.5p28中有一项要求:

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

我真的不明白。对象表示被定义为memcpy获得的无符号char[sizeofthe_type]的内容

取两个任意的char*和void*比如说:

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

int j = 20;
void * test2 = &j;
printf("%d\n", test2 == test1); // prints 0
上面的代码打印0,这意味着test2和test1的对象表示形式不同,即6.2.6p4

具有相同对象表示形式的两个非NaN值 比较平等

问题:该条款是否假设从字符类型指针转换为void指针的表示和对齐要求与从中转换为void的字符类型指针的表示和对齐要求相同

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

因此,输出值为0是正确的

如果您这样做:

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

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

因此,输出值为0是正确的

如果您这样做:

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

输出将为1。

表示法大致表示事物在内存中的存储方式。引用的第6.2.5部分§28规定,某些指针类型必须以相同的方式存储。同一段落对各种其他指针类型提出了更多的要求

除了列出的指针类型之外,C还为实现提供了一定的自由度,以异国情调且不一定兼容的方式存储指针。但在实践中,这是错误的,因为我不认为任何现实世界的实现曾经这样做过。相反,需要不同指针表示的系统似乎总是为指针限定符发明非标准关键字:远和近

上面的代码打印0,这意味着test2和test1的对象表示形式不同,即6.2.6p4

它们指向不同的变量,所以它当然不会是相同的——指针包含不同的值,而不考虑表示形式。要检查它们的对象表示形式是否相同,必须执行以下操作:

int i = 10;
char * test1 = (char *) &i;
void * test2 = &i;
printf("%d\n", test2 == test1); // prints 1
或者更好:printf%d\n、memcmptest1、test2、sizeof test1;。它打印0等于

问题:该条款是否假设从字符类型指针转换为void指针的表示和对齐要求与从中转换为void的字符类型指针的表示和对齐要求相同

是,因为第6.2.5条第28款要求这样做。指针转换第6.3.2.3§7章中也有要求:

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


这也意味着在实践中,所有对象指针在内部必须具有相同的格式,否则上述格式将不可能实现。

表示法大致上是指事物在内存中的存储方式。引用的第6.2.5部分§28规定,某些指针类型必须以相同的方式存储。同一段落对各种其他指针类型提出了更多的要求

除了列出的指针类型之外,C还为实现提供了一定的自由度,以异国情调且不一定兼容的方式存储指针。但在实践中,这是错误的,因为我不认为任何现实世界的实现曾经这样做过。相反,需要不同指针表示的系统似乎总是为指针限定符发明非标准关键字:远和近

上面的代码打印0,这意味着test2和test1的对象表示形式不同,即6.2.6p4

它们指向不同的变量,所以它当然不会是相同的——指针包含不同的值,而不考虑表示形式。要检查它们的对象表示形式是否相同,必须执行以下操作:

int i = 10;
char * test1 = (char *) &i;
void * test2 = &i;
printf("%d\n", test2 == test1); // prints 1
或者更好:printf%d\n、memcmptest1、test2、sizeof test1;。它打印0等于

问题:该条款是否假设从字符类型指针转换为void指针的表示和对齐要求与从中转换为void的字符类型指针的表示和对齐要求相同

是,因为第6.2.5条第28款要求这样做。指针转换第6.3.2.3§7章中也有要求:

指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针与引用的类型未正确对齐,则行为未定义。其他 rwise,当再次转换回时,结果应与 原始指针


这也意味着在实践中,所有对象指针在内部都必须具有相同的格式,否则上述内容将不可能实现。

您的示例与指针的类型无关。它们指向不同的地方,所以它们并不相等。即使将void*更改为char*,结果也将保持不变。同样地,如果你改变它,使两者都指向同一个地方,例如i,那么结果是1,无论它们是char*还是void*。标准是指指针的对象表示,而不是指向的对象的对象表示。我很确定它是指如果int i;char*pc=char*&i;void*pv=&i;,然后memcmp&pc,&pv,sizeof pc==0。@因此,显式或隐式地将指向char*的指针转换为指向void*的指针将具有相同的对象表示形式。标准没有明确规定这一点,这可能是显而易见的,因为@Blaze提到它们指向不同的对象,并且不能进行相等的比较。我认为在标准中术语的使用方式存在混淆:类型的表示要求和值的对象表示,这些都是稍微不同的东西。你的例子与它们是什么类型的指针无关。它们指向不同的地方,所以它们并不相等。即使将void*更改为char*,结果也将保持不变。同样地,如果你改变它,使两者都指向同一个地方,例如i,那么结果是1,无论它们是char*还是void*。标准是指指针的对象表示,而不是指向的对象的对象表示。我很确定它是指如果int i;char*pc=char*&i;void*pv=&i;,然后memcmp&pc,&pv,sizeof pc==0。@因此,显式或隐式地将指向char*的指针转换为指向void*的指针将具有相同的对象表示形式。标准没有明确规定这一点,这可能是显而易见的,因为@Blaze提到它们指向不同的对象,并且不能进行相等的比较。我认为在标准中术语的使用方式存在混淆:类型的表示要求和值的对象表示,这是稍微不同的东西。char*test1=&i;我认为这会导致未定义的行为。由于赋值运算符规则6.5.16.1p1,两个操作数都是指向兼容类型的合格或不合格版本的指针。因此,我们需要显式转换为char*test1=char*&i@一个不好的名字,而不是UB@curiousguy在C++中,但是我可以说C标准没有定义不成形程序或类似的术语。至少搜索“ill”这个词没有产生任何有用的结果。@SomeName你可能就在这里。。。我可能混淆了C++和C术语。My bad.char*test1=&i;我认为这会导致未定义的行为。由于赋值运算符规则6.5.16.1p1,两个操作数都是指向兼容类型的合格或不合格版本的指针。因此,我们需要显式转换为char*test1=char*&i@一个不好的名字,而不是UB@curiousguy在C++中,但是我可以说C标准没有定义不成形程序或类似的术语。至少搜索“ill”这个词没有产生任何有用的结果。@SomeName你可能就在这里。。。我可能混淆了C++和C术语。我的错。@melpomene是的,总是有一些实验性的,历史性的建筑。但在计算机考古学领域之外,重要的系统是主流MS DOS和无数微控制器系统,在这些系统中,外部寻址需要超过16位。他们都通过发明far限定符来解决这个问题,以避免指针转换过程中出现细微的错误。C语言根本无法以合理的方式满足现实世界的要求。@melpomene是的,总是有一些实验性的、历史性的架构。但在计算机考古学领域之外,重要的系统是主流MS DOS和无数微控制器系统,在这些系统中,外部寻址需要超过16位。他们都通过发明far限定符来解决这个问题,以避免指针转换过程中出现细微的错误。C语言根本无法以合理的方式满足现实世界的要求。