指针
指针的两个重要概念:
1.分配一个盒子,盒子要有多大?
在32bit系统中,指针大小为4个字节,2^32种状态(2进制)
2.盒子里存放的地址,所指向内存的读取方法?
指针前面的类型就是定义的读取方法。
定义为char *p;一次读取一个字节
定义为int *p;一次就读4个字节。
举例如下:
int main ()
{
int a =0x12345678;
int *p1;
p1 = &a;
printf("the p1 is %x\n",*p1);
}
输出为 :0x12345678;
int main ()
{
int a =0x12345678;
unsigned char *p1;
p1 = &a;//这样写会有警告(某些编译器会直接报错),char型指针指向int型变量,可以在&a前加强制类型转换(char *)
printf("the p1 is %x\n",*p1);
}
输出为:0x12或者0x78(涉及大小端模式问题)
指针偏移
int *p;
p+1,表示访问下一个地址等同于p+sizeof(p[0]);
地址内容标签访问方式:p[n];和数组访问方式相同
举例:
int main()
{
int a = 0x12345678;
int b = 0x99991199;
int *p1 = &b;
char *p2 = (char *)&b;
printf("the p1+1 is %x , %x, %x\n",*(p1+1), p[1], *p1+1);
printf("the p2 is %x\n", p2[1]);
}
输出为:the p1+1 is 12345678, 12345678, 9999119a
the p2+1 is 11(输出结果和编译器有关,可能有的编译器定义变量的空间不连续,就不符合上面所述)。
多级指针
二维指针
int main (int argc , char **argv)
{
int i = 0;
while(argv[i] != NULL){
printf("the argv is %s\n",argv[i]);
i++;
}
}
上述程序在编译后,运行输入./build hello 123 456
则会打印输出:
the argv is ./build
the argv is hello
the argv is 123
the argv is 456
二维指针示意图
指针数组(可以理解为指针的数组)
普通数组定义
int a[100]; int代表的是这个空间访问的最小权限
指针数组定义方式
char *a[100];
a先与右侧[ ]结合
a数组名,100表示范围, * 告诉a中存放内容的属性,char 是指定 * 读内存的方法。
sizeof(a) = 100 * 4 = 400;
二维指针
char **a ;//等同于指针数组
a[1]访问第一个存放的指针地址,依此类推。
数组名的指针保存(数组的指针)
定义一个指针,指向int a[10];
的首地址
定义一个指针,指向int b[5][6];
的首地址
第一个是一维数组:int *p1 = a;
正确
第二个是二维数组:int **p2 = b;
错误
二维数组与二维指针没有关系
正确的应该写为 int (*p)[5];
指针数组和数组指针
例题1:
int a[10];
int *p = a;//数组名为第一个元素地址,也是数组首地址,&a是整个数组的首地址,二者值一样,含义不一样,用法也不一样
以下哪一个表示方法不能表示a[1]:
A. p+1 B. p++ C.a++ D.a+1
答案是C,a++等同于a = a+1;数组名是一个常量指针,作为一个常量,自然不能放在=左边进行赋值运算。