C语言---(一)指针做函数参数/数组/结构体的问题及
先给一个连接,我觉得总结的特别好:https://blog.****.net/tsfkurry/article/details/42027407
指针最重要理解下面几句话:
1.编译器总是要为函数的每一个参数制作临时副本,指针参数p的副本是_p,编译器使_p=p.如果函数体内的程序修改了_p的内容,就导致参数p的内容做相应的修改。这就是指针可以作为输出参数的原因。在例子中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数getmemory并不输出任何东西,事实上,每执行一次函数就会泄露一块内存,因为没有free释放内存。如果非得要用指针参数去申请内存,那么应该使用指针的指针。
2.输出指的是在函数里面分配内存,使用malloc ,malloc必须和free配合使用。
3.char *a =null
getMemer(a);
传递给函数一个指针变量,通过指针在函数中(getMemer(char *a))可以获取到a的值,但是改变不了a的值
4.理解指针的三种内存模型
5.多维数组的理解(以栈开口向下理解)
多维数组名的本质是数组指针, 步长是一维长度
int a[3][5];
int (*pArray)[5];
pArry=a;
*(a+i)+j=a[i][j];
(a+1)代表是整个第i行的地址,二级指针
*(a+1)代表第i行的首元素地址 一级指针
printf("%d %d \n", pArray, pArray + 1);//16448976 16448996
printf("%d %d \n", &pArray, &pArray + 1);//16448928 16448932
一个int是4个字节
printf("%d %d \n", a,a+1);//16448976 16448996
printf("%d %d \n", &a, &a + 1);//16448976 16449036
理解图
对于一维数组int c[1024]={0},c是数组首元素的地址,步长4个字节;&c,是整个数组的地址,步长1024*4
二维数组可以看成一维数组,二位素质中的每个元素是一维数组,二维数组参数中的第一维的参数可以省略int a[3][3]==int a[][3]==int (*a)[3]
结构体
结构体是一种数据类型,是固定大小内存块的别名,还没有分配内存;
1、定义结构体的两种方式:1) struct Teacher{ char name[40];int age;int id},在main函数中引用struct Teacher t1//同时c编译器分配内存
2) typedef stuct Teacher{char name[40],,int age;int id}Teacher; main函数调用,Teacher t1//分配内存
2、定义结构体变量三种方法:1)struct Student{ char name[54],int age}s1,s2;定义类型同时,定义变量
2)struct {char name[43],int age}s1,s2//定义匿名变量
3)略
3、初始化三种方法,略;如Teacher t1={"aaa",23,3}; t1.name="t1name";
t1.age中。t1. 的点是寻址操作,计算age相对于大变量的偏移量,在CPU中进行计算,没有操作作内存,“=”操作的内存。
4)通过指针操作内存空间
Teacher *p=NULL; p=&t2;
printf("p->age:%d \n",p->age); //-> 是寻址操作 计算age相对于t2的偏移量,在cpu总进行计算。
5)结构体赋值操作及做函数参数
Teacher t1={"dd",32,3}; Teacher t2; t2=t1;//直接赋值即可
下图是结构体做函数参数的传递过程;
6)结构体偏移量
Stutent *p=NULL;
(int)&(((Student *)0)->age)==(int)&(p->age); age变量相对于Student的指针位置
//一旦结构体定义下来,结构体中的成员内存布局就定下来了。
7)结构体的深浅拷贝
编译器的“=”操作,只会把指针变量的值从from copy到to,但是不会吧指针变量所知的内存空间给copy过去。
指针的理解
1.函数参数的传递是值传递
2.指针就是一把钥匙,通过地址找到对应的内存空间
3.未初始化的指针变量,打印出来的地址是随机数