C 数组如何成为“本身的命名变量”?
How is a C array a “named variable in its own right”?
在 Peter Van Der Linden 的书 “Expert C Programming: Deep C Secrets” 的第 103 页上有一个 table 关于数组和指针之间的区别.
一个问题我不是很明白——直接引用:
Pointer: Typically points to anonymous data
Array: Is a named variable in its own right
这是什么意思?由于您可以执行以下操作:
#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
更像是一个命名变量。
我同意作者在这里可以说得更清楚。指针本身也是一个命名变量,但如果它指向一个数组,它就没有关于数组长度的任何信息。事实上,它并不知道它指向的是一个数组。即使 p
被分配了单个 int
或其他数据类型的地址,语法 p[100]
仍然有效(尽管未定义)。
这就是为什么当数组作为参数传递给函数时,它是:
- 附带一个 "length" 参数,该参数相信调用代码会正确提供它
- 以标记值终止(如字符串的空终止符)
为了更清楚地展示这种区别,试试这个:
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];
我认为作者 试图 说的是数组的元素形成一个命名的 "object"(根据 C 标准的定义),而指针的元素通常来自未命名的 "object".
有关对象的定义,请参阅 C11 §3.15,有关对象存储持续时间的信息,请参阅 §6.2.4。
有很多很多蹩脚的编程书籍,而 C 是一种古老而流行的语言,它比大多数都多。
其实你写的是声明数组的两种方式。当然,第一个更传统也更容易。作者想告诉我们的是,数组是一个命名变量,因为你需要命名变量来访问数组的所有元素。要到达下一个元素等等,您需要放置索引号。所以,第一个元素的 "address" 乘以索引号,你就会得到想要的元素。如果我们分析的话,一个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
我们基本上是在猜测别人的意思。但这是我最好的猜测。
int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int *y = malloc(9*sizeof(int));
x
是数组名。
y
是一个指针的名字。它指向的数组没有名称。
在 Peter Van Der Linden 的书 “Expert C Programming: Deep C Secrets” 的第 103 页上有一个 table 关于数组和指针之间的区别.
一个问题我不是很明白——直接引用:
Pointer: Typically points to anonymous data
Array: Is a named variable in its own right
这是什么意思?由于您可以执行以下操作:
#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
更像是一个命名变量。
我同意作者在这里可以说得更清楚。指针本身也是一个命名变量,但如果它指向一个数组,它就没有关于数组长度的任何信息。事实上,它并不知道它指向的是一个数组。即使 p
被分配了单个 int
或其他数据类型的地址,语法 p[100]
仍然有效(尽管未定义)。
这就是为什么当数组作为参数传递给函数时,它是:
- 附带一个 "length" 参数,该参数相信调用代码会正确提供它
- 以标记值终止(如字符串的空终止符)
为了更清楚地展示这种区别,试试这个:
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];
我认为作者 试图 说的是数组的元素形成一个命名的 "object"(根据 C 标准的定义),而指针的元素通常来自未命名的 "object".
有关对象的定义,请参阅 C11 §3.15,有关对象存储持续时间的信息,请参阅 §6.2.4。
有很多很多蹩脚的编程书籍,而 C 是一种古老而流行的语言,它比大多数都多。
其实你写的是声明数组的两种方式。当然,第一个更传统也更容易。作者想告诉我们的是,数组是一个命名变量,因为你需要命名变量来访问数组的所有元素。要到达下一个元素等等,您需要放置索引号。所以,第一个元素的 "address" 乘以索引号,你就会得到想要的元素。如果我们分析的话,一个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
我们基本上是在猜测别人的意思。但这是我最好的猜测。
int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int *y = malloc(9*sizeof(int));
x
是数组名。
y
是一个指针的名字。它指向的数组没有名称。