1概念
(1).32位,有2的32次方个内存单元。64位有2的64次方个内存单元。
(2).一个内存单元存放大小为1个字节(byte)
(3).指针就是地址,内存空间由多个内存单元组成,每个内 存单元由一个或多个字节组成,每个字节都有一个唯一 的编号,这个编号地址 在不影响理解的情况中,有时对地址、指针和指针变量 不区分,通称指针。
(4)指针大小(sizeof(char*)/sizeof(int*))是相同的:因为指针需要多大空间,取决于地址的存储需要多大空间。
32位-32bit-4byte
64位-64bit-8byte
1.1取地址与解引用
1.打印地址:
int a = 10;//内存分配4个字节地址 printf("%p\n",&a);//用%p打印a的首地址 int* pa = &a; //pa用来存放a的地址,在c语言中pa叫指针变量 //*说明 pa是指针变量 //int说明pa执行的对象是int类型 return 0;
此时pa = &a
2.解引用:
int a = 10; int* pa = &a; *pa = 20;//解引用操作,*pa通过pa里面的地址找到a
此时*pa = a
1.2指针类型的意义
1.指针类型决定了:指针解引用的权限有多大
char*:访问1个字节。
int*:访问4个字节。
eg:
int a = 0x11223344; 分别用4个字节表示为: 44 33 22 11 char* pc = &a; *pc = 0; //此时char类型的*pc只能访问int类型a的一个字节(44) 所以只改变个字节 : 00 33 22 11
注意:一个十六进制位要4个二进制位(4位)表示,所以两个十六进制占8位(8个二进制),而8位表示一个字节。
所以在0x11223344中:11表一个字节,22表一个字节,33表一个字节,44表一个字节)
2.指针类型决定了,指针走一步,能走多远(步长)
eg:
注:p是从当前位置开始加减的,可以理解为下标为1.而arr是从0开始加减的。
9 int main(int argc, char *argv[]) 10 { 11 int arr[5] = {1,2,3,4,5}; 12 int* p = arr; 13 printf("%d\n",arr[2]); 14 printf("%d",*(p+2)); 15 16 return 0; 17 } 3 3
但是,从数组角度来看,p+n,数据就从0开始移动n位。
1.3野指针
野指针是指指针指向的位置不可知。
1.
int* p;//p是一个局部的指针变量,局部变量不初始化的话,默认是随机值。 *p = 20;//非法访问
2.越界
int arr[10] = {0}; int* p =arr; int i = 0; for(i = 0;i<=10;i++) { *p = i; p++; }
二.各种指针介绍
2.1字符指针
//1. char ch = 'q'; char* pc = &ch; //2: char* ps = "hello word"; printf("%c",*ps); --->h //也可以打印字符串 printf("%s",ps); printf("%s",arr); 因为(%s)打印字符数组时,给了起始地址,会把剩下的都打印下来。
对于(2:)ps存放的是字符串的第一个地址。
例题:
7 #include <stdio.h>
8
9 int main(int argc, char *argv[])
10 {
11 int a[5] = {1,2,3,4,5};
12 int b[5] = {1,1,1,1,1};
13 int c[5] = {2,2,2,2,2};
14 int* arr[3] = {a,b,c};
15
16 for(int i = 0;i<3;i++){
17 for(int j = 0;j<5;j++){
18 printf("%d",*(arr[i]+j));//arr[i][j];因为[j] = *( +j);
19 }
20 puts("");
21 }
22
23
24
25 return 0;
26 }
hqyj@ubuntu:~/c/day11$ ./a.out
12345
11111
22222
2.2指针数组
int* arr[3];存放整型数组
2.3数组指针
arr与&arr区别
1.表示的结果都是表示数组的首地址
2.但存入内存的表达方式不一样:
int arr[10]={0}; int* p1 = arr; 存入的是一个指针,用int类型指针p1指向arr首地址。p1是一个整型指针。 int (*p2)[10]= &arr p2是一个数组指针。 &arr表示一整行数组,此p2就是相当于指向了arr一整行数组。上升到到二维数组,arr[10][5](相当于10个一维数组,每一行5个数据),p2相当于指向了arr这个二维数组的第一行。 ??为什么p2要的是一个数组指针? ??p2是指向arr的每一个地址吗?
2种arr不表示首地址的情况
1.sizeof(arr),表示整个数组,计算整个数组的大小。
2.&arr。数组名表示整个数组,是取整个数组的地址。
2.3.1一维数组指针
arr[ ] int* p
1.arr是常量指针,所以不可以arr++,可以arr+n;
2.p是变量指针,所以可以p++实现移位
eg:
arr[2]在编译器编译的时候,会把arr[2]变成解引用---->*(arr + 2)
p[2] ----> *(p+2)
2.3.2二维数组指针
二维数组的首地址是第一行
二维数组名是行指针
229行:传入的是arr,表示数组首元素地址,而首元素是第一行,所以传入的是一个一维数组地址。
209行:用一个指向一维数组的指针p来接受该地址。
217行:用p+i找到第i行地址;*()称为解引用,表示找到i行的数组地址,等于找到了第i行首元素地址;首元素地址+j,表示该行j元素的地址;最后再*(),表示解引用(i行j列)地址,获得该地址的数据。
*(p+i)中,*表示解第i行引用,获得的是数组名。
q+1:是行加1,及q+1 == q+4*7(int 占4个字节)