当我想通过引用函数传递数组时,我不知道该选择什么。
void myFunction(int* data);
这两种情况之间是否存在差异或最佳编码方式:
myFunction(&data[0]);
或
myFunction(data);
答案 0 :(得分:4)
没有区别。数组(“适当”数组)会自动衰减指向其第一个元素的指针。
例如,假设您有
int my_array[10];
然后使用普通的my_array
将自动衰减为指向其第一个元素&my_array[0]
的指针。
正是这种数组到指针的衰减,使您可以对数组和指针使用指针算术和数组索引。对于my_array[i]
以上的数组,它等于*(my_array + i)
。指针也存在这种等效性:
int *my_pointer = my_array; // Make my_pointer point to the first element of my_array
然后,my_pointer[i]
也完全等于*(my_pointer + i)
。
出于好奇(以及在现实程序中您永远不应该做的事情),多亏了commutative property,像*(my_array + i)
这样的表达式也等于*(i + my_array)
,然后等于到i[my_array]
。
答案 1 :(得分:2)
一个数组,当作为参数传递给函数时,会自动衰减指向其第一个元素的指针。因此,将data
或&data[0]
传递给函数是完全等效的。
从可读性的角度来看,我会选择前者。读者可以清楚地知道,该函数可能在整个数组上运行,而不仅仅是在一个元素上运行。
答案 2 :(得分:2)
除了显而易见的(data
比&data[0]
短;因此更易于写和读)之外,没有区别。
考虑&data[0]
的含义:
data[0]
的指针。data[0]
仅表示*(data+0)
,即*data
。*data
的指针就是data
。答案 3 :(得分:1)
没有区别。当被强制转换为指针时,数组(data
)会衰减为指向其第一个元素(&data[0]
)的指针。
请记住,data[0]
仅表示*(data+0)
,因此&data[0]
等同于&*(data+0)
,它简化为data
(因为&*
会被抵消)。
演示:
#include <stdio.h>
int main(void) {
int data[2];
printf("%p\n", (void*)data);
printf("%p\n", (void*)&*(data+0));
printf("%p\n", (void*)&data[0]);
return 0;
}
输出:
$ gcc -Wall -Wextra -pedantic a.c -o a && a
0x3c2180f4fa0
0x3c2180f4fa0
0x3c2180f4fa0
答案 4 :(得分:1)
data是指向数组开头的指针。 &data [0]是数组第一个元素的地址。
在阅读代码时,对于大多数人来说,第一个选择是更具可读性,我想这是大多数程序员都会并且应该选择的一种方式
答案 5 :(得分:1)
没有什么区别,因为它们都指向数组的相同起始位置,即a [0]。
答案 6 :(得分:1)
我总是建议使用一般方法。
只需考虑功能
void myFunction( char* data);
其中参数的类型为char *
,而不是int *
。
现在假设您要向函数传递字符串文字。
可以像
一样完成myFunction( "Hello" );
或喜欢
myFunction( &"Hello"[0] );
很明显,第一种方法更清晰易读。
所以我更喜欢使用第一种方法。:)
实际上是这样的表达
&data[i];
在语法上是多余的。实际上,它看起来像
&( *( data + i ) )
等同于
data + i
当i
等于0时,您拥有
data + 0
在表达式中等同于(我不考虑操作符的大小)
data
因此,请使用data
而不是&data[0]
。
答案 7 :(得分:1)
我只会使用my_function(data)
,因为为什么要使它比必须的更加混乱?
如果由于某种原因您需要在数据中间某个地方找到单个元素的内存地址,那么可能my_function(&data[17])
是有必要的,但是也可能有更好的方法来处理这种情况。
通常,如果您必须手动且专门地手动挑选单个数据,则可能不是很好的方法。
在极少数情况下它是有道理的(例如,如果您正在解析其他来源的数据,而您始终100%的时间只关心第17个字节)……但这通常不是这种情况。
请考虑以下内容: 随着代码的发展和更改,您可能还会略微更改数据结构。 Data [17]可能不再是您所需的神奇字节。现在可能是数据[18]。如果您在代码中100或1000个不同的位置手动对数据进行了硬编码[17],则现在必须手动进行全部更改,并希望它不会引起任何新的错误。另外...可移植性问题。
相反,设计功能可以从数据结构中查找并返回所需的任何数据,而无需任何硬编码地址。随着代码的发展,它们仍然可以工作(如果设计正确),并且可移植性将提高1000倍。