目录
指针与一维数组
约定俗成的用法
- 关键字sizeof:
- 首先要知道的是sizeof是运算符,不是函数。
- 用于计算操作数所占空间的字节数大小,操作数所占空间的字节数大小。
- strlen()函数
- strlen()用于计算字符串的长度。
- 头文件为#include<string.h>
- '\0’作为终止符。
- 其参数必须是字符型指针(char*),所以可以用字符串数组的数组名作为首元素的地址,来计算字符串的长度。
- 数组名不作为首元素地址的两个特例
- 在绝大多数情况下,定义完一个数组arr可以数组名表示首元素的地址,但以下两种情况是需要牢记的特例:
- sizeof(arr) 此时arr不局限于首元素,而是用于计算整个数组所占内存空间的大小
- &arr 此处的含义是指arr这整个数组的地址(后文会详细辨析)
- 在绝大多数情况下,定义完一个数组arr可以数组名表示首元素的地址,但以下两种情况是需要牢记的特例:
- 指针所占内存空间的大小
- 指针变量占用的内存空间大小根据所使用的操作系统及编译环境而定。
- 32位机器的代码时,指针占4个字节
- 64位机器的代码时,指针占8个字节
- arr[i]=*(arr+i)
指针与一维数组
这里从定义一个简单的数组介绍起
char arr[10]={1,2,3,4,5,6,7,8,9,10};
这里就引申出来了四个特殊的表示方法,每个均有所差异:
- arr
在这里arr表示的是首元素的地址,也就是 arr[0]的地址
- arr+1
因为arr是首元素的地址,地址+1对应跳过相同的类型,但不改变指针本身,因此,arr+1表示的是此时 arr[1]的地址
- &arr
&arr 此处的含义是指 arr这整个数组的地址。此时&arr的类型是int(*)[10],是一种数组指针类型
- &arr+1
数组的地址+1,跳过整个数组的大小,所以&arr+1相当于&arr的差值是:
int的大小4byte * 10个元素=40byte
指针与二维数组
这里定义一个简单的二维数组加以解释:
int a[3][4]={0};
这里也有多种表达形式:
- a
a是整个二维数组的数组名,但表示的却是第一行元素的首地址。
其类型是int(*)[4],是个数组指针。
- a+1
二维数组名+1表示第2行的首元素的地址。
其类型是int(*)[4],是个数组指针。
- a[0]
表示为a[0] [0]这个元素的地址。
但是!
「1」printf("%d\n",sizeof(a[0]));
「2」printf("%d\n",sizeof(a[0]+1));
「3」printf("%d\n",sizeof(&a[0]+1));
「4」printf("%d\n",sizeof(*(&a[0]+1)));
- 「1」打印的结果为16。
要回顾一下约定俗成的数组名使用的特例:a[0]表示第一行的数组名,最终计算出这个数组名下元素所占内存的大小。所以最终结果为4*4=16。此时的sizeof(a[0])不可以理解成a[0] [0]这个元素的地址。
- 「2」打印的结果为4。
这种情况之下,就将a[0]+1就是a[0] [1]这个元素的地址,在32位机器下大小都为4。
- 「3」打印的结果为4。
看上去更繁琐了,但实际上和「1」类似。也是两个数组名特例中的第二个 :&数组名
&a[0],此处a[0]表示第一行的数组名,二维数组下&a[0]和a[0]一样都是表示第一行的地址。所以&a[0]+1是第二行的地址。
- 「4」打印的结果为16。
其余部分都与「3」相同,知识多了一个 * 。所以整体类型不再是指针了,而是第二行元素的整体,结果为4 * 4=16。
- a[0]+1
表示为a[0] [1]这个元素的地址。
可以用这段代码验证上述内容: { printf("%p\n",&a[0][1]); printf("%p\n",a[0]+1); } 发现结果是相同的。
以上便是全部内容啦,感谢观看