将指针与不同数组进行比较以获得相等性是否是未指定的行为?

Fre*_*urk 16 c++ standards pointers unspecified-behavior

等于运算符对指针的关系运算符有语义限制:

==(等于)和!=(不等于)运算符具有与关系运算符相同的语义限制,转换和结果类型,除了它们的优先级和真值结果.[C++03§5.10p2]

关系运算符对比较指针有限制:

如果同一类型的两个指针p和q指向不是同一个对象的成员或同一个数组的元素或不同函数的不同对象,或者只有其中一个为null,则p <q,p的结果> q,p <= q,p> = q未指定.[§5.9p2]

这是一个由等式运算符"继承"的语义限制吗?

具体来说,给出:

int a[42];
int b[42];
Run Code Online (Sandbox Code Playgroud)

很明显,(a + 3)<(b + 3)是未指定的,但是(a + 3)==(b + 3)也未指定?

Joh*_*itb 16

语义op==op!=明确说明映射除了它们的真值结果.因此,您需要查看为其真值结果定义的内容.如果他们说结果未指定,那么它是未指定的.如果他们定义了特定的规则,那么它就不是.它特别说

相同类型的两个指针比较相等,当且仅当它们都为空时,都指向相同的函数,或者两者都表示相同的地址

  • +1:我完全赞同*的解释,除了他们的真值结果*.它**虽然是**可怕的标准:-) (6认同)
  • 引用的文本已被 [DR1652](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1652) 取代 (2认同)

Jer*_*fin 11

只要指针指向相同类型的对象,等于运算符(==!=)的结果就会产生指定的结果.给定两个指向同一类型的指针,恰好其中一个是真的:

  1. 两者都是空指针,它们相互比较相等.
  2. 两者都是指向同一对象的指针,它们相互比较相等.
  3. 它们是指向不同对象的指针,它们相互比较不相等.
  4. 至少有一个未初始化,并且未定义比较结果(事实上,比较本身可能永远不会发生 - 只是尝试读取指针以进行比较会产生未定义的行为).

在相同的约束条件(两个指针是到同一类型的对象)从排序操作符(结果<,<=,>,>=)仅指定如果两者是指向同一个对象,或以分离在相同阵列中的对象(和为此目的,一个的存储器"块"与分配malloc,new等,有资格作为阵列).如果指针引用不属于同一数组的单独对象,则结果未指定.如果一个或两个指针尚未初始化,则表明存在未定义的行为.

但尽管如此,在标准库的比较模板(std::less,std::greater,std::less_equalstd::greater_equal)都产生有意义的结果,即使当/如果内置运营商没有.特别是,它们需要产生总排序.因此,如果需要,可以进行排序,而不是使用内置的比较运算符(当然,如果其中一个或两个指针未初始化,行为仍未定义).


Ytt*_*ill 6

由于在一致性语义上存在混淆,因此这些是C++的规则.C使用完全不同的一致性模型.

  1. 未定义的行为是一个矛盾的术语,它意味着翻译不是你的程序,可以随心所欲.这通常意味着它可以生成代码,它也可以做任何它喜欢的事情(但这是一个演绎).如果标准表示行为未定义,则文本实际上对用户没有意义,因为删除此文本不会改变标准对翻译人员的要求.

  2. 生成错误的程序意味着除非另有说明,否则转换器的行为是严格定义的:它需要拒绝您的程序并发出诊断消息.这里的主要特例是单一定义规则,如果您违反了您的程序格式错误但不需要诊断.

  3. 实现定义要求翻译者包含明确指定行为的文档.在这种特殊情况下,未定义的行为可能是结果,但必须明确说明.

  4. 未指定是一个愚蠢的术语,这意味着行为来自一个集合.在这个意义上,定义良好只是一种特殊情况,其中允许的行为集只包含一个元素.未指定不需要文档,因此在某种意义上它也与没有文档定义的实现相同.

通常,C++标准不是语言标准,它是标准语言的模型.要生成实际标准,您必须插入各种参数.最容易识别的是实现定义的限制.

标准中存在一些愚蠢的冲突,例如,合法的翻译者可以拒绝每个看似很好的C++程序,因为您需要提供一个main()函数,但翻译者只支持1个字符的标识符.QOI或实施质量的概念解决了这个问题.它基本上说,谁在乎,没有人会因为它符合要求而购买该编译器.

从技术上讲,operator <指针指向不相关对象的未指定性质可能意味着:您将获得某种结果,无论是真还是假,但您的程序不会崩溃,但这不是未指定的正确含义,因此是一个缺陷:未指定对标准编写者施加负担来记录允许的行为集,因为如果集合是打开的,那么它等同于未定义的行为.

我实际上提出std::less了一个问题的解决方案,一些数据结构要求键完全有序,但指针并非完全有序operator <.在大多数使用线性寻址的机器上less都是相同的<,但是对lessx86处理器的操作可能更昂贵.