c数组指针 int(*p)[4]声明后的使用

C语言 码拜 10年前 (2015-05-12) 1340次浏览 0个评论


                    #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 a[4] = { 1, 3, 5, 7 };

int(*p)[4]; //—>首先,(*p)表明p是一个指针,指向一个一维数组,该数组有4个元素,元素的类型是int

p = &a;

(*p)表示p指向的一维数组的第一个元素的地址

引用 1 楼 Intel0011 的回复:

int a[4] = { 1, 3, 5, 7 };

int(*p)[4]; //—>首先,(*p)表明p是一个指针,指向一个一维数组,该数组有4个元素,元素的类型是int

p = &a;

(*p)表示p指向的一维数组的第一个元素的地址

错了,应该是

                    int(* p)[4]; //--->首先,(*p)表明p是一个指针,指向一个一维指针数组,该数组有4个元素,元素的类型是int*
总结下,是不是这样

int (*p)[4]

他只在内存中开辟了4字节存储空间用来存地址

变量名为p 类型为int (*)[4]

存储的地址为4元素一维数组地址(虽然地址是一维数组的首元素地址,但他是行指针)

*p代表一维数组首元素的地址

(*p)[0]  *(*p)   代表一维数组中下标为0的值

(*p)[1]  *(*p+1) 代表一维数组中下标为1的值

(*p)[2]  *(*p+2) 代表一维数组中下标为2的值

(*p)[3]  *(*p+3) 代表一维数组中下标为3的值

说错了望指正!
引用 2 楼 zxh707wk 的回复:
Quote: 引用 1 楼 Intel0011 的回复:

int a[4] = { 1, 3, 5, 7 };

int(*p)[4]; //—>首先,(*p)表明p是一个指针,指向一个一维数组,该数组有4个元素,元素的类型是int

p = &a;

(*p)表示p指向的一维数组的第一个元素的地址

错了,应该是

                            int(* p)[4]; //--->首先,(*p)表明p是一个指针,指向一个一维指针数组,该数组有4个元素,元素的类型是int*

自己先整明白了再来评论对错

如果你说的对,那

int * (* p)[4];

表示什么

显然你都没搞清楚

int  (* p)[4];

int  *p[4];

的区别

20分

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的区别,都是地址,但前者的++操作会等于数组总长度,后者则是一个数组单元长度,此外,前者由于是地址的地址,所以可以取两次值。

数组int p[4]

指针的数组int *p[4]——这是个数组,4个成员,每个成员类型都是int *

数组指针int (*p)[4]——这是个单变量,不是个数组,数据类型int (*)[4],它赋值为int p[4]这样的数组

骚年,明白否?

引用 1 楼 Intel0011 的回复:

int a[4] = { 1, 3, 5, 7 };

int(*p)[4]; //—>首先,(*p)表明p是一个指针,指向一个一维数组,该数组有4个元素,元素的类型是int

p = &a;

(*p)表示p指向的一维数组的第一个元素的地址

这个就是正确的。

指向数组的指针就是说一个指针指向了整个数组,也就是说这个指针指向的是整个数组的空间,此时对这个指针进行自加操作得到的地址就是向后移动整个数组长度的地址。

20分

                    //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]


引用 楼主 u013491662 的回复:


                            #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里的值我明白,但是用在数组指针上就不明白是什么意思了。。。

p = &a;                                                       //p指向了a整个数组

printf(“%d\n”, sizeof(p)); //4字节               //p指针变量的尺寸是4字节

printf(“%d\n”, sizeof(*p));//16字节            //p指向的a数组尺寸是4*4个字节

printf(“%d\n”, sizeof(a)); //16字节            //同上

printf(“%d\n”, &a[0]);//16645296              //a数组首元素的地址(指针值)是16645296

printf(“%d\n”, p);    //16645296                //a数组首址是16645296。注意数组首址和首元素地址值同、类型不同

printf(“%d\n”, p[0]); //16645296               //这是首元素的地址

printf(“%d\n”, p[1]); //16645312              //这里语法上无错,但语义上有错,这是a数组之后存储单元的地址

printf(“%d\n”, p[2]); //16645312             //这里语法上无错,但语义上有错,这是a数组之后存储单元的地址–另外输出应该是16645328

printf(“%d\n”, p[3]); //16645344            //这里语法上无错,但语义上有错,这是a数组之后存储单元的地址

printf(“%d\n”, *p);   //16645296            //p是指向a数组的首址,*p就是指向a数组首元素的地址

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                      //p<=&a,则*p就是a(即&a[0]),(*p)[0]就是a[0]

printf(“%d\n”, (*p)[1]);//3                     //p<=&a,则*p就是a(即&a[0]),(*p)[1]就是a[1]

printf(“%d\n”, (*p)[2]);//5                     //p<=&a,则*p就是a(即&a[0]),(*p)[2]就是a[2]

printf(“%d\n”, (*p)[3]);//7                     //p<=&a,则*p就是a(即&a[0]),(*p)[3]就是a[3]

=====================================================================

p=&a

a[0]  <——–p[0]   <—p,但这两个指针的类型不同

a[1]

a[2]

a[3]

?[0]  <——-p[1]

?[1]

?[2]

?[3]

引用 9 楼 zhao4zhong1 的回复:
                            //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]




                    #include <stdio.h>




                    int main()




                    {




                    char(*(*x[3])())[5];




                    (char (*)[5]) (*y[3])();




                    return 0;




                    }


                    //前几步我都看懂了 x是一个数组,元素是指针,而且是函数指针


                    //函数返回值我看不懂了 看我第9行 y是一个数组,元素是指针,是函数指针,函数的返回值是指向一维字符数组的指针


                    //问题是 编译起来 第9行就报错 我也不知道哪里不对 希望你能帮我看看!


骚年,提向数组的指针不明白的话,怎么帮你都没用。

不要企图依赖输出指针相关表达式的值【比如printf(“%p\n”,…)】来理解指针的本质,

而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=…】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。

引用 5 楼 Intel0011 的回复:
Quote: 引用 2 楼 zxh707wk 的回复:
Quote: 引用 1 楼 Intel0011 的回复:

int a[4] = { 1, 3, 5, 7 };

int(*p)[4]; //—>首先,(*p)表明p是一个指针,指向一个一维数组,该数组有4个元素,元素的类型是int

p = &a;

(*p)表示p指向的一维数组的第一个元素的地址

错了,应该是

                                    int(* p)[4]; //--->首先,(*p)表明p是一个指针,指向一个一维指针数组,该数组有4个元素,元素的类型是int*

自己先整明白了再来评论对错

如果你说的对,那

int * (* p)[4];

表示什么

显然你都没搞清楚

int  (* p)[4];

int  *p[4];

的区别

把你那句话理解错了。。。

请问,这里的lamda表达式中想要接收每一行数组的指针,为什么总是编译不通过

int *p_2d = new int[r*c];

int (*p)[c] = (int (*)[c])p_2d;

for_each(&p[0],&p[r],[](int *line){cout  << *line[1] << endl;});

error: no matching function for call to “”for_each(int (*)[c], int (*)[c], dynamic_array_2D(int, int)::<lambda(int*)>)””

而下面的方式:

int **m;

for_each(m,m+r,[&](int *line){ for_each(line,line + c,[](int &a){cout << a << ” “;});});

是可以的,也就是我也对p和p[0]还有&p[0]在此的含义由疑惑


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明c数组指针 int(*p)[4]声明后的使用
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!