字符串自己的逆序,char型直接赋值,找中间变量t
整型一维数组指针传参,传的方式与整型相同
*a 传的是首元素的地址
打印指定长度、位置的数组(迭代器的方法)
指针数组
数组指针,一般在二维数组中遇到(&a 存的是整个数组的地址,与a <=> &a[0] 地址相同,但是意义不同)
将第一列和第四列交换位置:
a代表基类型为一维数组的指针,a + i代表跳过i * sizeof(一维数组) 的大小,即跳过i 行,*(a + i)代表一位数组的数组名,为int *型,后面进行一维数组操作
int a[3]; // a为 int *型
int a[3][4]; // a为 int (*p)[4]型
// 两者a <=> &a[0]
整形二维数组,直接赋值,找中间变量t
二维数组作为函数参数传递,形参为指向数组的指针
字符串数组,只有行(字符串个数),输出时只要一层循环,打印地址
指针数组作为函数参数传递,形参为指向指针数组的指针
字符串的选择排序,实际只循环一层,定义中间变量(一个字符数组,用其地址),用strcpy交换地址
用指针排序,只是改变了指针所指向的对象,节省了空间(对象在字符串常量区,是不连续的,指针在栈区,空间是连续的)
字符串的查找,也是通过地址用strcmp来比较查找
整形一维数组的传参
字符串的传参,不用传长度,通过while循环每次输出单个字符
strlen就是统计单个字符
strcpy就是单个字符的替换,‘\0’就是0,可通过src[i] 来作为while的循环结束条件
整型二维数组传参,传行数,列数靠计算
字符串数组传参,要传行数,作为地址数组
----------------------------------------------------------------------------------------------------
指针
要改谁,就取地址谁,传参时传该变量的(基类型)的指针
指针是一个用来装地址的数据类型
int *p = &i;
交换的正确做法:定义整形的中间变量 t
只是交换了两个指针所指的地址,变量的值并未发生改变:
t只充当一个中间变量,是可以的,虽然类型不匹配
--------------------------------------------------------
错误做法:p当中保存的地址是随机数
正确做法:先确定一个变量(例如 int 型),则其地址在指定空间(例如栈区)
& 和 * 加在一起,可以抵消(不能 *整型)
-------------------------------------------------------------------------------
定义的i 为整型,但是指针是char型,则从定位处开始偏移sizeof(char)即一个字节,0A,输出仍为10。用这个方法可以解决判断计算机大小端的问题
----------------------------------------------------------------------------------
指针p + n,是在地址上加了n * sizeof(基类型)
p指向的是数组的首元素地址,则*p 是数组的首元素
指针p指向的地址改变了:
指针p指向的地址没变:
a的地址是常量,不能改变,不能写成 *a++
两个指针间无法进行加法,可以进行减法(必须保证两个指针的基类型相等),减出来是两个地址之间差的基类型(可以是负数)
-------------------------------------------------------------------------
错误做法:定义指针p 在栈区(局部变量),而“Hello world!”在字符串常量区,无法进行修改,因此程序崩溃
只要在指针p 前加const,const修饰的是 *p,就无法修改所指变量的值 *p,可以修改p换个对象
const修饰的是 p,则指针p不能被修改,但是不影响所指的对象
两个都不能改
万能指针不能直接运算,必须要先强转
-------------------------------------------------
开空间只开一次,只初始化一次,i 有静态生存期,(去掉static ,i就是具有动态生存期,调一次函数开一次空间)第一次调foo()结果为11,第二次调foo()结果为12
static加在全局变量前,该变量只能在该文件中使用,不能被其它.c文件调用。同理,加在函数前面,则该函数只能在本文件中使用
---------------------------------------------------------------------------------------------------------
extern 在主函数中调用外部函数、变量
---------------------------------------------------------------------------------------------------------
调试时打印,不调试时关闭
不调试:
-----------------------------------------------------------------------------
动态分配内存空间
malloc();保证是连续空间,堆区
传参传的是字节数
传递的参数为0或空间太大开不出来,则返回NULL
指针p在栈区,“Hello world!”在字符串常量区,指针p所指向的变量在堆区,free(p) 释放的是指针所指对象所在的堆区上的内容,而并不是指针,指针要单独置空
错误做法:在使用动态分配时,原来的地址值千万不能改!借的地址和还的地址要一样
扩充开辟的空间:在复制完之后要销毁之前的空间,最后销毁时只用free() 一次,两个指针置空
首先在栈区给指针s开空间,再给形参指针p开空间,再给p所指向的对象在堆区开空间,最后函数调用完之后,指针变量p 被销毁,但是开出的堆空间没被销毁,内存泄漏
正确做法:传指针的地址
字符串的拷贝:要拷贝到的地方就传指针的地址用来malloc开空间,要拷贝的内容则只需传字符串的首地址,最后要释放堆空间,指针置空
也可以调用函数:
ptr 原有空间指针,size新开空间大小,该函数负责将原有内容拷贝到新空间上来,并将原有空间销毁
传参:几个元素,每个元素占多少个字节
传参:ptr原来空间指针,新开空间几个元素,新开空间每个元素占多少个字节
--------------------------------------------------------------------
错误做法:返回值为指针类型时,不能返回局部变量的地址,因为局部变量具有动态生存期,调用函数之后空间被销毁,所以该指针p 是野指针
可以返回静生存期的变量,例如加static的变量或者全局变量(未初始化时值为0)
XX
函数指针:保存函数的入口地址
函数指针可以用于多种函数(形参、返回值相同)的函数的调用,传参时多传一个参数(函数指针),调用函数时,多加传入函数名来选择采用哪种同种函数
=> 回调函数
去掉变量名,就是类型
qsort();快速排序
传参:数组首元素地址base,数组里几个元素(sizeof(a) / sizeof(a[0])),每个元素占几个字节(sizeof(a[0])),比较函数(两个元素的地址)