这个C程序出现了格式错误警告。

4

我正在尝试编译这个程序,但希望在没有警告的情况下进行。

#include<stdio.h>
int main()
{
    int arr[] = {1,2,3};
    printf("value1 = %d value2 %d\n", *(&arr+1), *(arr+1));//here is the warning
    return 0;
}

但是我收到了编译时警告。
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat]

我在一台64位Ubuntu机器上编译我的程序,使用的是gcc版本4.6.3(Ubuntu/Linaro 4.6.3-1ubuntu5)编译器。


*(&arr+1) --> 获取指向整型数组的指针 arr 的地址(作为一维三元素整型数组的指针),加上一维三元素整型数组的大小偏移,然后进行解引用操作以获取一个三元素整型数组,随后将其转换为指向整型的指针(该指针指向 arr 原始开头的第四个整型,即指向从 arr 地址开始的第二个整型数组的第一个整型)。 - Dmitri
3个回答

6

&arr接收数组的地址,它是一个数组指针(不要与指向第一个元素的指针混淆)。它的类型为int(*)[3]

然后您对此数组指针进行指针算术运算。由于它指向一个包含3个整数的数组,&arr + 1将意味着“加上整个数组的大小”,并且您最终会指向声明的数组之外,这没有任何意义。

然后您使用*获取数组指针的内容。然后您将再次获得数组本身。当您在表达式中使用数组时,它会衰减为指向其第一个元素的指针int*。它与int不兼容,因此出现错误。

我猜您可能尝试执行&arr [0] + 1arr + 1,它们都表示同样的意思。


是的,我也在尝试做同样的事情。我正在寻找一个适当的解释来解决这个警告。*(&arr[0]) 也会给我同样的警告。 - mrigendra
我错误地将第二个参数解释为*(arr+1),导致出现了警告。 - mrigendra

1
逐步操作:

arr 的类型为 "array 3 of int"。

int arr[] = {1,2,3};

&arr的类型是“指向包含3个int元素的数组的指针”。

&arr + 1也是类型为“指向包含3个int元素的数组的指针”。

*(&arr+1)的类型是“包含3个int元素的数组”。

当一个数组被传递给一个函数时,会发生一种转换。传递的是数组第一个元素的地址,而不是整个数组本身。在这种情况下,它的类型是int *

"%d"期望匹配的int类型,因此编译器发出警告:

format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’


1

arr 的类型是 int (*)[3],而不是 int *。虽然在大多数情况下,数组名会衰减为指向第一个元素的指针,也就是你的第二个例子中的 &arr[0],这正是为什么你的 value2 正常输出的原因。

但是,当 arr& 运算符的参数时,它不会衰减。因此,&arr+1 的值与 &arr[0]+3 的值相等。这是因为 sizeof &arr 等于 sizeof (int (*)[3]),其结果为 3。因此,在尝试输出 value1 时,实际上访问的是 &arr[3],其类型为 int *。它是 &arr[3],而不是 arr[3],因为当你解引用具有 int (*)[3] 类型的东西时,它会衰减为指针。

因此,正如你所看到的,警告确实在试图防止潜在的错误。

另请参阅: 异常情况下数组不会衰减为指针?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接