基于C
中的以下片段int c1,c2;
printf("%d ",&c1-&c2);
Output : -1
printf("%d ",&c2 - &c1)
时,我得到1而不是任何随机值!为什么?printf("%d ",(int)&c1 - (int)&c2)
我是否将地址转换为整数值?这是否意味着存储为十六进制的地址的值现在转换为int然后减去?答案 0 :(得分:4)
1)获得int
。指向某物的指针减去指向某物的指针是一个整数值(类型ptrdiff_t
)。它告诉你有多少元素是指向同一个数组的两个指针。
2)由于两个指针没有指向同一个数组,因此差异未定义。可以获得任何价值。
3)是的。但是"十六进制"部分不正确。地址以位/二进制形式存储(如整数一样)。您的计划的解释会有什么变化。这与表示无关(hex / dec / oct /...).
答案 1 :(得分:1)
这里有多种未定义的行为。
如果我们转到草案C99标准部分6.5.6
添加运算符,它会说(强调我的):
当减去两个指针时,两个指针都应该指向 相同的数组对象,或者超过数组对象的最后一个元素; 结果是两个数组的下标的差异 元素。 结果的大小是实现定义的,以及它的结果 type(有符号整数类型)是中定义的ptrdiff_t 头。如果结果在该类型的对象中无法表示, 行为未定义。
虽然,你所拥有的是未定义的行为,因为指针不指向同一个数组的元素。
printf
ptrdiff_t
使用%td
时的正确格式说明符将是{{1}},因为您指定的格式说明符不正确,所以会给我们第二种未定义的行为。
答案 2 :(得分:0)
1)有些编译器会对格式错误的printf
参数发出警告,但作为可变参数函数,运行时无法检查参数是否为格式字符串指定的类型。任何不匹配都会发出未定义的行为,因为该函数会尝试将此类参数强制转换为不正确的类型。
2)你说结果应该是-4,但这不正确。只保证数组的指针连续对齐。您不能认为c2
位于(&c1 + 1)
。
3)(int)&c1
正在将c1
的地址转换为int
。一般来说,这仍然是未定义的行为,因为您不知道int
足以保存指针地址值。 (int
可能是64位芯片组上的32位)。您应该使用intptr_t
代替int
。
答案 3 :(得分:0)
1)空虚*只不过是一个地址。地址是一个数字(很长)。在那里,地址被隐式地转换为int。
2)在内存中,您的变量的存储顺序与输入的顺序不同 你的代码;)。此外,出于同样的原因:
int a[2];
a[0] = 3;
*(a + 1) = 5; // same that "a[1] = 5;"
此代码将放置" 5"在第二种情况下。因为它实际上会这样做:
*(a + 1 *sizeof(*a)) = 5;
3)十六进制是数字表示。它可以存储在int中!示例:
int a = 0xFF;
printf("%d\n", a); // print 255
我希望我已经回答了你的问题。