C语言小结(一)

p + n      =     (unsigned int)p + n*sizeof(*p);
结论:

当指针p指向一个同类型的数组的元素时:p+1将指向当前元素的下一个元素;p-1将指向当前元素的上一个元素。

如:int a[] = {1,2,3,4}   a[1] = *(a+1) = *(p+1)


指针之间只支持减法运算,且必须参与运算的指针类型必须相同
p1 – p2; ( (unsigned int)p1 - (unsigned int)p2) / sizeof(type);
注意:
只有当两个指针指向同一个数组中的元素时,指针相减才有意义,其意义为指针所指元素的下标差,当两个指针指向的元素不在同一个数组中时,结果未定义


(数组)下标VS 指针

从理论上而言,当指针以固定增量在数组中移动时,其效率高于下标产生的代码.当指针增量为1且硬件具有硬件增量模型时,表现更佳

现代编译器的生成代码优化率已大大提高,在固定增量时,下标形式的效率已经和指针形式相当;但从可读性和代码维护的角度来看,下标形式更优。

C语言中,数组作为函数参数时,编译器将
其编译成对应的指针
void f(int a[]); = void f(int* a);
void f(int a[5]); = void f(int* a);
结论:
一般情况下,当定义的函数中有数组参数时,需要定义另一个参数来标示数组的大小。


malloc分配的内存没有被初始化,calloc分配的初始化了


char *a = "123" char *b = "1234"

if(strlen(a) > strlen(b))

if(stren(a) < strlen(b))  //strlen返回值为无符号整数,相减不可能小于0


C语言中通过typedef为数组类型重命名
typedef type(name)[size];
数组类型:
typedef int(AINT5)[5];
typedef float(AFLOAT10)[10];
数组定义:
AINT5    iArray;
AFLOAT10   fArray;

数组名是数组首元素的起始地址,但并不是数组的起始地址
通过将取地址符&作用于数组名可以得到数组的起始地址


main函数可以理解为操作系统调用的函数
在执行程序的时候可以向main函数传递参数

int main()
int main(int argc)
int main(int argc, char *argv[])
int main(int argc, char *argv[], char *env[])
argc – 命令行参数个数
argv – 命令行参数数组
env – 环境变量数组


为什么需要指向指针的指针?
指针在本质上也是变量,对于指针也同样存在传值调用与传址调用


C语言中只会以值拷贝的方式传递参数

当向函数传递数组时,将数组名看做常量指针传数组首元素地址。

C语言以高效为最初设计目标,在函数传递的时候如果拷贝整个数组执行效率将大大下降。

二维数组参数中第一维的参数可以省略。为了提供正确的指针运算,必须提供除第一维之外的所有维长度
void f(int a[5]); void f(int a[]); void f(int* a);
void g(int a[3][3]); = void g(int a[][3]); = void g(int (*a)[3]);


指针数组做参数:int* a[5]     ==  指针的指针:int** a



回调函数是利用函数指针实现的一种调用机制
回调机制原理
调用者不知道具体事件发生的时候需要调用的具体函数,被调函数不知道何时被调用,只知道被调用后需要完成的任务。当具体事件发生时,调用者通过函数指针调用具体函数,回调机制的将调用者和被调函数分开,两者互不依赖



malloc实际分配的内存可能会比请求的稍微多一点,但是不能依赖于编译器的这个行为
• 当请求的动态内存无法满足时malloc返回NULL
• 当free的参数为NULL时,free函数直接返回

char *p = (char *)malloc(0);
可以返回一个有效地址没错,可是为什么这个可以正常使用? 它哪来的内存呢?? 我在linux下 测试居然能正常使用这个指针,而且是可以free的 
这涉及到malloc内的内存分配算法。通常malloc有个最小单元分配,也就是申请1个字节,可能要分配n字节给应用程序
有的人可能从语意上定义.认为有这个定义就可以用.
如果从实现出发.一般就是在堆内存范围开辟一个区,这个区包含表示一个可用内存区的记录头部+可用内存。malloc(0)可用内存长度为0.但是分配了一个记录头部.
free时则去掉这个记录头部,详细的代码可以看一些lib库的malloc实现

全局区为什么要分初始化区和未初始化区?


初始化的放在data段,未初始化的放在bss段(初始化为0的也可能放在bss段) 
对于初始化的global变量,例如int   x   =   10; 
那么10这个数据必须在目标文件中保存起来,然后在OS程序加载的时候,复制到相应的内存。10这个实际的数据就会保存在目标文件中的data段。 
而如果是未初始化的数据(也就是说初始值0是合适的),就没有必要在目标文件中保存0这个值,而只需要记录一个字节数,来告诉OS有多少字节需要
在程序加载到内存的时候清空为0。这些信息就保存在bss段。 
bss段主要是为了节省程序的目标文件或者说可执行文件所占的磁盘空间。 
对于单个变量可能不明显,但当情形是初始化和未初始化的大型数组时,例如 
int   ar0[10000]   =   {1,   2,   3,   ...}; 
和   
int   ar1[10000]; 
时, 
把ar1放在bss段,只记录共有10000*4个字节要初始化为0,而不是像ar0那样记录每一个数据1,2,3...,那么bss为目标文件所节省的磁盘空间还是
相当可观的。 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值