int(*p)[4]声明后的使用有关问题

int(*p)[4]声明后的使用问题!
本帖最后由 u013491662 于 2014-07-01 20:24:42 编辑

#include <stdio.h>
int main()
{
int a[4] = { 1, 3, 5, 7 };
int(*p)[4];
p = &a;
printf("%d\n", sizeof(p)); //4字节
printf("%d\n", sizeof(*p));//16字节
printf("%d\n", sizeof(a)); //16字节
printf("%d\n", &a[0]);//16645296
printf("%d\n", p);    //16645296
printf("%d\n", p[0]); //16645296
printf("%d\n", p[1]); //16645312
printf("%d\n", p[2]); //16645312
printf("%d\n", p[3]); //16645344
printf("%d\n", *p);   //16645296
printf("%d\n", *p[0]);//1
printf("%d\n", *p[1]);//-858993460
printf("%d\n", *p[2]);//1
printf("%d\n", *p[3]);//0
printf("%d\n", (*p)); //16645296
printf("%d\n", (*p)[0]);//1
printf("%d\n", (*p)[1]);//3
printf("%d\n", (*p)[2]);//5
printf("%d\n", (*p)[3]);//7
return 0;
}


我不明白的是
这里的
p p[0] p[1] p[2] p[3]
*p *p[0] *p[1] *p[2] *p[3]
(*p) (*p)[0] (*p)[1] (*p)[2] (*p)[3]
分别代表什么?
上网查了好多,指针数组我明白,但是指向一个数组的指针不是很明白!
int (*p)[4];  不懂声明之后如果使用 是用*p 还是p还是(*p) 也不理解这三种代表什么意思?希望有高人解惑!
*p是取地址p里的值我明白,但是用在数组指针上就不明白是什么意思了。。。
------解决方案--------------------
int(*p)[4];// p是一个指针,指向int型数组,数组大小是4
    p = &a;// p指向了数组a的地址的地址,但一次++p操作会让p增加数组大小的字节,也就是4*4=16,虽然都是指向数组地址,但这就是p=&a和p=a的不同之处

printf("%d\n", sizeof(p)); //4字节    指针都是4字节,32位系统中
    printf("%d\n", sizeof(*p));//16字节   *p是数组首地址,等价于a,也就是计算了数组的长度
    printf("%d\n", sizeof(a)); //16字节   同上
    printf("%d\n", &a[0]);//16645296   数组首地址
    printf("%d\n", p);    //16645296  上面已经解释了,p是数组首地址的地址,地址值等同于数组首地址
    printf("%d\n", p[0]); //16645296  对该二级地址取值,等价于*p,这时它真正代表了数组首地址,升级为一级地址
    printf("%d\n", p[1]); //16645312  等价于++p,仍然是个地址,可是加了数组的长度16
    printf("%d\n", p[2]); //16645312 同上,估计的写错了,应该是16645328
    printf("%d\n", p[3]); //16645344 同上
    printf("%d\n", *p);   //16645296 解释过了
    printf("%d\n", *p[0]);//1 等价于在p【0】上取值,当然是数组的第一个元素值
    printf("%d\n", *p[1]);//-858993460 p[1]已经指向了一个位置的地址,其值也位置
    printf("%d\n", *p[2]);//1 P[2]更加未知
    printf("%d\n", *p[3]);//0  更加未知
    printf("%d\n", (*p)); //16645296  解释过了
    printf("%d\n", (*p)[0]);//1  // 首先取值(*p),变成了一级地址,这时候++就正常了,为一个int的值,所以取到了数组第一个值
    printf("%d\n", (*p)[1]);//3// 取到了第二个值
    printf("%d\n", (*p)[2]);//5 不解释
    printf("%d\n", (*p)[3]);//7  不解释。。。

综上所述,在你懂得了指针指向数组的前提下,你还要明白p=&a,p=a的区别,都是地址,但前者的++操作会等于数组总长度,后者则是一个数组单元长度,此外,前者由于是地址的地址,所以可以取两次值。
------解决方案--------------------
//char (*(*x[3])())[5];//x是什么类型的变量?
//
//分析C语言声明,关键是搞清楚这个变量是个什么东西(函数、指针、数组),
//是函数那么剩下的就是他的参数和返回值,
//是指针那剩下部分是说明他指向什么,
//是数组剩下的部分就是说明数组的成员是什么类型。
//解析C语言声明规则:
//从左侧第一个标识符开始,按照优先级进行结合。*表示是..的指针,const表示只读的,volatile表示可变的,[]表示是数组,()表示是函数。
//
//x和[3]结合说明是一个大小为3的数组,该数组的每个元素为一类指针,该类指针指向一类函数,该类函数无参数,返回一类指针,该类指针指向一个大小为5的char型数组
#include <stdio.h>
#include <typeinfo.h>
char num[5];
char (*x00())[5] {
    return &num;
}
int main() {
    char (*x000)[5];//返回值
    char (*(x00)())[5];//函数原型,参数为空,返回值为指针
    char (*(*x0)())[5];//数组的元素,是个函数指针
    char (*(*x[3])())[5];//是个数组,大小为3

    x0 = x00;
    x[0] = x0;
    x[1] = x0;
    x[2] = x0;
    printf("typeid(x).name() is %s\n",typeid(x).name());
    return 0;
}
//typeid(x).name() is char (* (__cdecl**)(void))[5]