C语言提高篇(一)

 为什么大家普遍使用C语言代码而不是汇编代码呢?

主要是汇编语言下面直接对应的就是机器码,如果平台不同的话,他是没办法运行的,而C语言就不同了,使用C语言编写好的代码,在不同平台使用不同的编译器去编译,最终生成的汇编代码恰好是可以在当前平台上运行的,所以他的移植性比较好。

原则上是用多少取多少,避免了内存被浪费的现象出现

 

 

 

 代码区是只读的,任何代码想要修改只读区的内容,都会被操作系统干掉(报错使之崩溃),同时代码区也是共享的,这样做的主要目的是实现程序的多开共享内存资源,实现内存的最大利用。

 栈空间的变量一般是临时变量,我们一般是没有办法控制的,随着函数调用的结束,栈空间的内存也会随之被回收掉。自动申请,自动释放。

 编译时的内存只是分配的地址,只有真正运行时才会真正分配内存。

全局静态区一般包括:全局区、静态区、常量区

extern int a; //可以在别的文件使用

static int a; //只能在当前的文件当中使用

他们的生命周期都贯穿程序的始终

字符串常量"hello"一般都放在常量区

全局的const变量也放在常量区,一经初始化通过指针也无法修改

int* myFun(){

        int a=10;

        return &a;

}

函数调用完之后a的值已经没有意义了,一定要注意a的生命周期只在函数的内部有意义,离开了函数就没有意义了,我们也不关心调用函数拿到的值是什么,因为这段内存会被自动回收。

因为你使用这个变量之后一定会出错,所以不要返回局部变量的地址!

函数调用之后,str当中保存的内容就被回收掉了,所以会打印出一堆乱码出来 

 

 只要是一段连续的内存,都可以使用下标的方式访问内存

for循环中,推荐使用++i,这样效率更高

在堆中申请的内存一定要拿到首地址,这样才能够释放掉

p的内存会被回收掉,但是使用ret可以接收申请的内存首地址

 使用完堆内存一定要及时释放掉,并将指针置为NULL

定义变量的时候一定要记得初始化,很多bug的产生都是由于没有初始化产生的

void allocSpace(char* p) {
	p = (char*)malloc(100);
	memset(p, 0, 100);
	strcpy(p, "hello");

}

int main() {
	char* p = NULL;
	allocSpace(p);
	cout << p << endl;
	return 0;
}

出现如下问题:读取内存异常,因为p是NULL

 

//在main函数中	
char* p = NULL;
00182065  mov         dword ptr [ebp-8],0  
	allocSpace(p);
0018206C  mov         eax,dword ptr [ebp-8]  
0018206F  push        eax  
00182070  call        001814E7  
00182075  add         esp,4 

//在allocSpace函数中
p = (char*)malloc(100);
00181951  mov         esi,esp  
00181953  push        64h  
00181955  call        dword ptr ds:[0018D1FCh]  
0018195B  add         esp,4  
0018195E  cmp         esi,esp  
00181960  call        00181299  
00181965  mov         dword ptr [ebp+8],eax  

跟进之后发现两个p根本不是同一个东西,在不同的函数中,他们的地址是分离的,彼此毫无关系

 把堆内存的地址丢了,导致了内存泄漏

在一个函数当中他的参数,局部变量都要分配一段独一无二的空间,与别的函数没有任何关系

解决方案:

void allocSpace02(char**p) {
	char* tmp = (char*)malloc(100);
	memset(tmp, 0, 100);
	strcpy(tmp, "hello");
	*p = tmp;
}

int main() {
	char* p = NULL;
	allocSpace02(&p);
	cout << p << endl;
	return 0;
}

 

使用带一个星的指针同样可以存储的下指针的地址(&p)那么为什么要用二级指针呢?

答:注要是设计者希望你能够区分指针指向的是什么类型的数据,都使用一个星的话,无法辨别你的指针里面保存的是谁的地址,是普通数据类型的地址还是指针类型的地址。

 

一个无法解析的外部符号g_a:是连接器在报错,在各个文件均找不到g_a,但是编译能够通过

头文件里面存放的全是声明而不是定义

任何不同类型的指针直接赋值都会报警告/报错,void*除外

 

 全局const放在常量区,一经初始化,不再能够修改

局部变量,不管是不是常量都是存储在栈上的

程序正常运行:

 程序运行报错:

 字符串常量可读不可写 ↑

 

函数调用: 

 

 

对于一个频繁调用而且比较短小的函数,建议采用宏函数(以空间换时间),因为他没有普通函数的开销:函数压栈、跳转、返回等。

P20 栈的生长方向和内存存放方向

 

打印出来的结果地址在减小表面栈的生长方向是朝上的

 

 

  低地址存低位就是小端模式,num标号处于低地址处

验证:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值