C语言指针铅封

1,指针就是地址,每个字节都有对应的地址,指针变量本质就是个变量存放的是地址编号,任何地址编号都是四个字节,也就是sizeof(int *  char* double ***)都是四个字节

2,如何定义一切指针

        1、*修饰 指针变量名                                                                //   *p

        2、保存啥类型变量的地址 就用该类型定义一个普通变量。    //    int num

        3、从上 往下 整体 替换                                                            //   int *p

3,*p什么意思?

*p表示取p保存的地址编号对应的空间内容。*p等价于num

4,指针变量的类型

        1,指针变量自身类型(p是什么类型)        只将指针变量涂黑,剩下啥类型,指针变量自身就是啥类型。        比如 p自身的类型是int *

        推广,int num,num的类型是?把num涂黑

        2,指针变量所指向的类型?        将指针变量和最近的一个*一起涂黑剩下啥类型就指向啥类型         p指向的类型为int类型 == p保存int类型变量的地址

              即指向XXXX类型 == 保存XXX类型变量的地址

5  指针变量的初始化

//如果 局部 指针变量 不初始化 保存的是随机的地址编号(千万别取值) int *p;

//不想让指针变量指向任何地方 应该初始化为NULL(千万别取值)  //#define NULL ((void *)0)

 int *p1 = NULL;

//将指针变量初始化为合法的地址(可以取值)        int *p2=&a;

//千万别看成 *p2 = & num;        是先 int * p2; p2 = &a  *修饰p2为指针变量        

6,&&与**的区别

//如果对一个变量取地址 整个表达式的类型 就是变量的类型+*.

//p的类型是 int *类型 

//*p的类型是 int 类型

//如果对指针变量取* 整个表达式的类型是 指针变量的类型‐*.

//高级总结:如果&和*同时存在 可以相互抵消(从右‐‐>左)。(重要)

7,数组与指针

        1, []与*()关系  //在使用中 本质:[] 是*( ) 缩写

         //缩写规则:+左边的值 放在[]左边边 +右边的值 放在[]里面

        arr[i]=*(arr+i)

        2,arr代表的是 第0个元素的地址(&arr[0])

        //&arr[0] == &*(arr+0) == arr+0 == arr 

        //所以:数组名arr代表第0个元素的地址,&arr是数组的首地址

        arr+1代表首元素地址+1,跳过了一个元素(4B)

        &arr+1代表是数组的首地址+1,跳过整个数组(4*5B)

        3,数组名arr是一个符号常量,不能被赋值(不能放在等号左边)

8,指针数组:本质就是数组,只是数组的每个元素都是指针

        1,定义,就是数组的定义,int arr[5]

                                                       *arr

                                                        int *arr[5] 

        int *arr[3]={&num1,&num2,&num3}        这个数组有三个元素,每个元素是什么类型?

        把arr[3]涂黑,剩下int *,每个元素是int *

        2, 指针数组保存字符串

        char * arr[3]={"hehe","haha","heihei"};

        数组每个元素保存的是字符串首元素的地址,即arr[0]保存的是‘h’的地址

        而字符串储存在文字常量区,是只读的

        那如何打印字符串?

        printf("%s",arr[1])

        如何打印arr[1]中的字符a,printf("%c", *(arr[1]+1)  )首元素的地址加一,再解引用

void test12()
{
	int arr[5]={10,20,30,40,50};
	int *p = arr;

	printf("%d\n", *p++);//10
    ++运算级搞,但是因为是后自增,所以先算*p,再把p++,此时,*p=20

	printf("%d\n", (*p)++);//20
先算*p就是20,然后再20++,(*p)++等价于(*p)=(*p)+1,此时*p等于21

	printf("%d\n", *(p++));//21
}

