指针算术和数组:什么是合法的?

bit*_*her 4 c arrays pointers pointer-arithmetic

请考虑以下陈述:

int    *pFarr, *pVarr;

int    farr[3] = {11,22,33};
int    varr[3] = {7,8,9};

pFarr = &(farr[0]);
pVarr = varr;
Run Code Online (Sandbox Code Playgroud)

在这个阶段,两个指针都指向每个相应阵列地址的开头.对于*pFarr,我们目前正在考虑11和*pVarr,7.

同样,如果我通过*farr和*varr请求每个数组的内容,我也得到11和7.

到现在为止还挺好.

现在,让我们尝试pFarr++pVarr++.大.正如预期的那样,我们现在看22和8.

但现在...

试图拉升farr++varr++...我们得到"错误类型的参数来增加".

现在,我认识到数组指针和常规指针之间的区别,但由于它们的行为相似,为什么会出现这种限制呢?

当我还考虑在同一个程序中我可以用表面上正确的方式和另一种不正确的方式调用以下函数时,这让我更加困惑,我得到了相同的行为,尽管与上面发布的代码中发生的情况形成对比!?

working_on_pointers ( pFarr, farr );  // calling with expected parameters
working_on_pointers ( farr, pFarr );  // calling with inverted parameters 
Run Code Online (Sandbox Code Playgroud)

.

void working_on_pointers ( int *pExpect, int aExpect[] ) {

    printf("%i", *pExpect);  // displays the contents of pExpect ok
    printf("%i", *aExpect);  // displays the contents of aExpect ok

    pExpect++;               // no warnings or errors
    aExpect++;               // no warnings or errors

    printf("%i", *pExpect);  // displays the next element or an overflow element (with no errors)
    printf("%i", *aExpect);  // displays the next element or an overflow element (with no errors)

}
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我理解为什么在某些情况下数组指针和指针的行为方式类似,但在其他情况下有所不同吗?

非常感谢.

编辑:像我这样的Noobs可以从这个资源中获益:http://www.panix.com/~elflord/cpp/gotchas/index.shtml

Joh*_*itb 8

不同之处在于,farr++为了产生任何影响,编译器需要存储的某个位置farr将评估为数组的第二个元素的地址.但是没有地方可以提供这些信息.编译器仅为3整数分配位置.

现在,当您声明函数参数是数组时,函数参数将不是数组.函数参数将是一个指针.C中没有数组参数.因此以下两个声明是等效的

void f(int *a);
void f(int a[]);
Run Code Online (Sandbox Code Playgroud)

你放在括号之间的数字甚至不重要 - 因为参数确实是一个指针,"size"只是被忽略了.

这与函数相同 - 以下两个是等效的,并且函数指针作为参数:

void f(void (*p)());
void f(void p()); 
Run Code Online (Sandbox Code Playgroud)

虽然你可以同时调用一个函数指针和一个函数(所以它们被类似地使用),你也将无法写入函数,因为它不是指针 - 它只是转换为指针:

f = NULL; // error!
Run Code Online (Sandbox Code Playgroud)

您无法修改数组的方式大致相同.


Alo*_*hal 5

在C中,您无法分配给数组.所以,给定:

T data[N];
Run Code Online (Sandbox Code Playgroud)

哪里T是类型而且N是数字,你不能说:

data = ...;
Run Code Online (Sandbox Code Playgroud)

鉴于上述情况,并且data++;尝试分配data,您会收到错误.

关于数组和指针,C中有一条简单的规则.在值上下文中,数组的名称等同于指向其第一个元素的指针,而在对象上下文中,数组的名称等同于数组.

对象上下文是指使用数组的大小sizeof,或者当您获取其地址(&data)时,或者在数组初始化时.在所有其他情境中,您处于价值背景中.这包括将数组传递给函数.

所以,你的功能:

void working_on_pointers ( int *pExpect, int aExpect[] ) {
Run Code Online (Sandbox Code Playgroud)

相当于

void working_on_pointers ( int *pExpect, int *aExpect ) {
Run Code Online (Sandbox Code Playgroud)

该函数无法判断它是否传递了数组或指针,因为它看到的只是一个指针.

以下问题的答案中有更多详细信息:

另请参阅C部分的智能手机网站,这篇文章写得非常好.