“地址”(&)被忽略的数组/地址是gcc吗?
我是入门编程课程的助教,有些学生犯了这种错误:
char name[20]; scanf("%s",&name);
这并不奇怪,因为他们正在学习……令人惊讶的是,除了gcc警告之外,代码也起作用(至少这部分)。 我一直在努力理解,并编写了以下代码:
void foo(int *v1, int *v2) { if (v1 == v2) printf("Both pointers are the same\n"); else printf("They are not the same\n"); } int main() { int test[50]; foo(&test, test); if (&test == test) printf("Both pointers are the same\n"); else printf("They are not the same\n"); }
编译和执行:
$ gcc test.c -g test.c: In function 'main': test.c:12: warning: passing argument 1 of 'foo' from incompatible pointer type test.c:13: warning: comparison of distinct pointer types lacks a cast $ ./a.out Both pointers are the same Both pointers are the same
谁能解释为什么他们没有什么不同?
我怀疑是因为我无法获取数组的地址(因为我不能拥有& &x
),但在这种情况下代码不应该编译。
编辑:我知道数组本身与第一个元素的地址相同,但我认为这与此问题无关。 例如:
int main() { int a[50]; int * p = a; printf("%d %d %d\n", p == a, p == &a[0], &p[0] == a); printf("%d %d %d\n", p == &a, &p == a, &p == &a); }
打印:
$ ./a.out 1 1 1 1 0 0
我不明白为什么第二行以1
开头。
在您的示例中,数组test
是一个50个ints
的块。 所以它看起来像这样:
| int | int | ... | int |
将一元&
运算符应用于数组时,将获得该数组的地址。 就像你将它应用于其他任何东西一样,真的。 所以&test
是一个指向50个ints
块的指针:
(&test) -----------> | int | int | ... | int |
指向50个int的数组的指针具有int (*)[50]
类型 – 这就是&test
的类型。
当你在任何不是sizeof
或unary- &
operator的操作数的地方使用名称test
时,它被评估为指向其第一个元素的指针。 因此,传递给foo()
的test
将计算为指向test[0]
元素的指针:
(test) -----------------\ v (&test) -----------> | int | int | ... | int |
您可以看到这两者都指向相同的地址 – 尽管&test
指向整个数组,而test
指向数组的第一个元素(仅显示这些值具有的不同类型 )。
实际上,它们是不同的,它们至少没有相同的类型。
但是在C中,数组的地址与数组中第一个元素的地址相同,这就是为什么“它们没有不同”,基本上,它们指向同一个东西。
如果你定义一个像这样的数组
char name[20];
name
可以隐式转换为char*
,但&name
的类型为char (*)[20]
(指向20个字符的数组的指针)。 地址是一样的。
检查(&name + 1)
的地址。 它的forms&name
与sizeof(char [20])
。
在大多数情况下,数组的名称将计算其初始元素的地址。 两个例外是当它是sizeof
或一元&
的操作数时。
一元&
给出其论点的地址。 数组的地址与其初始元素的地址相同,因此(void*)&array == (void*)array
将始终为true。
当转换为指向其初始元素的指针时, array
的类型为T *
。 &array
的类型是T (*)[n]
,其中n
是数组中元素的数量。 从而,
int* p = array; // Works; p is a pointer to array[0] int* q = &array; // Doesn't work; &array has type int (*)[10] int (*r)[10] = &array; // Works; r is a pointer to array
我相信这是一个gcc优化。 想一想。
-
&test
指向test
地址 -
test
指向test
的第一个元素或&test[0]
-
[0]
与*
(大部分)相同*
所以根据这个&test
可能 &test
不同,但gcc优化了这一点,因为在这一点上没有额外的间接级别的目的。