[原创]C/C++中复杂指针声明&&数组名的一点小事

C/C++中指针声明一向是一个难点,当情况复杂时很容易弄错。当然实际情况可能较少用到复杂指针,但是深挖指针的内涵毕竟没有坏处。来看以下一例。

有三个简单函数

int mydb(int a)
{
    return 2*a;
}
int mytri(int a)
{
    return 3*a;
}
int myqua(int a)
{
    return 4*a;
}

Q1. 声明一个指针数组存放以上三个函数。

int (*fun_arr[3])(int) = {mydb, mytri, myqua};

Q2. 声明一个指向数组元素的指针。

int (** pfun)(int) = fun_arr;

Q3. 声明一个数组指针,指向fun_arr

int (*(*parr)[3])(int) = &fun_arr

 

确定指针类型的步骤:

1. 在一个声明表达式中定位 标识符

例如在Q1中,标识符为fun_arr

2. 根据优先级,将标识符先后与左右操作符相结合。注意声明指针的 * 的优先级低于 声明为数组的 [],圆括号()优先级最高。

例如Q1中,fun_arr优先与[]结合,表明fun_arr是一个数组;Q3中parr被圆括号括住,那么parr先与*结合,表明parr是一个指针。

3. 从标识符开始,由内向外递归结合左右操作符,逐渐扩大结果;并依据当前结果的类型填充“上下文”。

例如,当前结果是指针,那么隐含的下文应该是,指针指向的类型是____?

        当前结果是数组,那么隐含的下文应该是,数组元素的类型是____?

分析Q2的指针声明如下:

a. pfun是一个指针: *pfun

b. pfun指向一个指针: (**pfun)

c. 这个指针指向一个函数: (** pfun)()

d. 这个函数的参数是一个int,返回int: int (**pfun)(int)

 

分析Q3如下:

a. parr是一个指针: (*parr)

b. 它指向一个数组,包含三个元素: (*parr)[3]

c. 数组的元素是指针: * (*parr)[3]

d. 指针指向一个函数  * (*parr)[3] ()

e. 函数接受一个int,返回int : int * (*parr)[3](int)

 

关于Q3的答案中为什么要把 fun_arr取地址再赋给 parr,这里引出第二个问题

Q4. 数组名称的类型与对数组名取地址的类型一样吗?

即 若int arr[3] = {1,2,3};

arr与&arr的类型是一样的吗?

——————————————

答案是不一样。

arr 的类型是:指向arr中元素的指针,即 int *

&arr的类型是:指向整个arr数组的指针,即 (*)[3]

编译器会对语句: int * pi = &arr;

显示类型不兼容的警告。

 

知道了这些,可以解决这样的问题:

int arr[3] = {1,2,3};

print("%d\n",*((int *)(&arr+1)-1));

结果是?

————————————————

结果是:3

posted @ 2012-08-03 12:56  油炸西瓜  阅读(415)  评论(0编辑  收藏  举报