9,数组指针          本质就是指针,保存的是数组的首地址,p=&arr

        1,定义,就是定义一个指针,*修饰变量名*p        定义一个变量int arr [5]                                    替换int(*p)arr[5]

        *修饰p为指针变量,指针变量保存什么类型的地址?把*p涂黑,保存的是数组的地址

         是数组的地址(&arr)不是数组首元素的地址(&arr[0])

        该数组有五个元素,每个元素是什么类型?

        2,p=&arr,p+1跳过4*5个字节

        如何利用p取出arr[3]  40?

        如果p是=&arr[0]也就是p=arr,只要*(p+3),但是p=&arr故同时解引用,*p=arr

        故arr[3] = *(*p+3)

        睁大眼睛,*p看成*(p+0)=p[0],   见到*()想到变成p[]

        *(p[0]+3)= p[0]p[3]        也就是说一维数组看成只有一行的二维数组

10,二维数组        int arr[3][4];

        1,二维数组名代表行地址,加一跳过一行        arr+1就是第1行地址

        2,对行地址取*就代表当前行第零列的列地址,*(arr+1)就是第一行第零列地址,再对他加一加二就可以取这一行其他元素的地址

        3 ,组合技,如何取出第一行第二列的元素?

        *(arr+1)第一行第零列元素地址,*(arr+1)+2,在对他解引用,*(*(arr+1)+2)

        化简,==  *(arr[1]+2)==arr[1][2]

        4,案例, int arr[3][4]

        *arr+2   第零行第二列的列地址

        arr[1]        等于*(arr+1)第一行第零列的列地址

        &arr[0]+2        化简==&*(arr+0)+2==arr+2第二行的行地址

        **arr        化简==*(*(arr+0)+0)==arr[0][0]

11,数组指针与二维数组的关系

        1,定义一个指针变量,保存二维数组的行地址   int arr[3][4]

        数组指针          int (*p)[4]        p=arr        p完全等价与arr

        2,二维数组的行数        int row = sizeof (arr)/sizeof(arr[0])

        二维数组的列数        int col=sizeof(arr[0]/sizeof(arr[0][0]))

12,指针变量作为函数参数

        1,如果想在函数内部修改外部变量的值,就要将外部变量的地址传递给函数(以指针变量作为函数的参数)

13,一维数组名做函数参数

        1,如果函数内部想操作外部数组元素,请将外部数组的数组名传递给参数

        2,一维数组作为函数的形参,会被优化为一级指针

        int arr[5]        int arr[]----->int *p

        int arr[3][4]----->int(*p)[4]

        int arr[3][4][5]------->>int(*p)[4][5]

14,函数指针

        1,定义,  *p   int func (int a , int b)替换得到,int (*p)(int a,int b)

        2,函数名代表函数入口地址,就是个地址  p=func

        3,对函数指针取*****无意义

14,malloc和free函数

1 #include
2 void *malloc(unsigned int num_size);
3 形参:num_size需要申请空间大小的字节数。
4 返回值:
5 成功:返回空间的起始地址
6 失败:NULL
7 特点:
 1、对于malloc的返回值 一般要强制类型转换
 2、malloc申请的空间 内容不确定 一般使用memset进行清空
 3、多次调用malloc 第1次malloc 和 第2次malloc的地址不一定连续
案例

void test02()
2 {
3 int *addr = NULL;
4
5 addr = (int *)malloc(sizeof(int));
6 if(addr == NULL)//申请失败了
7 {
8 printf("malloc err\n");
9 return;
10 }
11
12 printf("*addr=%d\n", *addr);//不确定的值
13
14 //对堆区空间 清0
15 memset(addr, 0, sizeof(int));
16 printf("*addr=%d\n", *addr);//0
17
18 //对addr的空间 就行写 或 读
19 *addr = 1000;//写
20
21 printf("*addr=%d\n", *addr);//1000 读
22
23
24 //释放堆区空间 空间使用权限的回收 是否对空间内容清0 这是不确定的
25 free(addr);
26 }
27 int main(int argc,char *argv[])
28 {
29 test02();
30 return 0;
31 }

你可能感兴趣的:(c语言,开发语言)