简体   繁体   English

为什么我不必给函数提供数组的地址

[英]Why don't I have to give the function the address of the array

Hi I'm new to C and learning about pointers. 嗨,我是C的新手并且学习指针。 I'm writing a simple recursive function to test it where it takes parameters int *a and int size . 我正在编写一个简单的递归函数来测试它需要参数int *aint size In my main method, I send print_array the address of the first character of my array using the & beforehand. 在我的main方法中,我使用& print_array发送print_array我的数组的第一个字符的地址。

This doesn't seem to work, I get given an "incompatible pointer types" error at compilation. 这似乎不起作用,我在编译时得到“不兼容的指针类型”错误。 I understand that I can remove the & and the program works fine. 我知道我可以删除&和程序工作正常。 I have a question: 我有个问题:

Why can't I pass in the memory address of my_array from main with a &? 为什么我不能通过&传递my_array的内存地址? Shouldn't I be able to just give the function the memory address of first element of array and it can deal with the rest? 我不应该只给函数数组的第一个元素的内存地址,它可以处理其余的吗?

Thanks, hope this question wasn't too noob. 谢谢,希望这个问题不是太棒了。

 #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;

}

Yes, you can give the function the address of the first element, and let it deal with the rest. 是的,您可以为函数提供第一个元素的地址,并让它处理其余元素。 You could do that as either: 您可以这样做:

print_array(my_array, 20);

...or: ...要么:

print_array(&my_array[0], 20);

Unfortunately, while &my_array is legal code, it produces a pointer to the entire array, rather than a pointer to the first element of the array. 不幸的是,虽然&my_array是合法代码,但它会生成一个指向整个数组的指针,而不是指向数组第一个元素的指针。 Those have the same address, but different types, which is what's causing the error. 那些具有相同的地址,但是不同的类型,这是导致错误的原因。

The type of a pointer determines (among other things) how arithmetic on that pointer will work. 指针的类型决定(除此之外)该指针上的算术将如何工作。 In your case, print_array prints the first int in the array, then adds one to the pointer. 在您的情况下, print_array打印数组中的第一个int,然后将一个添加到指针。 Since it's a pointer to int, that addition actually adds the size of an int to the address in the pointer. 由于它是指向int的指针,因此该添加实际上将int的大小添加到指针中的地址。

If you used a pointer to the entire array, then adding one would instead add the size of the entire array to the address. 如果您使用指向整个数组的指针,那么添加一个指针会将整个数组的大小添加到地址中。 For example, let's assume 4-byte ints and that my_array has a base address of 1000. In this case, my_array+1 will yield 1004, so it holds the address of the second int in the array (just as you undoubtedly wanted). 例如,假设4字节的整数和my_array的基地址为1000.在这种情况下, my_array+1将产生1004,因此它保存数组中第二个int的地址(正如您无疑想要的那样)。 By contrast, &my_array will take the address of the entire array, with the type "pointer to array of 20 ints". 相比之下, &my_array将获取整个数组的地址,类型为“指向20个整数的数组的指针”。 When you add one to it, that will add 1 * the size of the pointed-to type to the address, so you'll get 1080 (ie, the entire array is 20 * 4 = 80 bytes). 当你向它添加一个时,它会将指向类型的大小加1到地址,所以你将得到1080 (即整个数组是20 * 4 = 80字节)。 This is obviously not what you wanted--instead of x+1 pointing to the second item in the array, it now points past the end of the array, and attempting to dereference the pointer will give undefined behavior. 这显然不是你想要的东西-而不是x+1指向数组的第二个项目,它指向过去的数组的结尾,并试图取消引用指针会给未定义的行为。

So, just switch to one of the forms above ( my_array or &my_array[0] ). 所以,只需切换到上面的一个表单( my_array&my_array[0] )。 As a more general point, realize that the name of an array evaluates as a pointer to the first element of the array under most circumstances--the notable exceptions being when you use the name of the array as a the operand of either the sizeof operator or the address-of operator (as you did here). 更一般的观点是,在大多数情况下,要意识到数组的名称作为指向数组第一个元素的指针进行计算 - 值得注意的例外是当您使用数组的名称作为sizeof运算符的操作数时或运营商的地址(就像你在这里所做的那样)。 In these two cases, the name of the array still refers to the entire array instead of a pointer to the first element. 在这两种情况下,数组的名称仍然引用整个数组而不是指向第一个元素的指针。

Your function needs a pointer to an int , specifically the address of the first (0th) element of the array. 您的函数需要一个指向int的指针,特别是数组的第一个(第0个)元素的地址。

By calling print_array(&my_array, 20); 通过调用print_array(&my_array, 20); , you're trying to pass the address of the entire array, a value of type int(*)[20] , which is different than int* . ,你试图传递整个数组的地址,类型为int(*)[20] ,它与int*不同。 It points to the same memory location, but it's of a different type. 它指向相同的内存位置,但它是不同的类型。

To pass the address of the first element, you can write: 要传递第一个元素的地址,您可以编写:

print_array(&my_array[0], 20);

or, equivalently: 或者,等效地:

print_array(my_array, 20);

The latter works because, in most but not all contexts, the name of an array is implicitly converted to a pointer to its first element. 后者的工作原理是,在大多数但不是所有上下文中,数组的名称被隐式转换为指向其第一个元素的指针。

The relationship between arrays and pointers in C and C++ can be confusing. C和C ++中数组和指针之间的关系可能令人困惑。 Recommended reading: Section 6 of the comp.lang.c FAQ 推荐阅读: comp.lang.c FAQ的第6部分

Because arrays automatically decay to pointers, the following was extracted from the n1570 draft 因为数组会自动衰减为指针,所以从n1570草案中提取以下内容

6.3.2 Other operands 6.3.2其他操作数

6.3.2.1 Lvalues, arrays, and function designators 6.3.2.1左值,数组和函数指示符

  1. 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. 除非它是sizeof运算符, _Alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则将具有类型''数组类型''的表达式转换为表达式输入''指向类型'的指针,指向数组对象的初始元素,而不是左值。 If the array object has register storage class, the behavior is undefined. 如果数组对象具有寄存器存储类,则行为未定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM