




免费预览已结束,剩余379页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1#include stdio.hint main() int a; int *p; p = &a; *p = 0x500; a = (int )(*(&p); a = (int )(&(*p); if(a = (int)p) printf(equal !n); else printf(not equal !n);请问本程序的输出显示是什么?答案:输出显示为”equal!”2struct signed int bit0:1; signed int bit1:1; signed int bit2:1; signed int bit3:1; signed int bit4:1; signed int bit5:1; signed int bit6:1; signed int bit7:1;bits;请问sizeof(bits)是否是正确的表达式?请问语句bits mybits; 的定义是否正确?如果不正确,要如何修改上述的结构定义才能使该语句正确?修改后的结构定义是否会影响sizeof(bits)的正确性?如果正确则该表达式的值为多少?如果将上述的结构中int类型改为char类型,此时sizeof(bits)的大小为多少?答案:1)是正确的表达式,因为sizeof后面的内容可以是类型,也可以是变量。2)该语句的定义不正确,因为此时的bits为一个变量;应该这样修改结构的定义typedef struct signed int bit0:1; signed int bit1:1; signed int bit2:1; signed int bit3:1; signed int bit4:1; signed int bit5:1; signed int bit6:1; signed int bit7:1;bits;修改后sizeof(bits)表达式依然正确,其值为4;类型改为char后其值为1,注意该值是在VC环境中的32位程序中得到的值,在不同的编译器其值有可能不同,因此在编程时不能自己假定类似结构的大小。3 struct bit unsigned int a0:1,a1:1,a2:1.a7:1; 请问这种写法是否正确?为什么?答案:不正确,位域中的变量不能是数组。4struct a int x; char y; struct a z; struct a *p; 请问这种定义结构正确否? 如果有问题,问题在哪里?答案:结构中不能对定义结构本身的非指针变量,如果编译器支持则会导致无限嵌套,因此一般编译器都会认为struct a是未定义的类型,即使提前声明也不会有任何用处。5 什么是可重入函数?C语言中写可重入函数,应注意的事项?答案:可重入函数是指能够被多个线程“同时”调用的函数,并且能保证函数结果的正确性的函数。在编写可重入函数时通常要注意如下的一些问题:尽量不要使用全局变量,静态变量,如果使用了应该注意对变量访问的互斥。通常可以根据具体的情况采用:信号量机制,关调度机制,关中断机制等方式来保证函数的可重入性。不要调用不可重入的函数,调用了不可重入的函数会使该函数也变为不可重入的函数。注意对系统中的临界资源,互斥资源的访问方式,防止使函数成为不可重入的函数。一般驱动程序都是不可重入的函数,因此在编写驱动程序时一定要注意重入的问题。6 简述stack frame 的含义。答案:stack frame的中文译名为:栈框架,表示函数在栈空间的调用层次,以x86平台的函数调用为例,通常一个函数编译成汇编程序,都有如下的结构: 其中的leave指令相当于:mov ebp,esp ;pop ebp各个函数在栈空间的映象为: test1函数 test2函数 test3函数因此在函数test3中,就可以根据这种栈框架的形式得到函数调用层次上的每个函数的基址指针,当前栈指针,以及函数调用点等信息。7 printf (“%d%dn”,+n, power(2,n); 其中power(2,n)为实现一定功能的函数 如 2n 。 请问这种表示方法有什么潜在的问题? 答案:编译器的不同,对+n 和power(2,n)处理的先后顺序不一样,形成二义性,造成程序的移植性差,因此最好把+n 写在printf函数外面,以消除二义性。printf (s); 请问这样的语句有没有问题?(s为一指向有效字符串的指针) 答案:没有%的话,可以这样表达,如果有%在s中的话,有意想不到的输出结果。9 两段代码共存于一个文件,编译时有选择的编译其中的一部分,请问如何实现?答案:有两种简单的办法可以实现:在源码中使用条件编译语句,然后在程序文件中定义宏的形式来选择需要的编译代码。在源码中使用条件编译语句,然后在编译命令的命令中加入宏定义命令来实现选择编译。10数据结构指针传给函数,函数能访问数据单元,但不能修改实际的内容,如何实现?答案:定义为指向常量的指针,这样指针所指的数据结构中的内容就不会被改变。如: const 类型 *p 或 类型 const *p 11 在头文件中定义静态变量,可能产生什么问题? 答案:在使用了该头文件的每个c程序文件中都单独存在一个该静态变量,这样造成空间的浪费并且很容易引起错误。因此建议不要在头文件中定义任何变量。12malloc()与 calloc()的区别?答案: 1)参数上的区别malloc (size_t size);calloc (size_t n , size_t size);malloc分配一块size大小的内存块,而calloc分配一个n*size大小的内存块 2)返回内存块的状态不同malloc分配的内存块没有被清零,而calloc分配的内存块是清了零的。但是建议在使用内存时,如果需要初始化,则最好自己按照需要来进行初试化,不要依赖函数的实现说明。13寄存器变量可不可以访问其地址?可否是全局变量?在什么场合使用寄存器变量? 答案:这些问题都与编译器的实现有关,建议不要声明全局变量为寄存器变量,即使是局部变量都最好不要声明其为寄存器变量,现在的编译器在优化时都会较为合理的安排寄存器变量的使用,而人为的安排有时会造成优化的低效。14n n 的区别?答案:前者是一个字符串并且以/0结束,而后者只是一个简单的字符。15包含预定义头文件 和 的区别?答案:只在指定的目录里寻找被包含文件; 先在当前目录下查找 ,再在指定目录下查找;通常方式用于系统的头文件,而一般用户的头文件用 的方式。16strunt S_A int a10; ; void f() int i; strunt S_A *s_ptr; for (i=0,i ai = i; 请问这段代码正确否?答案:这段代码不正确,没有对s_ptr指针进行初始化,在编程中要注意此类低级错误的发生。#pragma pack(8)struct s1short a;long b;struct s2char c;s1 d;long long e;#pragma pack()问 1.sizeof(s2) = ?2.s2的s1中的a后面空了几个字节接着是b?如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考:网友rwxybh(行云)的答案:内存布局是1* 11*1111 *1111 1111所以答案就是24和3下面是一个测试的程序,试一试就知道了,我用的是VC2005#pragma pack(8)struct s1short a; / 2 BYteslong b; / 4 Bytes;struct s2char c; / 1 Bytes1 d; / 8 Byteslong long e; / 8 Bytes;/ 1* 11*/ 1111 */ 1111 1111/ 00 01 02 03 04 05 06 07/ 00 01 02 03 04 05 06 07/ 00 01 02 03 04 05 06 07/ #pragma pack()int main(int argc, char* argv)s2 a;char *p = (char *)&a;for(int i=0;i24;+i)pi = (char)(i%8);printf(%dn,sizeof(a);printf(c=0x%lxn,a.c);printf(d.a=0x%xn,a.d.a);printf(d.b=0x%xn,a.d.b);printf(e=0x%llxn,a.e);return 0;结果:24c=0x0d.a=0x504d.b=0x3020100e=0x706050403020100网友 redleaves (ID最吊的网友)的答案和分析:如果代码:#pragma pack(8)struct S1char a;long b;struct S2 char c;struct S1 d;long long e;#pragma pack()sizeof(S2)结果为24.成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐.也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节.a bS1的内存布局:11*,1111,c S1.a S1.b dS2的内存布局:1*,11*,1111,*11111111这里有三点很重要:1.每个成员分别按自己的方式对齐,并能最小化长度2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐网友xue23(xue23) 的答案和分析:有程序查一下各个变量的内存地址得知:各个变量在内存中的位置为c*aa*bbbb*dddddddd测试代码为:s2 ss;cout ss.c = &ss endl ;cout ss.d.a = &ss.d.a endl;cout ss.d.b = &(ss.d.b) cout ss.d = &ss.e Setting-Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。 注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。 生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。 分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C+函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。 虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。 无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的:) C+/C试题的答案与评分标准一、请填写BOOL , float, 指针变量 与“零值”比较的 if 语句。(10分)请写出 BOOL flag 与“零值”比较的 if 语句。(3分)标准答案: if ( flag ) if ( !flag )如下写法均属不良风格,不得分。if (flag = TRUE)if (flag = 1 )if (flag = FALSE) if (flag = 0)请写出 float x 与“零值”比较的 if 语句。(4分)标准答案示例:const float EPSINON = 0.00001;if (x = - EPSINON) & (x =”或“=”此类形式。 如下是错误的写法,不得分。if (x = 0.0)if (x != 0.0)请写出 char *p 与“零值”比较的 if 语句。(3分)标准答案: if (p = NULL) if (p != NULL)如下写法均属不良风格,不得分。if (p = 0)if (p != 0)if (p) if (!)二、以下为Windows NT下的32位C+程序,请计算sizeof的值(10分)char str = “Hello” ;char *p = str ;int n = 10;请计算sizeof (str ) = 6 (2分) sizeof ( p ) = 4 (2分) sizeof ( n ) = 4 (2分)void Func ( char str100)请计算 sizeof( str ) = 4 (2分)void *p = malloc( 100 );请计算sizeof ( p ) = 4 (2分)三、简答题(25分)1、头文件中的 ifndef/define/endif 干什么用?(5分)答:防止该头文件被重复引用。2、#include 和 #include “filename.h” 有什么区别?(5分)答:对于#include ,编译器从标准库路径开始搜索 filename.h 对于#include “filename.h” ,编译器从用户的工作路径开始搜索 filename.h3、const 有什么用途?(请至少说明两种)(5分)答:(1)可以定义 const 常量(2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。4、在C+ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? (5分)答:C+语言支持函数重载,C语言不支持函数重载。函数被C+编译后在库中的名字与C语言的不同。假设某个函数的原型为: void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,而C+编译器则会产生像_foo_int_int之类的名字。C+提供了C连接交换指定符号extern“C”来解决名字匹配问题。5、请简述以下两个for循环的优缺点(5分)for (i=0; iN; i+)if (condition) DoSomething();else DoOtherthing();if (condition)for (i=0; iN; i+) DoSomething();else for (i=0; i 6) ? puts( 6) : puts(0) if (n%2 = 1) val = val *x;val = val * foo(x*x , n/2);return val;这段代码对x和n完成什么样的功能(操作)?(a) xn (x的n次幂)(b) x*n(x与n的乘积)(c) nx(n的x次幂)(d) 以上均不是第4题:考查指针,这道题只适合于那些特别细心且对指针和数组有深入理解的人main() int a5 = 1,2,3,4,5;int *ptr = (int*)(&a+1);printf(%d %d , *(a+1), *(ptr-1);这段程序的输出是:(a) 2 2(b) 2 1(c) 2 5(d) 以上均不是第5题:考查多维数组与指针void foo(int 3); main()int a 33= 1,2,3 , 4,5,6,7,8,9;foo(a);printf(%d , a21);void foo(int b3) + b;b11 =9;这段程序的输出是:(a) 8(b) 9(c) 7(d)以上均不对第6题:考查逗号表达式main()int a, b,c, d;a=3;b=5;c=a,b;d=(a,b);printf(c=%d ,c);printf(d=%d ,d);这段程序的输出是:(a) c=3 d=3(b) c=5 d=3(c) c=3 d=5(d) c=5 d=5第7题:考查指针数组main()int a3 = 1,2,3 ,4,5,6;int (*ptr)3 = a;printf(%d %d , (*ptr)1, (*ptr)2);+ptr;printf(%d %d , (*ptr)1, (*ptr)2);这段程序的输出是:(a) 2 3 5 6(b) 2 3 4 5(c) 4 5 0 0(d) 以上均不对第8题:考查函数指针int *f1(void)int x =10;return(&x);int *f2(void)int*ptr;*ptr =10;return ptr;int *f3(void)int *ptr;ptr=(int*) malloc(sizeof(int);return ptr;上面这3个函数哪一个最可能引起指
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025广东深圳市殡葬服务中心招聘5人模拟试卷附答案详解(考试直接用)
- 2025河南许昌市消防救援支队招聘政府专职队员50人模拟试卷及答案详解(典优)
- 合作开发框架协议书
- 2025年垃圾焚烧发电厂废弃物处理设施运行维护报告
- 夫妻赠与协议书范本
- 2025-2032年新能源汽车充电设施与充电桩技术发展趋势报告
- 2025年酒店餐饮行业人才激励机制与创新成果报告
- 2025年新能源行业资本市场风险预警与技术创新应对策略报告
- 2025年能源行业智能电网在数字化转型中的能源市场竞争力优化报告
- 2025年太阳能硅片硅锭市场分析:技术创新与太阳能光伏发电站运营维护策略报告
- 虚拟现实技术在物流管理中的应用
- 志愿者安全培训课件
- 私募基金管理人尽职调查清单
- 前列腺剜除术手术技巧
- 居民自建桩安装告知书回执
- 科普:农药毒性分类
- 陈阅增普通生物学第1篇3细胞结构与细胞通讯教学课件
- 【执业药师考试】执业药师历年真题
- FZ/T 81004-2022连衣裙、裙套
- GB/T 34875-2017离心泵和转子泵用轴封系统
- 故障录波器课件
评论
0/150
提交评论