C语言理论

一,数组与指针问题

  1. 数组名是一个指向数组首元素的指针常量,一经定义,不可更改,其内容是数组的地址即数组首元素地址,其地址是自身在内存中的地址;指针是指针变量,定义之后仍可更改,其类型在定义时确定,其内容是所指元素的地址,其地址是自身地址。
  2. 对指针使用*操作符时,结果是指针所指元素的值,如*a,要求a存储的数据是另一个存储单元的地址,*a得到的值所指元素的数据而不是a的数据,a的数据是地址。
  3. 当对数组名使用 sizeof 和 & 操作符时,数组名不再当成指向一个元素的指针常量来使用,sizeof(数组名)得到的是整个数组所占字节数,&数组名得到的数组首元素的地址。举例如下:
int arr[3] = {1,2,3};

prinf(“ox%x\n”,&arr);

printf(“ox%x\n”,&arr+1);

第二行打印的地址与第一行打印的地址相差12,即数组所占字节的大小,int占4一个字节

当对指针使用sizeof和&时,指针仍当成指向一个元素的指针变量来使用。举例如下:

int *p = arr;

sizeof(p)的结果是指针变量p所占字节数,在32位系统为4,64位系统为8,注意sizeof(p)并不是arr首元素所占字节数,可以认为sizeof(x)所关注的是x本身类型所占的空而间大小,而与x所指目标无关,这个x的类型可以是数组,指针,变量,表达式等。

&p的结果是指针变量p的地址。

4,对于使用指针和数组下标的选择: 

1)系统在使用数组下标对数组成员变量进行访问时,开销比较大,指针的访问效率是远远大于数组名的访问效率的;

2)只有在指针正确访问时,使用指针才比下标法更有效率; 

3)下标法更加容易理解,在可读性方面,也更加的具有优势;

二,结构体的理解:

1,结构体成员的地址是相对地址,是相对与结构体地址的偏移量,如下:

struct User{

    int i;

    char *p;

};

struct User u;

结构体实例u的地址是&u,其成员i的地址是&u+0x0(即第一个成员的地址就是结构体的地址),成员p的地址是&u+0x4因为int占4个字节,所以p相对于i偏移为4。

如果一个结构体没有初始化,访问其成员地址将得到的是偏移量,访问其成员数据时程序将出错,因为这时成员的地址是偏移量,不是一个元素的真是地址。

如下:

struct People{

struct User *u;

};

struct People p = {0};

struct People p = NULL;

printf(p.u->p);   //访问地址为0x04的数据,将出错

printf(“0x\n”,p.u->p);//得到的是p的偏移量4

注意:在计算结构体偏移量的时候要考虑内存对齐,偏移量不一定就是前面元素所占字节数。

三,内存管理

1,4个内存区,分别为代码区,静态区,栈区,堆区。

  1. 代码区,程序加载到内存时,代码,常亮,字符串等加载到该区,函数包括main在该区,程序运行期间不变。
  2. 静态区,存储全局变量,静态变量
  3. 栈区,存储自动变量(即函数形参和非static局部变量),程序运行期间可变,自动的含义是变量超出作用域{}(即代码块和函数体),自动从栈中弹出。每个线程都有专属的栈,栈最大尺度固定,超出即栈溢出。变量离开作用域,其栈上内存自动释放,如函数体内定义的变量,在函数结束自动释放内存,如果函数内某变量是通过malloc分配内存的,则需要手动调用free释放,函数结束该变量的内存不会自动释放,因为它的内存在堆区;如果函数内某变量以static修饰,则该变量在函数结束时不会自动释放,其内存在静态区,并且该变量只能在所在函数内部访问。
  4. 堆区,程序运行期间可变,其容量远大于栈,堆内存空间的申请(malloc)和释放(free)都需要手动编写代码来完成(malloc与free要成对存在)。

四,变量

  1. 全局变量(外部变量),代码块{}外部定义的变量
  2. 局部变量(自动变量),代码块{}内部定义的变量,可用auto显示定义
  3. 静态变量,程序运行期间内存地址不变,以static修饰,代码块{}内部定义的静态变量只能在代码块内访问,代码块{}外部定义的静态变量只能被定义这个变量的文件访问
  4. C语言中函数默认都是全局的,可用static来修饰为静态函数,静态函数只能被定义它的文件访问
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值