简体   繁体   English

将数组作为指针和值传递给函数

[英]Pass array to a function as a pointer and value

What is the deference between passing array this way:以这种方式传递数组之间的差异是什么:

static char arr[N];

void func(void *buf, size_t size) {
    // ...
}

int main(void) {
    func(arr, N);

    // ...
}

And this way:这样:

// ...

int main(void) {
    func(&arr, N);

    // ...
}

Is there any deference in those listings?这些列表中有任何尊重吗? It seems that the 2nd version passes an array as void ** , but is it really so?似乎第二个版本将数组作为void **传递,但真的如此吗?

The first is correct and the second is wrong or at least very questionable.第一个是正确的,第二个是错误的,或者至少是非常值得怀疑的。

arr when used in an expression or passed to a function, gets adjusted to a pointer to the first element. arr在表达式中使用或传递给函数时,会调整为指向第一个元素的指针。 So it turns equivalent to char* .所以它相当于char*

In the second example, &arr is one of the few exceptions to this "array decay" rule.在第二个例子中, &arr是这个“数组衰减”规则的少数例外之一。 Instead of a pointer to the first element, we get a pointer to the whole array, type char(*)[N] .我们得到的不是指向第一个元素的指针,而是指向整个数组的指针,类型为char(*)[N] This type is not compatible with char* , so if you would attempt to cast the void* buf to a char* inside the function, the second example causes a subtle bug.此类型与char*不兼容,因此如果您尝试将void* buf转换为函数内的char* ,则第二个示例会导致一个微妙的错误。

The reason why the second example compiles at all is because void* (and only that type, not void** ) is a special pointer type that can be converted to/from any other pointer to object.第二个示例完全编译的原因是因为void* (并且只有那个类型,而不是void** )是一种特殊的指针类型,可以转换为/从任何其他指向对象的指针。 Should you change the function to您是否应该将功能更改为

void func(char *buf, size_t size)

Then func(&arr, N);然后func(&arr, N); gives the expected compiler diagnostic "passing argument 1 of 'func' from incompatible pointer type".给出预期的编译器诊断“从不兼容的指针类型传递‘func’的参数 1”。

Now as it happens, if you write the function like this现在碰巧,如果你这样写函数

void func(void *buf, size_t size) {
    char* ptr = buf;
    for(int i=0; i<size; i++)
    {
      printf("%c ", ch[i]);
    }
}

It will most likely work for either version, because the address of the first item ( char* ) is the same as the address of the array ( char(*)[N] ).它很可能适用于任一版本,因为第一项的地址 ( char* ) 与数组的地址 ( char(*)[N] ) 相同。 Also, C's peculiar type system allows us to access a memory location of some type through an array or struct of items of that same type ("the strict aliasing rule").此外,C 的特殊类型系统允许我们通过数组或相同类型项的结构访问某种类型的内存位置(“严格的别名规则”)。

Best practices:最佳实践:

  • Use the first version.使用第一个版本。
  • Avoid the use of void* when possible, since they are type unsafe.尽可能避免使用void* ,因为它们是类型不安全的。
  • Be as explicit with types as you can and don't rely on implicit type conversions.尽可能明确地使用类型,不要依赖隐式类型转换。

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

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