【问题标题】:Why is -x[ptr] always 0?为什么 -x[ptr] 总是 0?
【发布时间】:2017-10-12 15:07:20
【问题描述】:

我的代码:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int *pi;
    short *ps;

    pi = malloc(16 * sizeof *pi);
    ps = malloc(16 * sizeof *ps);
    pi += 8;
    ps += 8;
    ps = (short*) pi;
    *pi = 1000000;
    printf("*pi = %d,", *pi);
    printf("*ps = %hd\n", *ps);
    printf("before incrementing ps : ps = %p\n", ps);
    ps++;
    printf("after incrementing ps : ps = %p\n", ps);
    printf("*ps = %hd\n", *ps);
    *ps = 16;
    printf("after *ps = %hd -> *pi = %d\n", *ps, *pi);
    printf("ps - 1 = %p, -1 + ps = %p\n", ps - 1,-1 + ps);
    printf("*(ps - 1) = %hd, *(-1 + ps) = %hd\n", *(ps - 1), *(-1 + ps));
    printf("0[ps - 1] = %hd, 1[ps - 2] = %hd, ps[-1] = %hd\n", 0[ps - 1], 1[ps - 2], ps[-1]);
    printf("-1[ps] = %hd, -2[ps + 1] = %hd, -3[ps + 2] = %hd\n", -1[ps], -2[ps + 1], -3[ps + 2]);
    printf("-3[ps] = %hd, -3[ps + 1] = %hd, -3[ps + 3] = %hd,", -3[ps], -3[ps + 1], -3[ps + 3]);
    printf("-3[ps + 4] = %hd\n",-3[ps + 4]);
}
/* format string in printf was adjusted to increase readability */

我的输出:

*pi=1000000,*ps=16960
before incrementing ps:ps=0xbb9030
after incrementing ps:ps=0xbb9032
*ps=15
after *ps=16->*pi=1065536
ps-1=0xbb9030,-1+ps=0xbb9030
*(ps-1)=16960,*(-1+ps)=16960
0[ps-1]=16960,1[ps-2]=16960,ps[-1]=16960
-1[ps]=0,-2[ps+1]=0,-3[ps+2]=0
-3[ps]=0,-3[ps+1]=0,-3[ps+3]=0,-3[ps+4]=0

我读到a[b] 被定义为*(a+b)。因此,ps[-1]==*(ps-1)==*(-1+ps)==-1[ps]。但是,从输出中可以看出,虽然除了最后一个表达式之外的所有表达式都具有预期值(16960),但最后一个表达式的值是 0?

为什么会这样? -x[ps] 是否会产生未定义的行为,导致编译器只使用 0?

为了您的信息,我使用 gcc。 gcc -v 输出gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5)

【问题讨论】:

  • 您知道编译器忽略空格,不是吗?这段代码太难读,太无聊了,请解释你的确切问题并尝试在更简单的程序中重现它。另外,你知道1[x] is the same as x[1]吗?
  • 我不知道你在说什么或者这段代码应该实现什么。
  • @EugeneSh。这是一段用于试验指针算法的代码。
  • 这个实验在我看来更多关于可以用来执行指针算术的语法,这是一个有趣的话题,但你应该尽量坚持给定的语法,比如x[n]可读且直观。
  • 然后分离出让你困惑的代码段,并解释预期的和实际的行为。

标签: c pointers gcc


【解决方案1】:

一元否定 - 的优先级低于 []

所以-1[ps] 被评估为-(1[ps])

您还应该注意,指针运算仅在数组中定义:除了允许将指针设置(尽管不能取消引用)一个超出数组末尾的位置,或一个超出标量地址的位置的重要例外。

其他一切都很明显:尤其是您无法访问数组边界之外的内容。

【讨论】:

  • 另外,断言-x[ptr] 总是0 是错误的。因为一个简单的测试可以证明它不是真的。
  • @IharobAlAsimi 你是说输出底行的表达式为零仅仅是因为 malloc 分配了一块为零的内存吗?这不太可能,因为我已经多次运行代码。可以看到,甚至 3[ps + 4] 也在数组的范围内。
  • @IharobAlAsimi 好吧,我做了更多的实验,发现数组神秘地填充了0。
  • @user_194421: malloc 不必这样做。另一方面,calloc 确实如此。见stackoverflow.com/questions/1538420/…
  • @Bathsheba 但正如你所见,我使用了 malloc,并添加了一段代码来打印整个 malloced 内存。它被 0 填充,除了我分配了非零值的地方。
猜你喜欢
  • 2022-08-22
  • 1970-01-01
  • 2019-07-18
  • 2021-04-14
  • 2011-12-28
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
相关资源
最近更新 更多