C中指针问题

本文详细解析了C语言中的指针数组、数组指针的概念及其区别,并深入探讨了函数指针、数组名特性、多维数组及作为函数参数时的注意事项等内容。

老生常谈的问题:指针数组和数组指针。这是一篇需要不断补充的博文,知道多少先写多少吧

int *p[];

int (*p)[];

对于第一个,p先和[]结合,故p被声明为一个数组,而这个数组的每个元素的类型为int*型;

下一个p先和*结合,所以p是一个指针,其指向的是一个int型的一维数组(一直认为C里面数组的声明方式没有JAVA里面直观,C里声明一个int型的数组a为int a[],Java里则更明显 int[] a)

 

同理 对于一个函数

int *p();

int (*p)();

前者定义了一个函数,其返回值为一个int类型的指针;

后者则是定义了一直指针,它指向的是一个具有int类型返回值的函数。

 

 

--------------------------------------------------------------------------------------------------------------------------------------------------------

 

以下内容总结自《C与指针》

 

数组 int b[5];

b[4]的类型是整型,但是数组名b的类型是 指针常量(所谓指针常量,就是该指针是个常量,所存储的内容(地址)不能修改,即不能修改该指针所指向的地址),它的值是数组第一个元素的地址(若要对某个固定地址(如100)进行赋值,就需要先将该地址强制转换为指针常量 *(int *)100 = 5)其具体类型取决于数组类型,若是整型数组,则b就是 “指向int的指针常量”。

 

在两种情况下,数组名不能用指针常量来表示:

1、 作为sizeof的操作数

2、 作为&的操作数。此时返回的是指向数组的指针,而不是指向数组第一个元素的指针的指针。

 

声明一个数组时,编译器会根据声明所规定的个数为数组分配内存空间,然后再创建数组名,它的值是一个常量,指向这段空间的起始位置。

声明一个指针时,编译器只会为指针本身保存内存空间。

另int a[5]={...};  a++,++a均会报错,a是常量,不能被修改。

 

数组的初始化:

对于静态数组,初始化只进行一次,且才程序开始执行之间就完成了。这个工作是由链接器完成的,它用包含可执行程序的文件中的合适的值对数组进行初始化,若未指明,初始化为0

对于auto数组,每次执行进入相应的程序块时,变量所占据的内存空间可能并不相同,所以编译器无法为其预先分配内存地址,每次都会为其初始化,这应该很浪费时间。

 

char[] p = "hello world";  //只是为了简化'h','e'...初始化数组;其并非表示字符串常量

char *p = "hello world";  //字符串常量,p被初始化为“helloworld”的地址

 

对于数组和指针的声明,只有作为函数的参数时才能等同。且作为函数的参数时,总是转换为指针的,所以指明数组的第一维的长度也是无用的。

如:fun(char[] string )和fun(char *string)两者相同。传递过来的只是一个指针。

 

多维数组

 

C中多维数组在内存中的存储顺序为:按其最右边(先是最后一维,然后倒数第二维。。。最后才是第一维)下标的变化存储。

指向数组的指针

int matrix[5][10];  (matrix是一个指向数组的指针)

故int (*p)[10] = matrix才是正确的 此时若p+i;实际运算过程中是 p+i*10

若声明过程中未写明第二维的长度 即int(*p)(),此时对p进行加减,会将第二维视为空指针,会执行 p+i*0。

多维数组作为函数的参数进行传递时,跟一维数组一样,可以声明为函数或者数组。但是值得注意的是,声明过程中必须指明除了第一维的其他所有维的长度,这样编译器才能判断出具体下标的存储位置(第一维长度不用指明,就像一维数组不需指明其长度一样)。

 

int a[2][3];

a,a+2一样,均为指向数组的指针,对其进行整数的加减运算,都是乘以相应数组长度进行加减的。

而a[0],a[2]则均为指向整型的指针,对其进行加减运算,是乘以sizeof(int)进行运算的。

 

sizeof(a)  结果为24  数组名

sizeof(a+2)  结果为4

sizeof(a[0])  结果为12  a[2]指向整型的指针,其相当于一个一维数组名,下同

sizeof(a[2])  结果为12

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值