【问题标题】:What's happening here? Pointer math messing up? [duplicate]这里发生了什么事?指针数学搞砸了? [复制]
【发布时间】:2019-05-08 02:24:08
【问题描述】:
    int i = 0, j = 0;

int *a , *b;

a = &i + 1;
b = &j;

printf(" %p \n ",a);
printf(" %p \n ",b);

if(a==b)
printf(" yo \n");

输出:

0x7ffda8e133a4

0x7ffda8e133a4

a 和 b 一样,printf 仍然不执行。

ideone link to this code

当我将 a 和 b 作为普通变量时,这很有效。 (int a, b;)

【问题讨论】:

  • 您能详细说明一下吗?这是否违反任何 C 标准?
  • 比较不指向同一数组元素(或超过数组末尾)的指针是未定义的。检查您的输出汇编代码,了解具体情况。
  • 未定义的行为表示未定义的行为,这意味着对于将要发生的事情没有标准。此外,您正在使用两个未初始化的变量 (int i, j)。
  • 我认为编译器正在进行编译时优化并删除这段代码。
  • @tkausl 不,不是。任何有效的指针(包括过去的结束)都可以进行相等比较。在 C 和 C++ 中都是如此。没有规定它们应该指向同一个对象(Carl Norum 将关系比较规则与相等比较规则混淆了)

标签: c


【解决方案1】:

ISO/IEC 9899:201x

§6.5.6 等式运算符:

  1. 两个指针比较相等当且仅当两者都是空指针,都是指向同一个对象的指针(包括指向对象的指针和开头的子对象)或函数, 两者都是指向同一个数组对象最后一个元素之后的指针,或者一个是指向一个数组对象末尾之后的指针,另一个是指向另一个数组对象开头的指针紧跟地址空间中的第一个数组对象。

但又一次:

  1. 出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为 1 且对象类型作为其元素类型的数组的第一个元素的指针的行为相同。

所以 ...ab 应该表现得与指向数组的指针相同,ij 在内存中碰巧彼此相邻...然后&i + 1 可以指向j (b) 的第一个“数组元素”的开头。嗯,这是一个很大的如果。我不会依赖那个。也许在打包的结构中。


@OmG

最后一个版本的代码对我有用! [初始化ij]

gcc 9.1 -O3,2 x printf() 然后ret

        sub     rsp, 24
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        lea     rsi, [rsp+12]
        mov     DWORD PTR [rsp+8], 0
        mov     DWORD PTR [rsp+12], 0
        call    printf                       ; <----------
        lea     rsi, [rsp+12]
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf                       ; <----------
        xor     eax, eax
        add     rsp, 24
        ret                                  ; <----------

godbolt Compiler Explorer, gcc 9.1

【讨论】:

  • 与没有 -O3 标志的代码相同。它在“yo” printf 中编译。那么 GCC 优化实现了这一点?
  • @AnupBuchke 请看一下这个问题的副本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
相关资源
最近更新 更多