1、数据存放在哪里
bss段用来存放那些没有初始化和初始化为0的全局变量。(bss类型的全局变量只占运行时的内存空间,而不占用文件空间,并且在整个程序的运行周期内,bss数据是一直存在的。)
data段用来存放那些初始化为非零的全局变量。(data类型的全局变量既占文件空间,又占用运行时的内存空间。作为全局变量,data数据是一直存在的。)
rodata段存放常量数据。注意:一,常量不一定就放在rodata里,有的立即数直接和指令编码放在一起,存放在代码段。二,对于字符串常量,编译器会自动去掉重复的字符,保证一个字符串在一个可执行文件只存在一份复制。三,rodata在多个进程间是共享的。四,常量是不能修改的。字符串会被编译器自动放到rodata中,其他数据要放到rodata中,只需要加const关键字修饰。
text段存放代码(如函数)和部分整数常量,它与rodata段很相似,主要不同在于这个段是可以执行的。
栈 用于存放临时变量和函数参数。
堆 malloc、realloc、free函数。(malloc和free要配对使用)
2、内存分配方式
从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在,如全局变量、static变量等
从栈上创建:在执行函数时,函数内部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算使用内置于处理器的指令集,效率很高,但分配的内存容量有限。
从堆上分配:也称动态内存分配。程序在运行时用malloc或new申请所需要的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存周期由程序员决定。
3、指针与数组比较
一,修改内容 char a[ ]="hello"; a[0] = 'a';正确
char *p = "hello"; p[0] = 'a';错误
二,内容复制与比较 不能对数组名直接复制和比较,用strcpy和strcmp。
三、计算内存容量 char a[ ] = "hello world"; char *p = a; sizeof(a)=12,sizeof(p)=4
char a[1000]; sizeof(a)=4
4、带参宏定义与自定义函数的区别
1)在带参宏定义中,形式参数不分配内存单元,因此不必作类型转换;而宏调用中的实参有具体的值,要用他们去代换形参,因此必须作类型说明。这与函数中的情况是不同的,在函数中,形参和实参时两个不同的量,各有自己的作用域,调用时要把实参值赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递问题
2)在宏定义中的形参是标识符,而宏调用中的实参可以是表达式
注意:在宏定义中,字符串内的形参通常要用括号括起来以避免出错
5、结构体与数组的比较
1)都由多个元素组成
2)各个元素在内存中的存储空间是连续的
3)数组中各个元素的数据类型相同,而结构体中的各个元素的数据类型可以相同
6、#define和typedef的区别
typedef只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在C语言中是为了定义常量。
1)typedef (int*) pINT; 2)#define pINT2 int*
1)pINT a,b; >>>>>>>>int *a;int*b;
2)pINT2 a,b;>>>>>>>>int *a,b;
7、文件包含命令中文件名用双引号和尖括号的区别
使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不再源文件目录去查找;使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择一种命令形式。
8、结构体和联合体的区别
bss段用来存放那些没有初始化和初始化为0的全局变量。(bss类型的全局变量只占运行时的内存空间,而不占用文件空间,并且在整个程序的运行周期内,bss数据是一直存在的。)
data段用来存放那些初始化为非零的全局变量。(data类型的全局变量既占文件空间,又占用运行时的内存空间。作为全局变量,data数据是一直存在的。)
rodata段存放常量数据。注意:一,常量不一定就放在rodata里,有的立即数直接和指令编码放在一起,存放在代码段。二,对于字符串常量,编译器会自动去掉重复的字符,保证一个字符串在一个可执行文件只存在一份复制。三,rodata在多个进程间是共享的。四,常量是不能修改的。字符串会被编译器自动放到rodata中,其他数据要放到rodata中,只需要加const关键字修饰。
text段存放代码(如函数)和部分整数常量,它与rodata段很相似,主要不同在于这个段是可以执行的。
栈 用于存放临时变量和函数参数。
堆 malloc、realloc、free函数。(malloc和free要配对使用)
2、内存分配方式
从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在,如全局变量、static变量等
从栈上创建:在执行函数时,函数内部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算使用内置于处理器的指令集,效率很高,但分配的内存容量有限。
从堆上分配:也称动态内存分配。程序在运行时用malloc或new申请所需要的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存周期由程序员决定。
3、指针与数组比较
一,修改内容 char a[ ]="hello"; a[0] = 'a';正确
char *p = "hello"; p[0] = 'a';错误
二,内容复制与比较 不能对数组名直接复制和比较,用strcpy和strcmp。
三、计算内存容量 char a[ ] = "hello world"; char *p = a; sizeof(a)=12,sizeof(p)=4
char a[1000]; sizeof(a)=4
4、带参宏定义与自定义函数的区别
1)在带参宏定义中,形式参数不分配内存单元,因此不必作类型转换;而宏调用中的实参有具体的值,要用他们去代换形参,因此必须作类型说明。这与函数中的情况是不同的,在函数中,形参和实参时两个不同的量,各有自己的作用域,调用时要把实参值赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递问题
2)在宏定义中的形参是标识符,而宏调用中的实参可以是表达式
注意:在宏定义中,字符串内的形参通常要用括号括起来以避免出错
5、结构体与数组的比较
1)都由多个元素组成
2)各个元素在内存中的存储空间是连续的
3)数组中各个元素的数据类型相同,而结构体中的各个元素的数据类型可以相同
6、#define和typedef的区别
typedef只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在C语言中是为了定义常量。
1)typedef (int*) pINT; 2)#define pINT2 int*
1)pINT a,b; >>>>>>>>int *a;int*b;
2)pINT2 a,b;>>>>>>>>int *a,b;
7、文件包含命令中文件名用双引号和尖括号的区别
使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不再源文件目录去查找;使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择一种命令形式。
8、结构体和联合体的区别
struct和union都是由多个不同的数据类型成员组成的,但在任何统一时刻,union中只存放了一个被选中的成员,而struct的所有成员都存在,各成员都占有自己的内存空间,它们都是同时存在的,一个struct变量的总长度等于所有成员长度之和;在union中,所有成员不能同时占用它的内存空间,union变量的长度等于最长的成员的长度。对于union的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于struct的不同成员赋值是互不影响的。
9.内存对齐正式原则
① 数据类型自身的对齐值: 基本数据类型的自身对齐值,等于“sizeof(基本数据类型)”。
②指定对齐值:“#pragma pack(value)”时的指定对齐值value.
③结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
④数据成员、结构体和类的有效对齐值: 自身对齐值和指定对齐值中较小的那个值。
10.条件编译
第一种形式:#ifdef 标识符
程序段1
#else
程序段2
#endif
第二种形式:#ifndef 标识符
程序段1
#else
程序段2
#endif
第三种形式:#if 常量表达式
程序段1
#else
程序段2
#endif
第一种形式:#ifdef 标识符
程序段1
#else
程序段2
#endif
第二种形式:#ifndef 标识符
程序段1
#else
程序段2
#endif
第三种形式:#if 常量表达式
程序段1
#else
程序段2
#endif