我的C代码中有一个奇怪的结果

时间:2014-06-23 18:47:52

标签: c arrays

我在C中有以下代码:

int arr[] = {1,7,4,2,5,8};
int x = (&(arr[arr[1] - arr[4]]) - arr);

当我运行此代码时,则x = 2。

但如果我这样做:

int arr[] = {1,7,4,2,5,8};
int a = &(arr[arr[1] - arr[4]]);
int b = arr;
int x = a-b;

他们x = 8。

为什么我会得到不同的值?

4 个答案:

答案 0 :(得分:4)

在您的情况下,8等于2 * sizeof( int )

在第一个代码片段中,使用指针算术,而在第二个代码snipeet中,使用普通算术和整数。

在此表达式中

&(arr[arr[1] - arr[4]]) - arr

你处理指针。在这两个地址(&(arr[arr[1] - arr[4]])arr)之间,数组中有two个元素,第一个代码段显示了这些地址之间的元素数量。但是,它们占用的内存大小等于'8,第二个代码片段显示为。

考虑一个简单的例子,它会更清楚

int a[2];

sizeof(a)等于8,即2 * sizeof(int)。 而sizeof( a ) / sizeof(int )等于2.它与表达式

的值相同
( a + 2 ) - a

答案 1 :(得分:2)

int b = arr;

这是一个错误(更确切地说,约束违规)。由于arr是一个数组表达式,因此在包括这个表达式的大多数上下文中,它隐式转换为第一个元素的地址。因此,在隐式转换之后,expersion arr的类型为int *。

由于同样的原因,a的初始化无效。

没有从int*int的隐式转换。

您的编译器可能会将这种隐式转换实现为扩展(它实际上是一个不再定义的非常古老的C功能),但如果它符合要求,它必须至少发布一个警告信息。

在您的第一个代码块中,您需要减去两个int*值,这两个值分别指向位置2 int。指针算术是根据数组索引定义的。

在你的第二个(无效)代码块中,如果,编译器允许你在int*对象中存储int值,它可能会存储原始内存地址。根据系统使用的寻址方案,并且取决于int的大小(系统上可能是4个字节),减法可能有效地计算差异,以字节为单位两个指针之间。

如果您在编译此代码时看到警告,您应该注意它们,并且在询问时您应该明确提及它们。如果您没有看到警告,您应该了解如何鼓励编译器警告错误的代码。

如果您真的想要计算两个地址之间的字节距离,可以将两个指针都转换为char*

int arr[] = {1,7,4,2,5,8};
int *p1 = &arr[0];
int *p2 = &arr[2];
char *cp1 = (char*)p1;
char *cp2 = (char*)p2;
printf("p2 - p1 = %d\n", (int)(p2 - p1));
printf("cp2 - cp1 = %d\n", (int)(cp2 - cp1));

第一行应打印2;第二个应打印2 * sizeof (int)的值。

答案 2 :(得分:1)

在第一个中,arr是一个指针。在第二个中,b是一个int。

在第一个中,减法结果为2,因为差异是数组中的两个点。

在第二个中,减法结果为8,因为数组中的每个点占用4个字节的内存。 4 * 2 = 8。

答案 3 :(得分:0)

使用指针进行算术运算时,结果是类型数组的单位数。

使用整数进行算术运算时,结果是字面数字差异。