C数组如何“本身就是命名变量”?

时间:2019-02-10 01:35:34

标签: c language-concepts

Peter Van Der Linden撰写的《专家C编程:Deep C的秘密》一书的第103页上有一张表格,介绍了数组与指针之间的区别。

我不太了解的一个问题–直接引用:

  

指针:通常指向匿名数据

     

数组:本身就是一个命名变量

这是什么意思?由于您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>

int main(void){
  int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  int *y = malloc(9*sizeof(int));
  printf("sizeof(x) == %zu\n", sizeof(x));
  printf("&(x[2]) = %p\n", (void*)&(x[2]));
  printf("sizeof(y) == %zu\n", sizeof(y));
  printf("&(y[2]) = %p\n", (void*)&(y[2]));
  return 0;
}

输出:

sizeof(x) == 36
&(x[2]) = 0x7fffffffe5f8
sizeof(y) == 8
&(y[2]) = 0x800e18008

我不知道y的命名变量比x少。

4 个答案:

答案 0 :(得分:3)

我同意,作者在这里可能会更加清楚。指针本身也是一个命名变量,但是如果它指向一个数组,则它没有有关数组长度的任何信息。实际上,它不知道它指向的是数组。即使为p[100]分配了单个p或其他数据类型的地址,语法int仍然有效(尽管未定义)。

这就是为什么将数组作为参数传递给函数时,原因是:

  • 带有“长度”参数,该参数信任调用代码以正确提供
  • 以前哨值终止(例如字符串的空终止符)

要更清楚地证明这种区别,请尝试以下操作:

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

我收到以下编译警告:

'=': 'int *' differs in levels of indirection from 'int (*)[3]'

但是,如果更改ptr指向arr的第一个元素(当arr衰减到指针时会发生这种情况),就没有问题:

ptr = &arr[0];

答案 1 :(得分:2)

我认为作者尝试要说的是,数组的元素形成一个命名为“对象”(根据C标准的定义),而指针的元素通常来自未命名的“对象”。

有关对象的定义,请参见C11§3.15,有关对象的存储期限的信息请参见§6.2.4。

有很多 糟糕的编程书籍,而C是一种古老而流行的语言,它比大多数语言都多。

答案 2 :(得分:0)

我们基本上是在猜测别人的意思。但是,这是我最好的猜测。

  int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  int *y = malloc(9*sizeof(int));

x是数组的名称。

y是指针的名称。它指向的数组没有名称。

答案 3 :(得分:-2)

实际上,您编写的是两种声明数组的方法。当然,第一个是更常规和更容易的。作者试图告诉我们的是,数组是一个命名变量,因为您需要该命名变量来访问数组的所有元素。要到达下一个元素,依此类推,您需要放置索引号。因此,将第一个元素的“地址”乘以索引号,您将获得所需的元素。如果我们分析它,则array [0]指向第一个元素,它本身就是一个指针。

要正确理解指针,请考虑以下问题:

int *y = malloc(sizeof(int));
int x[] = {1,2,3};
y = &x[2]; //points to an anonymous data because pointer "y" doesn't "know" the 
           //variable "x", only it's memory address
y = &x[0]; //points to the first element of x