变量的定义为变量分配地址和内存空间,变量的声明不分配地址。一个变量可以在多个地方声明,但是只在一个地方定义。加入 extern 修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。
说明:很多时候一个变量,只是声明不分配内存空间,知道具体使用时才初始化,分配内存空间,如外部变量。
int main() { extern int A; //这是个声明而不是定义,声明A是一个已经定义了的外部变量 //注意:声明外部变量时可以把变量类型去掉如:extern A; dosth();//执行函数 } int A;//是定义,定义了A为整型的外部变量2、简述#ifdef、#else、#endif和#ifndef的作用
- 利用#ifdef、#endif将某程序功能模块包括进去,以向特定用户提供该功能。在不需要时用户可轻易将其屏蔽。
- 在子程序前加上标记,以便于追踪和调试。
- 应对硬件的限制。由于一些具体应用环境的硬件不一样,限于条件,本地缺乏这种设备,只能绕过硬件,直接写出预期结果。
注意:虽然不用条件编译命令而直接用if语句也能达到要求,但那样做目标程序长(因为所有语句都编译),运行时间长(因为在程序运行时间对if语句进行测试)。而采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,减少运行时间。
3、写出int、bool、float、指针变量与“零值”比较的if语句//int与零值比较 if (n == 0) if (n != 0) //bool与零值比较 if (flag)//表示flag为真 if (!flag)//表示flag为假 //float与零值比较 const float EPSION = 0.00001; if((x>=-EPSION)&&(x<=EPSION))//其中EPSION时允许的误差 //指针变量与零值比较 if(p==NULL) if(p!=NULL)4、结构体可以直接赋值吗?
声明时可以直接初始化,同一结构体的不同对象之间也可以直接赋值,但是当结构体中含有指针“成员”时一定要小心。
注意:当有多个指针指向同一段内存时,某个指针释放这段内存可能会导致其他指针的非法 *** 作。因此在释放前一定要确保其他指针不再使用这段内存空间。
- sizeof是一个 *** 作符,strlen是库函数
- sizeof的参数可以是数据的类型,也可以是变量,而strlen只能以结尾为‘’的字符串做参数。
- 编译器在编译时就计算出了sizeof的结果,而strlen函数必须在运行时才能计算出来。并且sizeof计算的是数据类型占内存的大小,而strlen计算的是字符串实际的长度。
- 数组做sizeof的参数不退化,传递给strlen就退化为指针了。
在c中static用来修饰局部静态变量和外部静态变量、函数。而c++中除了上述功能外,还用来定义类的成员变量和函数。即静态成员和成员函数。
注意:编程时static的记忆性,和全局性的特点可以让在不同时期调用的函数进行通信,传递消息,而c++的静态成员则可以在多个对象实例间进行通信,传递消息。
- new、delete是 *** 作符,可以重载,只能在c++中使用
- malloc、free是函数,可以覆盖,c、c++中都可以使用
- new可以调用对象的构造函数,对应的delete调用相应的析构函数
- malloc仅仅分配内存,free仅仅收回内存,并不执行构造和析构函数
- new、delete返回的是某种数据类型指针,malloc、free返回的是void指针
注意:malloc申请的内存空间要用free释放,而new申请的内存空间要用delete释放,不要混用。
#define min(a,b)((a)<=(b)?(a):(b))
9、++i和i++的区别++i先自增1,再返回,i++先返回i,再自增1
10、volatile有什么作用- 状态寄存器一类的并行设备硬件寄存器
- 一个中断服务子程序会访问到的非自动变量。
- 多线程被几个任务共享的变量
注意:虽然volatile在嵌入式方面应用比较多,但是在pc软件的多线程中,volatile修饰的临界变量也是非常实用的。
可以,用const和volatile同时修饰变量,并且这个变量在程序内部是只读的,不能改变的,只在程序外部条件变化下改变,并且编译器不会优化这个变量。每次使用这个变量时,都要小心的去内存读取这个变量的值,而不是去寄存器读取他的备份。
注意:在此一定要注意const的意思,const只是不允许程序中的代码改变某一变量,其在编译期发挥作用,他并没有实际的禁止某段内存的读写特性。
&a:其含义就是”变量a的地址“
*a:用在不同的地方,含义也不一样
- 在声明语句中,*a只说明a是一个指针变量,如int *a;
- 在其他语句中,*a前面没有 *** 作数且a是一个指针时,*a代表指针a指向的地址内存放的数据,如b=*a;
- *a前面有 *** 作数且a是一个普通变量,a代表乘以a,如c=ba。
while(1)
{}
注意:很多种途径都可以实现同一种功能,但是不同的方法时间和空间占用度不同,特别是对于嵌入式软件,处理器速度比较慢,存储空间较小,所以时间和空间优势是选择各种方法的首要考虑条件。
请写出以下代码的输出结果:
#includeusing namespace std; struct s1 { int i : 8; char j : 4; int a : 4; double b; }; struct s2 { int i : 8; char j : 4; double b; int a : 4; }; struct s3 { int i; char j; double b; int a; }; int main() { cout< 说明:结构体作为一种复合数据类型,其构成元素既可以是基本数据类型的变量,也可以是一些复合型类型数据。对此,编译器会自动进行成员变量的对齐以提高运算速率。默认情况下,按自然对齐条件分配空间。各个成员按照他们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同,向结构体成员中size最大的成员对齐。
15、全局变量和局部变量有什么区别?是怎么是实现的? *** 作系统和编译器是怎么知道的?
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,他们会要求这些数据的首地址是某个数k(通常为4或8)的倍数,而这个k则被称为该数据类型的对齐模数。16、简述c、c++程序编译的内存分配情况
- 全局变量是整个程序都可访问的变量,谁都可以访问,生存期在整个程序从运行到结束(在程序结束时所占内存释放);
- 而局部变量存在于模块(子程序、函数)中,只有所在模块可以访问,其他模块不可直接访问,模块结束(函数调用完毕),局部变量消失,所占据的内存释放;
- *** 作系统和编译器,可能是通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序开始运行的时候被加载,局部变量则分配在堆栈里面。
- 从静态存储区域分配
内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量、常量字符串等。- 从栈上分配
在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。大小为2M.- 从堆上分配
即动态内存分配。程序在运行的时候用malloc和new申请任意大小的内存,程序员自己负责在何时用free和delete释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收他,否则运行的程序会出现内存泄露,另外频繁的分配和释放不同大小的堆空间将会产生”堆内碎块“。一个c、c++程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区、程序代码块区。
17、简述strcpy、sprintf、memcpy的区别18、解析((void()())0)()的含义
- *** 作对象不同,sprcpy的两个 *** 作对象均为字符串,sprintf的 *** 作源对象可以是多种数据类型,目的 *** 作对象是字符串,memcpy的两个对象就是就是两个任意可 *** 作的内存地址,并不限于何种数据类型。
- 执行效率不同,memcpy最高,strcpy次之,sprintf的效率最低
- 实现功能不同,strcpy主要实现字符串变量间的拷贝,sprintf主要实现其他数据类型格式到字符串的转化,memcpy主要是内存块间的拷贝
注意:strcpy、sprintf与memcpy都可以实现拷贝的功能,但是针对的对象不同,根据实际需求,来选择合适的函数实现拷贝功能。void(0)():是一个返回值为void,参数为空的函数指针0;
19、c语言的指针和引用和c++的有什么区别?
(void()())0:把0转换为一个返回值为void,参数为空的函数指针;
(void()())0)():在上句的基础上加表示整个是一个返回值为void,无参数,并且起始地址为0的函数的名字。;
((void(*)())0)():这就是上句的函数名所对应的函数的调用。
- 指针有自己的一块空间,而引用只是一个别名
- 使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小;
- 作为参数传递时,指针需要被解引用才可以对对象进行 *** 作,而直接对引用的修饰都会改变引用所指向的对象
- 可以有const指针,但是没有const引用
- 指针在使用中可以指向其他对象,但是引用只能是一个对象的引用,不能被改变;
- 指针可以有多级指针,而引用止于一级;
- 指针和引用使用++运算符的意义不一样;
- 如果返回动态内存分配的对象或者内存,必须使用指针,引用可能会引起内存泄漏。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)