为什么我不必给函数数组的地址
Why don't I have to give the function the address of the array
嗨,我是 C 语言的新手,正在学习指针。我正在编写一个简单的递归函数来测试它接受参数 int *a
和 int size
的地方。在我的主要方法中,我预先使用 &
发送 print_array
我的数组第一个字符的地址。
这似乎不起作用,我在编译时收到 "incompatible pointer types" 错误。我知道我可以删除 & 并且程序运行正常。我有一个问题:
为什么我不能用&从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;
}
是的,你可以把第一个元素的地址给函数,让它处理剩下的。您可以这样做:
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,因此它保存数组中第二个整数的地址(只是正如你无疑想要的那样)。相比之下,&my_array
将获取整个数组的地址,类型为 "pointer to array of 20 ints"。当你向它加一时,这会将 1 * 指向类型的大小添加到地址,所以你会得到 1080
(即,整个数组是 20 * 4 = 80 字节)。这显然 不是 你想要的——而不是 x+1
指向数组 中的第二个项目 ,它现在指向数组末尾,并尝试取消引用指针将产生未定义的行为。
因此,只需切换到上述形式之一(my_array
或 &my_array[0]
)。作为更一般的一点,要意识到在大多数情况下,数组名称的计算结果是指向数组第一个元素的指针——值得注意的例外是当您将数组名称用作 [= 的操作数时20=] 运算符或地址运算符(就像您在此处所做的那样)。在这两种情况下,数组的名称仍然引用整个数组而不是指向第一个元素的指针。
由于数组自动衰减为指针,以下摘自n1570草案
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators
- Except when it is the operand of the
sizeof
operator, the _Alignof
operator, or the
unary &
operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. If the array object has
register storage class, the behavior is undefined.
您的函数需要一个指向 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 节
嗨,我是 C 语言的新手,正在学习指针。我正在编写一个简单的递归函数来测试它接受参数 int *a
和 int size
的地方。在我的主要方法中,我预先使用 &
发送 print_array
我的数组第一个字符的地址。
这似乎不起作用,我在编译时收到 "incompatible pointer types" 错误。我知道我可以删除 & 并且程序运行正常。我有一个问题:
为什么我不能用&从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;
}
是的,你可以把第一个元素的地址给函数,让它处理剩下的。您可以这样做:
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,因此它保存数组中第二个整数的地址(只是正如你无疑想要的那样)。相比之下,&my_array
将获取整个数组的地址,类型为 "pointer to array of 20 ints"。当你向它加一时,这会将 1 * 指向类型的大小添加到地址,所以你会得到 1080
(即,整个数组是 20 * 4 = 80 字节)。这显然 不是 你想要的——而不是 x+1
指向数组 中的第二个项目 ,它现在指向数组末尾,并尝试取消引用指针将产生未定义的行为。
因此,只需切换到上述形式之一(my_array
或 &my_array[0]
)。作为更一般的一点,要意识到在大多数情况下,数组名称的计算结果是指向数组第一个元素的指针——值得注意的例外是当您将数组名称用作 [= 的操作数时20=] 运算符或地址运算符(就像您在此处所做的那样)。在这两种情况下,数组的名称仍然引用整个数组而不是指向第一个元素的指针。
由于数组自动衰减为指针,以下摘自n1570草案
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators
- Except when it is the operand of the
sizeof
operator, the_Alignof
operator, or the unary&
operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
您的函数需要一个指向 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 节