下面的代码创建一个数组和一个指向它的指针。然后程序打印出两个变量的内容。奇怪的是,打印出的内存地址是相同的,即使它们不应该。 ptr
应包含array
的地址,而不是array
本身。有人可以解释一下吗?
#include <stdio.h>
int main() {
char array[] = "abcdefg";
char (*ptr)[] = &array;
printf("%p\n", array);
printf("%p\n", ptr);
}
答案 0 :(得分:1)
对于名为array
的任何数组,array
和&array
具有相同的值 - 数组的第一个元素的地址。只是他们的类型不同 - array
此处的类型为char *
,其中&array
的类型为char(*)[]
。
答案 1 :(得分:0)
例如,将数组视为char a[10];
当我们分配指针变量时,我们指定为char *ptr=a
我们也可以分配像ptr=&a[0];
这样两个语句相同,两个语句将引用数组的起始地址
答案 2 :(得分:0)
根据Eli Bendersky的Pointers to arrays in C:
考虑以下代码:
void test(int** p) { } int main() { int arr[] = {30, 450, 14, 5}; test(&arr); return 0; }
gcc
对此并不感到高兴,并发出警告:passing arg 1 of test from incompatible pointer type
。 C ++有更严格的类型 检查,让我们尝试通过g++
运行相同的代码。如 我们得到一个错误:cannot convert int (*)[4] to int** for argument 1 to void test(int**)
。那么这里的问题是什么?上面的代码有什么问题?好, 一切。它只是无效,没有任何意义。有些人会 认为它应该有效,因为这有效:
void test(int* p) { } int main() { int arr[] = {30, 450, 14, 5}; test(arr); return 0; }
但是这个特别有效,因为C编译器应该遵循 C标准,要求阵列&#34;衰变&#34;当指针时 用作左值。因此,指向数组的第一个元素的指针是 实际上通过测试,一切正常。
但是,第一个代码段是不同的。虽然数组名称可以 衰减成指针,数组的地址不会衰减成a 指向指针的指针。为什么要这样呢?它有什么意义呢? 如此处理数组?
有时会传递指针指针来修改指针 (简单的指针参数不能在这里工作,因为C传递值, 这只会允许修改指向的内容,而不是指针 本身)。这是一些虚构的代码(不会编译):
void test(int** p) { *p = malloc ... /* retarget '*p' */ } int main() { int arr[] = {30, 450, 14, 5}; int* ptr; /* Fine! ** test will retarget ptr, and its new value ** will appear after this call. */ test(&ptr); /* Makes no sense! ** You cannot retarget 'arr', since it's a ** constant label created by the compiler. */ test(&arr); return 0; }
指向数组的指针
请注意,可以稍微修改原始代码以使其成为可能 工作:
void test(int (*p)[4]) { (*p)[2] = 10; } int main() { int arr[] = {30, 450, 14, 5}; test(&arr); printf("%d\n", arr[2]); return 0; }
奇怪的类型测试现在接受什么?跟一个&#34;指向你好 array&#34;,C的无用功能之一。这就是C FAQ所具有的功能 说来:
2.12:如何声明指向数组的指针?
通常,你不想。当人们随便说一个指针时 一个数组,它们通常表示指向其第一个元素的指针。
虽然上一个代码段的测试功能可以编译并运行, 它没有多大用处,因为写起来要清楚得多:
void test(int* p) { p[2] = 10; } ... ... /* then call */ test(arr);
指针作为函数参数的主要用途是要么避免 按值传递整个结构,或修改指向的对象 指针。两者都是指向数组指针的无关需求。这里&#39; S 一个澄清片段:
int joe[] = {1, 2, 3, 4}; void test(int (*p)[4]) { /* Fine: assign to an element through the ** pointer. */ (*p)[2] = 10; /* Works, but won't be reflected in the ** caller since p was passed by value. */ p = &joe; /* Error: arrays can't be assigned. */ *p = joe; }
无论如何都不通过值传递数组,因此指向数组的指针是 没用就是为了这个目的。也不能修改数组 杀死第二个原因。
要回答这个问题,&array
等于array
的原因是因为array
是由编译器创建的常量标签,&#34;不是指针变量。因此,对于&#34; dereference&#34;实际上没有任何意义。 array
并且只要发生这种情况,编译器就会简单地返回array
本身的值。
答案 3 :(得分:-1)
array
没有地址,就像ptr
有地址一样。因为阵列总是指向相同的存储器位置,所以不需要将该存储器位置存储在某些其他存储器位置中。我无法取array
并获得char**
的临时(*char)[0] == 'a'
。
因此&array
的类型为char(*)[]
,并返回数组中第一个char
的位置。同样地,array
在指针上下文中使用时(也就是说,几乎无处不在,有几个例外),与&array
具有相同的效果,但具有不同的类型。这被称为&#34;阵列衰减&#34;。
What is array decaying?的更多信息。