C和C++中未定义,未指定和实现定义的行为有什么区别?
c c++ undefined-behavior unspecified-behavior implementation-defined-behavior
关于和运营商的C标准第6.5.9节规定如下:==!=
2下列之一应持有:
- 两个操作数都有算术类型;
- 两个操作数都是指向兼容类型的限定或非限定版本的指针;
- 一个操作数是指向对象类型的指针,另一个是指向合格或非限定版本的void的指针; 要么
- 一个操作数是一个指针,另一个是空指针常量.
...
6 两个指针比较相等,当且仅当两个都是空指针时,两者都是指向同一对象的指针(包括指向对象的指针和在其开头的子对象)或函数,两者都是指向同一对象的最后一个元素的指针数组对象,或者一个是指向一个数组对象末尾的指针,另一个是指向不同数组对象的开头的指针,该数组对象恰好跟随地址空间中的第一个数组对象.109)
7出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型.
脚注109:
109)两个对象在内存中可能相邻,因为它们是较大数组的相邻元素或结构的相邻成员,它们之间没有填充,或者因为实现选择放置它们,即使它们是不相关的.如果先前的无效指针操作(例如数组边界外的访问)产生了未定义的行为,则后续比较也会产生未定义的行为.
这似乎表明您可以执行以下操作:
int a;
int b;
printf("a precedes b: %d\n", (&a + 1) == &b);
printf("b precedes a: %d\n", (&b + 1) == &a);
Run Code Online (Sandbox Code Playgroud)
这应该是合法的,因为我们使用地址一个元素超过数组的末尾(在这种情况下是一个被视为大小为1的数组的单个对象),而不解除引用它.更重要的是,1如果一个变量在内存中紧跟另一个变量,则需要输出这两个语句中的一个.
但是,测试似乎没有把它弄平.鉴于以下测试计划:
#include <stdio.h>
struct s {
int a;
int b;
};
int main()
{
int a;
int b;
int *x = &a;
int *y = &b;
printf("sizeof(int)=%zu\n", …Run Code Online (Sandbox Code Playgroud) 我最近在回答一个关于p < q当p和q是指向不同对象/数组的指针时在C 中执行的未定义行为的问题。这让我想到:C ++ <在这种情况下具有相同(未定义)的行为,但是还提供了标准库模板std::less,该模板保证可以返回与<可以比较指针时相同的东西,并在不能比较时返回一些一致的顺序。
C是否提供具有类似功能的东西,从而可以安全地比较任意指针(相同类型)?我尝试浏览C11标准并没有发现任何东西,但是我在C中的经验比在C ++中小得多,因此我很容易错过一些东西。
c pointers memory-model undefined-behavior memory-segmentation