如果我有两个变量a i b都是int,而一个指针ptr指向& b。如果我们增加ptr ++,它应该指向a,如果我没错。我认为这是可能的,因为当编译一个i b在堆栈中而b有4个字节小于a。但是当我在下一行打印指针时,我只得到地址。 代码:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a = 52;
int b = 12;
int *ptr;
ptr = &b;
printf("%d\n",*ptr);
ptr++;
printf("\n%d",*ptr);
return 0;
}
但如果我把printf(“%d”,&amp; a);然后最后printf打印好,它打印a的值 代码:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a = 52;
int b = 12;
printf("%d\n",&a);
int *ptr;
ptr = &b;
printf("%d\n",*ptr);
ptr++;
printf("\n%d",*ptr);
return 0;
}
答案 0 :(得分:2)
编译器可以按照它在堆栈中选择的任何顺序自由排列局部变量。事实上,C标准甚至没有提到堆栈。这是编译器留下的实现细节。
添加看似无关的代码行可能导致编译器决定以不同于没有附加代码的顺序将变量放在堆栈上。因此,在编写代码时,您无法依赖此行为。这样做是undefined behavior,您已经体验过。
此外,对不属于同一数组的变量执行指针运算也是未定义的行为。
答案 1 :(得分:0)
C11标准草案n1570:
6.5.2.4后缀增量和减量运算符
2
[...]参见附加算子和复合赋值的讨论 有关约束,类型和转换以及操作对其影响的信息 指针。[...]
6.5.6加法运算符
7
出于这些运算符的目的,指向不是元素的对象的指针 数组的行为与指向长度为1的数组的第一个元素的指针相同 对象的类型作为其元素类型。
8
[...]如果两个指针 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不得产生溢出;否则, 行为未定义。如果结果指向一个超过数组对象的最后一个元素的那个,那么 不得用作被评估的一元*运算符的操作数。
在ptr = &b;
和ptr++;
之后,在ptr
中解除引用printf("\n%d",*ptr);
是未定义的行为。
答案 2 :(得分:-1)
您无法保证a
和b
变量存储在内存附近的任何位置,并且尝试“旅行”并且#34;通过指针增量从一个到另一个,并依赖于结果。你正在做的是进入未定义行为的领域,你不应该这样做。