您好我是C的新手并且学习指针。我正在编写一个简单的递归函数来测试参数int *a
和int size
的位置。在我的main方法中,我事先使用print_array
发送&
我的数组的第一个字符的地址。
这似乎不起作用,我得到了一个"不兼容的指针类型"编译时出错。我明白我可以删除&并且程序运行正常。我有一个问题:
为什么我无法通过&amp ;?传递来自main的my_array的内存地址?难道我不能给函数提供数组第一个元素的内存地址,它可以处理剩下的吗?
谢谢,希望这个问题不是太棒了。
#include <stdio.h>
#include <stdlib.h>
void print_array(int *a, int size){
if (size>0){
printf("%d\n", a[0]);
print_array(a+1, size-1);
}
}
int main(void){
int my_array[20];
int i;
for (i=0; i < 20; i++){
my_array[i] = rand() % 20;
}
/*the contents of the array*/
printf("The contents of the array\n");
for (i=0; i < 20; i++){
printf("%d\n", my_array[i]);
}
printf("The recursive method print\n");
print_array(&my_array, 20);
return EXIT_SUCCESS;
}
答案 0 :(得分:6)
是的,您可以为函数提供第一个元素的地址,并让它处理其余元素。您可以这样做:
print_array(my_array, 20);
...或:
print_array(&my_array[0], 20);
不幸的是,虽然&my_array
是合法代码,但它会生成指向整个数组的指针,而不是指向数组第一个元素的指针。那些具有相同的地址,但是不同的类型,这是造成错误的原因。
指针的类型决定(除此之外)该指针的算术运算方式。在您的情况下,print_array
打印数组中的第一个int,然后将一个添加到指针。由于它是指向int的指针,因此该添加实际上将int的大小添加到指针中的地址。
如果您使用指向整个数组的指针,那么添加一个指针会将整个数组的大小添加到地址中。例如,假设4字节的整数和my_array的基地址为1000.在这种情况下,my_array+1
将产生1004,因此它保存数组中第二个int的地址(正如您无疑想要的那样) )。相比之下,&my_array
将获取整个数组的地址,类型为“指向20个整数的数组的指针”。当你向它添加一个时,它会将指向类型的大小加1到地址,因此你将获得1080
(即整个数组是20 * 4 = 80字节)。这显然是不你想要的 - 而不是x+1
指向数组中的第二项,它现在指向数组的末尾,并且试图取消引用指针将给出未定义的行为。
因此,只需切换到上面的表单之一(my_array
或&my_array[0]
)即可。更一般的说法是,在大多数情况下,要意识到数组的名称作为指向数组第一个元素的指针来计算 - 值得注意的例外是当您使用数组的名称作为{{的操作数时1}}运算符或运算符地址(如此处所示)。在这两种情况下,数组的名称仍然引用整个数组,而不是指向第一个元素的指针。
答案 1 :(得分:2)
你的函数需要一个指向int
的指针,特别是数组的第一个(第0个)元素的地址。
通过调用print_array(&my_array, 20);
,您尝试传递整个数组的地址,类型int(*)[20]
的值与int*
不同。它指向相同的内存位置,但它的类型不同。
要传递第一个元素的地址,您可以写:
print_array(&my_array[0], 20);
或等同于:
print_array(my_array, 20);
后者的工作原理是,在大多数但不是所有的上下文中,数组的名称被隐式转换为指向其第一个元素的指针。
C和C ++中数组和指针之间的关系可能令人困惑。推荐阅读:comp.lang.c FAQ
的第6部分答案 2 :(得分:0)
因为数组会自动衰减为指针,所以从n1570草案中提取以下内容
6.3.2其他操作数
6.3.2.1左值,数组和函数指示符
- 除非是
醇>sizeof
运算符,_Alignof
运算符或者&
运算符的操作数。 一元{{1}}运算符,或者是用于初始化数组的字符串文字,一个包含的表达式 类型''数组''转换为类型为''指向类型'指针的表达式 到数组对象的初始元素,而不是左值。如果数组对象有 注册存储类,行为未定义。