“地址” (&) 一个被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);
}
prints:
$ ./a.out
1 1 1
1 0 0
我不明白为什么第二行以 1
开头。
I am a teaching assistant of a introductory programming course, and some students made this type of error:
char name[20];
scanf("%s",&name);
which is not surprising as they are learning... What is surprising is that, besides gcc warning, the code works (at least this part). I have been trying to understand and I wrote the following code:
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");
}
Compiling and executing:
$ 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
Can anyone explain why they are not different?
I suspect it is because I cannot get the address of an array (as I cannot have & &x
), but in this case the code should not compile.
Edit: I know that an array by itself is the same as the address of the first element, but this is not related to this problem, I think. For example:
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);
}
prints:
$ ./a.out
1 1 1
1 0 0
I don't understand why the second line begins with 1
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在您的示例中,数组
test
是一个由 50 个int
组成的块。所以它看起来像这样:当您将一元
&
运算符应用于数组时,您将获得数组的地址。就像你将它应用到其他任何事情上一样,真的。因此,&test
是一个指向 50 个ints
块的指针:指向 50 个 ints 数组的指针的类型为
int (*)[ 50]
- 这是&test
的类型。当您在任何不是
sizeof
或一元-&
运算符的操作数的地方使用名称test
时,就会对它进行求值指向其第一个元素的指针。因此,您传递给foo()
的test
的计算结果为指向test[0]
元素的指针:您可以看到这两者都是指向相同的地址 - 尽管
&test
指向整个数组,而test
指向数组的第一个元素(仅显示在不同的数组中)这些值所具有的类型)。In your example, the array
test
is a block of 50ints
. So it looks like this:When you apply the unary
&
operator to an array, you get the address of the array. Just like when you apply it to anything else, really. So&test
is a pointer that points to that block of 50ints
:A pointer that points to an array of 50 ints has type
int (*)[50]
- that's the type of&test
.When you just use the name
test
in any place where it's not the operand of either thesizeof
or unary-&
operators, it is evaluated to a pointer to its first element. So thetest
that you pass tofoo()
evaluates to a pointer to thetest[0]
element:You can see that these both are pointing to the same address - although
&test
is pointing to the whole array, andtest
is pointing to the first element of the array (which only shows up in the different types that those values have).事实上,它们是不同的,至少不是同一类型。
但在C语言中,数组的地址与数组的地址相同。
数组中的第一个元素,这就是为什么“它们没有不同”,基本上,它们指向同一件事。
Actually, they are different, they don't have the same type at least.
But in C, the address of the array is the same as the address of the
first element in the array that's why "they are not different", basically, they point to the same thing.
如果您定义像
name
这样的数组,则可隐式转换为
char*
,但&name
的类型为char (*) [20]
(指向 20 个字符的数组的指针)。地址是相同的。检查
(&name + 1)
的地址。它的&name
形式与sizeof(char [20])
不同。If You define an array like
name
is implicitly convertible tochar*
, but&name
is of the typechar (*)[20]
(a pointer to an array of 20 characters). The addresses are the same.Check the address of
(&name + 1)
. It differs form&name
by thesizeof(char [20])
.在大多数情况下,数组的名称计算为其初始元素的地址。两个例外是当它是
sizeof
或一元&
的操作数时。一元
&
给出其参数的地址。数组的地址与其初始元素的地址相同,因此(void*)&array == (void*)array
始终为 true。array
当转换为指向其初始元素的指针时,其类型为T *
。&array
的类型为T (*)[n]
,其中n
是数组中元素的数量。因此,The name of an array, in most circumstances, evaluates to the address of its initial element. The two exceptions are when it is the operand of
sizeof
or the unary&
.The unary
&
gives the address of its argument. The address of an array is the same as the address of its initial element, so(void*)&array == (void*)array
will always be true.array
, when converted to a pointer to its initial element, has the typeT *
. The type of&array
isT (*)[n]
, wheren
is the number of elements in the array. Thus,我相信这是 gcc 的优化。想一想。
&test
指向test
的地址test
指向test
或& 的第一个元素;test[0]
[0]
与*
相同(大部分)因此根据此
&test
可能与test
不同,但 gcc 对此进行了优化,因为此时没有额外的间接级别。I believe this is a gcc optimization. Think about it.
&test
points to the address oftest
test
points to the first element oftest
or&test[0]
[0]
is the same(for the most part) as*
So according to this
&test
could be different thantest
but gcc optimizes this away because there is no purpose of having an extra level of indirection at that point.