“地址” (&) 一个被gcc忽略的数组/地址?

发布于 2024-09-02 06:27:08 字数 1269 浏览 6 评论 0原文

我是编程入门课程的助教,有些学生犯了这种类型的错误:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

回眸一遍 2024-09-09 06:27:09

在您的示例中,数组 test 是一个由 50 个 int 组成的块。所以它看起来像这样:

| int | int | ... | int |

当您将一元 & 运算符应用于数组时,您将获得数组的地址。就像你将它应用到其他任何事情上一样,真的。因此,&test 是一个指向 50 个 ints 块的指针:

(&test) -----------> | int | int | ... | int |

指向 50 个 ints 数组的指针的类型为 int (*)[ 50] - 这是 &test 的类型。

当您在任何不是 sizeof 或一元-& 运算符的操作数的地方使用名称 test 时,就会对它进行求值指向其第一个元素的指针。因此,您传递给 foo()test 的计算结果为指向 test[0] 元素的指针:

(test) -----------------\
                        v
(&test) -----------> | int | int | ... | int |

您可以看到这两者都是指向相同的地址 - 尽管 &test 指向整个数组,而 test 指向数组的第一个元素(仅显示在不同的数组中)这些值所具有的类型)。

In your example, the array test is a block of 50 ints. So it looks like this:

| int | int | ... | int |

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 50 ints:

(&test) -----------> | int | int | ... | int |

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 the sizeof or unary-& operators, it is evaluated to a pointer to its first element. So the test that you pass to foo() evaluates to a pointer to the test[0] element:

(test) -----------------\
                        v
(&test) -----------> | int | int | ... | int |

You can see that these both are pointing to the same address - although &test is pointing to the whole array, and test is pointing to the first element of the array (which only shows up in the different types that those values have).

初吻给了烟 2024-09-09 06:27:09

事实上,它们是不同的,至少不是同一类型。

但在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.

梦里°也失望 2024-09-09 06:27:09

如果您定义像 name 这样的数组,

char name[20];

则可隐式转换为 char*,但 &name 的类型为 char (*) [20](指向 20 个字符的数组的指针)。地址是相同的。

检查(&name + 1)的地址。它的 &name 形式与 sizeof(char [20]) 不同。

If You define an array like

char name[20];

name is implicitly convertible to char*, but &name is of the type char (*)[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 the sizeof(char [20]).

欲拥i 2024-09-09 06:27:09

在大多数情况下,数组的名称​​计算为其初始元素的地址。两个例外是当它是 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

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 type T *. The type of &array is T (*)[n], where n is the number of elements in the array. Thus,

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
时间你老了 2024-09-09 06:27:09

我相信这是 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 of test
  • test points to the first element of test or &test[0]
  • [0] is the same(for the most part) as *

So according to this &test could be different than test but gcc optimizes this away because there is no purpose of having an extra level of indirection at that point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文