当今的社会的人或多或少都有点惰性和急功近利,在一开始学习编程的时候不喜欢阅读那些枯燥的文字,喜欢直接去阅读代码,渐渐地,发现一个问题,那就是编程时经常会犯一些低级错误,总结一下,这些错误源自于自己对这门语言中的基本概念一知半解,意识到那些枯燥的文字堆掌握并熟练使用一门语言的重要性,下面整理一下:
本文来自cnblogs.com/heri
1.1堆栈
是两种数据结构
★栈:是硬件,作用是表现作为一种数据结构,只能在一端插入和删除数据的特殊线性表。
允许插入和删除操作的一端称为栈顶,按照后进先出的原则存储数据,插入:进栈push,删除则为出栈pop,栈也被称为先进后出表,在函数调用时用于存储断点,在递归中也会用到栈。
压栈的操作使栈顶地址减小,弹出的操作使栈顶变大。
栈保存了一个函数调用时所需的维护信息,被称为堆栈帧。
栈一般包括一下两方面信息:1函数的返回地址和参数 2临时变量(非静态局部变量和临时变量)
★堆:动态存储结构,数据段中的自由存储区,用于存储分配动态数据,堆中存入的数据地址向增加方向变动,堆可以不断进行分配直到没有堆空间为止,可以随时进行释放,再分配,不存在顺序问题。
堆内存分配通常用malloc(),calloc() ,realloc()函数实现
堆内存释放使用free()函数
堆和栈在使用时生长方向相反,栈向底地址方向生长,堆向高地址生长。
默认函数内部的压栈操作:从上到下,从左到右,采用4字节对齐。
数组压栈,从最后一个元素开始,直到起始元素,从右向左。
☆在不传递参数的情况下,print()函数中打印出main()函数中arr数组中的各个元素
1 #include<stdio.h> 2 void print() 3 { 4 unsigned int _ebp; 5 _asm{ 6 mov _ebp,ebp 7 } 8 int *p = (int *)(*(int *)_ebp-4-4-4-7*4); 9 for (int i=0;i<7;i++) 10 printf("%d",p[i]); 11 } 12 int main() 13 { 14 int a =1; 15 int b =2; 16 char c='a'; 17 int arr[]={11,12,13,14,15,16,17}; 18 print(); 19 return 0; 20 }
1.2全局变量和局部变量
★全局变量:外部变量,在函数体外定义,不是哪一个函数所持有的。
全局变量又分为:外部全局变量和静态全局变量,
区别是:
使用static存储类别的全局变量只能在被定义的源文件使用,而使用extern存储的全局变量,可以被其他源文件中函数引用。
★局部变量:在函数中定义的变量称为局部变量。(形参相当于在函数中定义的变量,因此也是一种局部变量)
1.3生存期和作用域
有些人对生存期有种错误的理解,认为变量离开了它的作用域,其生存期就结束了。
★生存期:变量占用内存或寄存器的时长。
根据变量存储类型不同,在编译时,将被存放到动态存储区或静态存储区,其声明周期由声明时存储类型决定。
本文来自cnblogs.com/heri
静态存储区:存放全局变量和静态变量,在执行程序前分配存储空间,占用固定的存储单元。
动态存储区:存放函数的局部变量,返回值,形参,函数被执行过程中动态分配,执行完该函数自动释放,这种分配和释放是每次执行函数进行的,所以前后两次调用同一函数,其临时变量分配的地址可能是不同的。
1-auto
非静态变量的局部变量即为自动变量,缺省为这个类型。
2-register
寄存器变量是为了提高执行效率,频繁从内存单元存取变量相比于从寄存器中存取变量要多花费更多时间。
register声明的寄存器类型的变量存放在寄存器中,不会占用内存单元,可以提高程序执行效率。不能&取地址,取不到。
事实证明,使用register的程序执行速度提高3倍,但register的数目是有限的。
3-static
静态变量,生存期从程序开始运行到程序结束。
静态全局变量:只能被定义的源程序文件的函数调用。
初始化区别:
静态局部变量:在他所在的函数被执行时初始化,之后再执行该函数不再初始化,保留上一次运行的结果。
静态全局变量:在执行main()函数之前初始化,当前值由最近一次对它赋值操作决定。
4-extern
在全局变量类型前加extern,如果没有指定全局变量的存储类别,则默认为extern
1.3.2作用域
一段程序代码中所用到的变量名字并不总是有效的,限定这个bi名字的可用性的范围就是这个名字的作用域。
局部变量的作用域仅在该函数中有效,可以在一个函数中定义与另一个函数中变量名相同的变量。
尽量避免使用相同的变量名,因为会导致IDE定位不准,可读性不好。
1.4内部函数和外部函数
函数也同样有作用域,如果在一个源文件中定义的函数只能被该文件中的函数所调用,二不能被同一程序其他文件中的函数调用,则为内部函数,
static 函数类型 函数名 (参数表)
反之为外部函数,若定义函数时没有加关键字static或extern,也是外部函数,
extern 函数类型 函数名 (参数表)
区别:作用范围不同
使用内部函数的优点是,不同人编写不同函数时,不用担心重名,所以,在编程过程中,只需要在一个源文件中使用的函数,要养成加static的习惯。
1.5指针变量
C语言之所以强大且有自由性,体现在对指针的灵活运用上,所以指针是C语言的灵魂。
存放地址的变量称为:指针变量
一般变量存放的是数据本身,而指针变量存放的是地址。
但不能简单的将指针理解为地址,而应该把指针理解为指向一块内存区域的起始地址,指向区域的大小由所指变量的类型决定。