【问题标题】:== for pointer comparison== 用于指针比较
【发布时间】:2012-04-03 13:23:38
【问题描述】:

我引用了 Kernighan & Ritchie 的“The C Programming Language”:

任何指针都可以有意义地比较是否等于或不等于零。但是对于算术或与不指向同一数组成员的指针的比较,行为是未定义的。 (有一个例外:数组末尾之后的第一个元素的地址可用于指针运算。)

这是否意味着我不能依靠== 来检查不同指针的相等性?什么情况下这种比较会导致错误的结果?

【问题讨论】:

  • 如果您有不同类型的指针并且它们具有相同的值,那么它们指向相同的内存地址,您可能会遇到一些问题。但是无论如何,如果您绝对肯定内存布局是完全线性的,那么比较指针通常是可以的。否则,不行。想想 8086。

标签: c pointers comparison equality


【解决方案1】:

我想到的一个例子是哈佛架构,代码和数据的地址空间分开。在该架构的计算机中,编译器可以将常量数据存储在代码存储器中。由于两个地址空间是分开的,指向代码存储器中地址的指针可以在数值上等于数据存储器中的指针,而不指向相同的地址。

【讨论】:

  • 这个答案可以改写为“在不符合 ISO C 标准的 C 编译器中。”
  • 这个答案与 C 无关,因为对象和函数指针不能直接比较,而且它们之间的转换没有定义。如果没有特定于实现的技巧,就没有有意义的方法来比较函数指针和对象指针。正如 chazomaticus 所指出的,哈佛架构的编译器不可能将数据存储在代码段中。
  • @R.. 早在 90 年代初,我就使用过 8051 C 编译器,它可以让您将常量放入 code 内存中。我不记得它是否需要编译器扩展或者简单地声明一个 const 数组就可以了,但我记得能够获得指向 不同 类型内存的 char*const char*。还有一种特殊的指针可以让你在运行时指向一种内存或另一种内存,但它需要三个字节而不是通常的两个字节。这是不久前的事了,标准充其量是 C89。
  • 那不是 C 编译器。 C 允许 const char * 指向非 const 数据(这是正常用法,甚至有隐式转换),并且还允许 char * 指向 const 数据,只要它不用于修改该数据。指针的类型不允许改变它指向的位置。
  • 这不是“参差不齐”。那使用const 的目的与它的预期完全不同,并且破坏了使用const任何 程序。即使是标准库也不起作用(strlen 需要 const char * 并且无法测量非const 字符串的长度...)。
【解决方案2】:

相等运算符是为所有有效指针定义的,它唯一可以给出“误报”的情况是当一个指针指向数组末尾的一个元素,而另一个恰好指向(或指向凭借结构定义)到存储在内存中数组之后的另一个对象。

我认为您的错误是将 K&R 视为规范。请参阅 C99 标准(此处为好 html 版本:http://port70.net/~nsz/c/c99/n1256.html),6.5.9 中的相等运算符。比较未定义的问题仅适用于关系运算符(参见 6.5.8):

当比较两个指针时,结果取决于所指向对象在地址空间中的相对位置。如果两个指向对象或不完整类型的指针都指向同一个对象,或者都指向同一个数组对象的最后一个元素,它们比较相等。如果指向的对象是同一个聚合对象的成员,则指向稍后声明的结构成员的指针比较大于指向结构中较早声明的成员的指针,并且指向具有较大下标值的数组元素的指针比较大于指向同一数组的元素的指针具有较低的下标值。所有指向同一个联合对象成员的指针比较相等。如果表达式 P 指向数组对象的一个​​元素,而表达式 Q 指向同一数组对象的最后一个元素,则指针表达式 Q+1 比较大于 P。在所有其他情况下,行为未定义。

【讨论】:

  • 请注意,ISO/IEC 9899:1990 在比较函数指针和对象指针时没有指定结果。
  • -1 您声明 “为所有有效指针定义相等运算符”, 然后引用标准中与 完全相反的部分(请注意它说如果它们都指向同一个对象,则相等性评估为真;它确实说如果它们指向不同的对象,则相等性为假).
  • +1:参考规范的第一个答案。丹尼,我想你很困惑:引用的段落是关于关系比较,而不是平等比较。关于相等运算符的部分说:“两个指针比较相等当且仅当……它们都是指向同一个对象的指针……”。这应该是公认的答案。
  • @BlueRaja-DannyPflughoeft:我引用的文本是关于除相等运算符之外的运算符,我认为它可能是误解的来源。等式运算符不承认误报,除了我已经介绍的一种情况。
【解决方案3】:

我的解释如下:

short a[9];
int b[12];
short * c = a + 9;

这里可以这么说

c > a

因为c 通过指针运算从a 得到,

但不一定是这样

b == c

c <= b

或类似的东西,因为它们来自不同的数组,它们在内存中的顺序和对齐方式没有定义。

【讨论】:

    【解决方案4】:

    您不能使用指针比较来比较指向不同数组的指针。

    所以:

    int arr[5] = {1, 2, 3, 4, 5};

    int * p = &amp;arr[0];

    int anotherarr[] = {1, 2};

    int * pf = &amp;anotherarr[0];

    你不能做if (p == pf),因为ppf不指向同一个数组。这将导致未定义的行为。

    如果它们指向同一个数组,您可以依赖指针比较。

    我自己不确定算术情况。

    【讨论】:

      【解决方案5】:

      您可以使用来自不同数组的指针来执行 ==!=

      、>= 未定义。

      【讨论】:

        猜你喜欢
        • 2014-09-08
        • 2017-01-19
        • 1970-01-01
        • 2012-07-01
        • 2012-02-23
        • 2012-10-05
        • 2018-10-18
        相关资源
        最近更新 更多