读《C语言深度解剖》读书笔记。
[32bit]
1 指针
在C中
- 指针变量占四个字节,系统为其分配4 bytes的内存。
- 指针变量不是所指内存块的名称,是系统为其分配空间的别名。
- 访问指针所存地址内容的方式有两种。指针形式和下标形式。访问过程都是先取指针所存地址值再在地址值上面通过运算得到目标地址,依据目标地址再得到内容。
- 指针+1操作表示指向下一个指针变量所指类型的元素。
(1)指针变量的内存
int *p;
? | ? | ? | ? |
0x1234ijmk 0x1234ijm(k+1) 0x1234ijm(k+2) 0x1234ijm(k+3)
定义指针p后,系统会在适当的时期(编译或允许时)给p分配4 bytes的内存空间,p就是这4 bytes空间的别名。如上图所示(假如起始地址为如此),系统为p分配了4 bytes空间,但此4 bytes 内存还未被初始化。
(2) 指针和所指对象关系
int j = 1;
p = &j;
系统为j分配内存,假如j变量存在0x6789qasz为起始地址的一片空间内。
内存以p为别名的空间存了j的地址(假设为大端模式)。
(3)访问指针所指内容
int a[3]={1, 2, 3};
p = a;
*(p + 1):先取p内的地址(即以0x1234ijmk为起始地址,连续4bytes内存里的值,这里为a数组数组元素的首地址),然后将得到的地址加1(sizeof(int))。
p[1]:编译器总是把以下标形式的操作解析为以指针形式操作[ *(p+1)]。先读出p内存的地址,再此地址基础上加上1个偏移量得到新的地址,再取新地址内的内容。
(4)指针移动
对指针加1操作,得到的是下一个元素的地址。一个类型为T的指针移动,以sizeof(T)单位移动。
2 数组
在C中,int a[3];
-
数组名a是数组元素的首地址。是数组元素所在连续空间的别名,后续地址的名字依次为a[0],a[1],……。是常量,不可更改。&a是数组的首地址。a,&a二者值一样。
-
访问数组元素的方式有两种。指针形式(*取内容形式)和下标形式。访问过程都是数组首元素地址加上偏移量得新地址,再取新地址上内容的过程。
(1) 数组元素首地址及数组首地址
char a[3];
a[0]=? | a[1]=? | a[2]=? |
0x4567qwer 0x4567qwe(r+1) 0x4567qwe(r+2)
a = 0x4567qwer。
&a = 0x4567qwer。
但二者意义不一样,a是a数组元素的首地址。&a是数组的首地址。a + 1得到a[1]元素的地址:a +sizeof(char),char为数组元素的类型;&a + 1得到下一个数组的地址(下一个数组也紧接a数组存储):&a + sizeof(a)。
(2) 数组访问元素的方式
int b[3] = {1, 2, 3};
*(b+1):b为数组b所有元素的首地址,在首地址基础上偏移1后得到新地址,再取新地址上的值。
b[1]:编译器总是把以下标形式的操作解析为以指针形式操作[ *(b+1)]。b为数组b所有元素的首地址,在首地址基础上偏移1后得到新地址,再取新地址上的值。
3 指针数组名差异
一位数组作为函数参数时,C编译器将函数形参中的一维数组编译成一个指向实参数组首地址的指针。这个可能只是编译器的功能。书上说的好。二者木有关系。
指针和数组名的值都是地址值。就指针和数组摆在面前,我觉得它们有以下区别:
1) 指针p代表为指针变量p分配的4 bytes的内存,它可以被看着此4 bytes内存的别名。数组名可以被看着为数组元素分配的连续内存的别名。
2) P值的改变表示此4 bytes地址所存的值改变。数组名不可再被赋值,它是一个常量。
3) P所存的地址是可以跟p的地址隔得很远的地址。而数组名所代表的地址就是以它为首地址的一片连续空间。
3)表示的是:P是为其p分配的空间的别名,p所存的地址在远方。数组名就是为其数组分配空间的别名。这就是数组和指针最本质的区别,使它们两个完全不再同一个概念之上,指针是比数组更深一个层次,数组名就是一个构造的数据类型变量。所以,当混淆它们俩的时候是有问题的。
把指针声明为数组
指针为系统为指针变量分配空间的别名。数组名是系统为整个数组分配内存的别名。正因为如此,当将指针变量(没有指向某段内存时)声明为数组时:
- 若原来的指针为char *型,被声明为char类型数组,则结果是得到维数为4的数组。因为系统为char*变量分配了4字节空间,被声明为数组过后,char *变量名就被认为是数组元素的首地址。此时,对这4个字节的访问都是原来指针存的地址值。若未存地址,则访问到的有可能是乱码。
- 若原来的指针类型为int*型,被声明为int类型数组,则结果是得到维数为1的整型数组[推测]。
- 若原来的指针类型为long long(超过4 bytes),这种情况下再被声明为数组,会咋地?如果编译器不报错的话,访问数组元素时很大可能是乱码,因为连第一个元素的值都要去其它地址内取值来组合。谁知道其它地址的值是what呢?
将数组声明为指针
如果将数组声明为同类型的指针。《C和指针》P.85。
另外的情况是,数组为char型,数组维数小于4。这个时候再将数组声明为指针,会咋地哦,哈哈。如果编译器不报错,用这个声明得来的指针访问的内容大概率都是乱码了。情况有点多……可待编程实际发现。懒得现场测试了,以后实践发现后分析。
C Note Over。