数组的名字是C语言中的指针吗? 如果不是,数组的名称和指针变量之间的区别是什么?
当前回答
下面的示例提供了数组名和指针之间的具体区别。假设你想用给定的最大维数表示一条一维线,你可以用数组或指针来实现:
typedef struct {
int length;
int line_as_array[1000];
int* line_as_pointer;
} Line;
现在让我们看看下面代码的行为:
void do_something_with_line(Line line) {
line.line_as_pointer[0] = 0;
line.line_as_array[0] = 0;
}
void main() {
Line my_line;
my_line.length = 20;
my_line.line_as_pointer = (int*) calloc(my_line.length, sizeof(int));
my_line.line_as_pointer[0] = 10;
my_line.line_as_array[0] = 10;
do_something_with_line(my_line);
printf("%d %d\n", my_line.line_as_pointer[0], my_line.line_as_array[0]);
};
这段代码将输出:
0 10
这是因为在do_something_with_line函数调用中,对象被复制,因此:
指针line_as_pointer仍然包含它所指向的相同地址 数组line_as_array被复制到一个没有超出函数作用域的新地址
因此,当你直接将数组输入到函数时,数组不是由值给出的,当你将它们封装在结构中时,它们是由值给出的(即复制),这概述了与使用指针实现相比,在行为上的主要区别。
其他回答
下面的示例提供了数组名和指针之间的具体区别。假设你想用给定的最大维数表示一条一维线,你可以用数组或指针来实现:
typedef struct {
int length;
int line_as_array[1000];
int* line_as_pointer;
} Line;
现在让我们看看下面代码的行为:
void do_something_with_line(Line line) {
line.line_as_pointer[0] = 0;
line.line_as_array[0] = 0;
}
void main() {
Line my_line;
my_line.length = 20;
my_line.line_as_pointer = (int*) calloc(my_line.length, sizeof(int));
my_line.line_as_pointer[0] = 10;
my_line.line_as_array[0] = 10;
do_something_with_line(my_line);
printf("%d %d\n", my_line.line_as_pointer[0], my_line.line_as_array[0]);
};
这段代码将输出:
0 10
这是因为在do_something_with_line函数调用中,对象被复制,因此:
指针line_as_pointer仍然包含它所指向的相同地址 数组line_as_array被复制到一个没有超出函数作用域的新地址
因此,当你直接将数组输入到函数时,数组不是由值给出的,当你将它们封装在结构中时,它们是由值给出的(即复制),这概述了与使用指针实现相比,在行为上的主要区别。
数组名的行为类似于指针,指向数组的第一个元素。例子:
int a[]={1,2,3};
printf("%p\n",a); //result is similar to 0x7fff6fe40bc0
printf("%p\n",&a[0]); //result is similar to 0x7fff6fe40bc0
这两个print语句将为一台机器提供完全相同的输出。在我的系统中,它给出:
0x7fff6fe40bc0
数组名本身会产生一个内存位置,所以你可以像对待指针一样对待数组名:
int a[7];
a[0] = 1976;
a[1] = 1984;
printf("memory location of a: %p", a);
printf("value at memory location %p is %d", a, *a);
你还可以对指针做其他漂亮的事情(例如增加/减去偏移量),你也可以对数组做:
printf("value at memory location %p is %d", a + 1, *(a + 1));
在语言方面,如果C语言没有将数组公开为某种“指针”(学究地说,它只是一个内存位置)。它不能指向内存中的任意位置,也不能由程序员控制)。我们总是需要这样编码:
printf("value at memory location %p is %d", &a[1], a[1]);
当数组用作值时,它的名称表示第一个元素的地址。 当数组不用作值时,其名称代表整个数组。
int arr[7];
/* arr used as value */
foo(arr);
int x = *(arr + 1); /* same as arr[1] */
/* arr not used as value */
size_t bytes = sizeof arr;
void *q = &arr; /* void pointers are compatible with pointers to any object */
像这样声明的数组
int a[10];
为10个int类型分配内存。你不能修改a,但你可以用a做指针算术。
这样的指针仅为指针p分配内存:
int *p;
它不分配任何int型。你可以修改它:
p = a;
并像使用a一样使用数组下标:
p[2] = 5;
a[2] = 5; // same
*(p+2) = 5; // same effect
*(a+2) = 5; // same effect