c&c++葵花宝典

所需积分/C币:10 2013-11-27 14:50:09 1.27MB PDF

此文档讲述了一些C/C++中一些小的知识点,这些知识点很多都是被我们所忽略的知识点;在工作中也许是要命的一小点
QQ: 1 zhangqqgf@ 163 sizeof 考点:区别 struct与 union、(一般假定在32位机 器上) 1.下代码中的两个 sizeof用法有问题吗? 答:DATE是一个 union,变量公用空间.旦面最 void Upper case( char str[]) 大的变量类型是int[5],古用20个字节.所以它 ∥/将str中的小写字母转换成大写字母 的大小是20.data是一个 struct;每个变量分开 占用空间.依次为int4+DATE20+ double8= for( size t i=0;i< sizeof(str)/ sizeof(str[0j);32,.所以结果是20+32=52.当然在某些 十 16位编辑器下,int可能是2宇节,那么结果是 if('a<=str[i] & str[]<=z) int2+ datE10+ double= 20 str[-=(a-A"); 3.若int占4个宇节,char占1个字节, float占 4个字节,则定义如下: char str[="aBcDe struct stut cout<<"str字符长度为:"< union sizeof(str)/sizeof(str[o]<< endl har bj[5]; UpperCase( str ) int bh[2] cout < str < endi fclass; 答:函数内的 sizeof有问题。根据语法, sizeof char xm[8]: 如用丁数组,只能测出静态数组的大小,无法检 float ci 测动态分配的或外部数组人小。函数的st是一}Xc; 个静态定义的数组,因此其大小为6,函数内的 则 sIzed(xc)的值为? tr实际只是一个指向字符串的指针,没有任何额答:20,一道边界对齐的题目,注意下联合的内 外的与数组相关的信息,因北 sizeof作用于上只存大小取决于其屮字节数最多的成员就可 将其当指针看,一个指针为4个字节,因此返回4.给定结构 struct A 4 注意:数组名作为函数参数时,退化为指针 char t: 4 数组名作为 sizeof()参数时,数组名不退化因 char k: 4: 为 sizeof不是函数 unsigned short i: 8: 2.设有以下说明和定义: unsigned long m typedef union ;问 sizeof(A)=? 给定结构 struct A long I int k[5] char t:4;4位 char char k:4;4位 DATE unsigned short i:8;8位 struct data unsigned long m;∥/偏移2字节保证4字节对 齐 int catr };∥/共8字节 DATE cOW 5. struct name 1 double dog s too: char str; DATE max short x 则语句 printf(("d", sizeof( struct int num; data)+ sizeof(max);的执行结果是: 52 QQ: 1 zhangqqgf@ 163 struct name2t 8个字节之间的位置被忽略,直接放在8字节的位 char str; 置了,因此,总共是16字节 int num 第二个最后会对照是不是结构体内最大数据的倍 short x 数,不是的话,会补成是最大数据的倍数 7.在对齐为4的情况下 sizeof(struct name1)=8 struct bbb sizeof(struct name2)=12 在第二个结构中,为保证num按四个字节对齐, long num; har后必须留出3宁节的空间;同时为保证整个 char nam 结构的自然对齐(这里是4字节对齐),在后还 short int data 要补齐2个字节,这样就是12字节 char ha: 6. struct s1 short ba[5]: inti: 8: p=0×1000000; nt j: 4 p+0x200 int a: 3: Ulong)p+0×200 double b; (char*)p+0X200= 希望各位达人给出答案和原因,谢谢拉 struct s2 解答:假设在32位CPU上, sizeof(long)=4 bytes f(char *)=4 by int ]: 4: sizeof(short int ) =sizeof (short)=2 bytes double b sizeof(char)=1 bytes int a: 3: 由于是4字节对齐, sizeof(struct BBB) of (p) printf("sizeof(s1)=%d\n sizeof(s1)) 4+4+2+1+1/*补齐*/+2*5+2/* printf("sizeof(s2)=%d \n", sizeof(s2)); 补齐*/=24 bytes(经Dev-C++验证) result: 16.24 p=0×1000000; 第一个 struct s1 +0X200 =0X1000000+0X200*24 int i: 8: Ulong)p+0×200= int j: 4 =0X1000000+0X200 int a: 3 (char*)p+0x200= double b: 01000000+0X200*4 相关系列问题 哩论上是这样的,首先是i在相对0的位置,占8a.对 struct s{ char a;intb}; sizeof(s) 位一个字节,然后,j就在相对一个字节的位置, 8;因为当结构体内元素长度都小于处理器位数 由于一个位置的字节数是4位的倍数,因此不用对(32位=4字节)的时候,使以结构体中最长的 齐,就放在那里了,然后是a,要在3位的倍数关数据元素为对齐条件,a按1字节对齐,b按4 系的位置上,因此要移一位,在15位的位置上放字节对齐,所以s默认对其参数为8 下,目前总共是18位,折算过来是2字节2位的 truct At 样子,由于doub|e是8字节的,因此要在相对0 short a 1 要是8个字节的位置上放下,因此从18位开始到 short a2 i hort a 3 QQ: 1 zhangqqgf@ 163 class a{ static int a;}; sizeof(A)=1;对于 sizeof(A)=6;原因同上,结构体按最长元素 静态成员变量是分配在全局存储区的,所以A还 short(2字节对齐)。 是相当于空类 b.对于inta[200]; sizeof(a)=200* class C: public virtual a: sizeof(C)=4 sizeof(int)=800;对整个数组大小评测 对丁虚拟继承的类拥有虚函数表,所以空类C含 nt*a= new int[200]; sizeof(a)=4;对有vptr 指针大小进行评测 e.设有以下说明和定义 char str[=012345 sizeof(str)=7: str typedef union flong i; int k[5]; char c; 是一个字符数组,数组最初大小未定,由具体值 DATE;// sizeof(int) *5=20 "012345"来决定,6* sizeof(char)=6,还有 struct datai int cat, DATE CoW; double 隐含的"\0",所以一共 dog;}too;/4+20+8=32 char str[]="sn"; sizeof(str)=3;回车"\n" DATE max; 是一个字符,可以查看 ASCII表。还有V、等 则语句 printf("%d", sizeof( struct 等字符 date)+ sizeof(max));执行结果是:52 c。这种使用位域的也有,其中元素最大为1字节 对于 union联合来说,取其中最大元素长度来做 大小=8bits,元素按照1字节进行对齐, 为联合大小 sizeof(b)= 1+1(4 bits +2bits <8 bits)+ f使用 malloc戌者new分配内存,void 1(3bits)=3 pp= malloc(10); sizeof(p)=4;跟揞针一 struct b 样, sizeof只能测出静态数组的长度,无法检测动 态分配的或外部数组大小 char a: 8 h.下面函数输出结果:对于 char str[100]或者 char b: 4: char str[]参数都退化为char*st,这样的函数即 char c: 2: 使传入 char s[10]也是可以的 char d: 3: void Func(char str[1001) 写出运行结果: printf( %d\n", sizeof(str)) union vt struct x char s[10];//凶数对数组长度并没有检验 unsigned char s1: 2 Func(s) unsigned char s2: 3 结果: sizeof( charx)=4 unsigned char s3: 3; 如何强制str为100位数组?可以如此声明 }X; char (&str)[100] unsigned char ci 理解顺序:1.str声明为一个引用2.引用一个 100元素数组3.数组元素每个为int大 VC=100 Func(char(&str)[100]) printf(" %d,vxS3) printf("/od\n 100的2进制是1100100去掉后面的5位 余11放入X.S3中结果 har sl100: d.对于空的类进行评测 class a}; sizeof(A)Func(s);∥这里必须给定100位长度char数 =1;默认空类是有一个占位符的 组 对丁虚函数c| ass at virtual test()}; class 结果:100* sizeof(char)=100 B:pub|icA{; sizeof(A)=4; sizeof(B)=4任何 含有虚函数的类捐有一个vptr指针,用来指向虚 函数表 vtable sizeof(vptr)=4 QQ: 1 zhangqqqf@163.com 地保护那些不希望被改变的参数,防止其被无意 const 的代码修改。简而言之,这样可以减少bug的出 1.关键字 const有什么含意? 现 我只要一听到被面试者说:" const意味着常数",答:1)表示常量不可以修改的变量。 我就知道我正在和一个业余者打交道。去年Dan 2)可以修饰参数作为输入参数 Saks己经在他的文章里完全概括了 const的所有 3)修饰函数,防止以外的改动 用法,因此ESP的每一位读者应该非常熟悉4)修饰类的成员函数,不改变类中的数据成员 const能做什么和不能做什么.如果你从没有读到2.cσnst的理解 那篇文章,只要能说出cons意味着"只读"就可以 const char*, char const*,char* const的区别 了。尽管这个答案不是完全的答案,但我接受它问题几乎是C++面试中每次都会有的题目。事 作为一个正确的答案。(如果你想知道更详细的答实上这个概念准都有只是三种声明方式非常相似 案,仔细读一下Saks的文章吧。) 很容易记混。 Bjarne在他的TheC++ 如果应试者能正确回答这个问题,我将问他一个 Programming Language里面给出过一个助记 附加的问题: 的方法:把一个声明从右向左读。 下面的声明都是什么意思? char* const cp;(*读成 pointer to) const int a; cp is a const pointer to char int const a const char来p; const int *a p is a pointer to const char int const a: char const p: int const x a const. 同上因为C++里面没有 const*的运算符,所以 const只能属于前面的类型 前两个的作用是一样,a是一个常整型数。第三个 意味着a是一个指向常整型数的指针(也就是,整3.下述三个有什么区别? 型数是不可修改的,但指针可以)。第四个意思 a char* const p; 是一个扫向整型数的常指针(也就是说,指针指向 har const米p 的整型数是可以侈改的,但指针是不可修改的)。 const char*p 最后一个意味着a是一个指向常整型数的常指针解答: (也就是说,指针指向的整型数是不可修改的,char* const p;/常量指针,p的值不可以修改 同时指针也是不可修改的)。如果应试者能正确回 char const*p;/指向常量的指针,指向的常量 答这些问题,那么他就给我留下了一个好印象。值不可以改 顺带提一句,也许你可能会问,即使不用关键字 const char*p://和 char const*p相司 const,也还是能很容易写出功能正确的程序,那1和2相冋,如果 const位于星号的左侧,则 么我为什么还要如此看重关键宇 const昵呢?我也 const就是用来修饰指针所指向的变量,即指针指 如下的几下理由 向为常量,不能修改指针指向对象的內容 1)关键字 const的作用是为给读你代码的人传达如果cons位于星号的右侧, const就是修饰指针 非常有用的信息,实际上,声明一个参数为常量本身,即指针本身是常量,不能修改指针的指向 是为了告诉了用户这个参数的应用目的。如果你4c0nst与#dene有什么不同 曾花很多时间清理其它人留下的垃圾,你就会很答案:1. const常量有数据类型,而宏没有数据 快学会慼谢这点多余的信息。(当然,懂得用类型。编译器可以对 const常量进行类型检查, const的程序员很少会留下的垃圾让別人来清理而对宏只进行字符替换没有类型检查。 2.有些编译器可以对 const常量进行调 2)通过给优化器一些附加的信息,使用关键字试,但不能对宏常量进行调试 const也许能产生更紧凑的代码 3. const可以用来修饰函数参数、函数返 3〕合理地使用关键字 const可以使编译器很自然回值,C++还可以用来修饰函数,定义内中某个 QQ: 1 zhangqqgf@ 163 成员函数为常量函数 3.一个参数既可以是cons还可以是 volatile吗? 解释为什么 static、 volatile 4.一个指针可以是 volatile吗?解释为什么。 5.下面的函数有什么错误: 1.关键字 static的作用是什么? It square (volatile int *ptr) 竺 1)定文静态局詺变量,作用域从函数开始到结束 return*ptr来*ptr; 2)在模块内的 static函数只可被这一模块内的 其它函数调用,这个函数的使用范围被限制在声 下面是答案 明它的模块内; 1)是的。一个例子是只读的状态寄存器。它是 3)在类中的 static成员变量属于整个类所拥 olatile因为它可能被意想不到地改变。它是 有,对类的所有对象只有一份拷贝 const因为稈序不应该试图去修改它 答案二: 2);是的。尽管这并不很常见。一个例子是当 1).在函数体,一个被声明为静态的变量在这 个屮服务子程序修该一个指向一个 buffer的指针 凼数被调用过程中维持其值不变。 时 2).在模块内(但在函数休外),一个被声明为静3)这段代码有点变态。这段代码的目的是用来返 态的变量可以被模块内所用函数访问,但不能被指针*pt指向值的平方,但是,由于*ptr指向一 模块外其它函数访问。它是一个本地的全局变个 volatile型参数,编译器将产生类似下面的代 量 3).在模块内,一个被声明为静态的函数只可被 int square( volatile int*ptr) 这一模块内的其它函数请用。那就是,这个函数 被限制在声明它的模块的亼地范围内使用。 nt a, b 2关键字voat|e有什么含意?并举出三个不同的 ptr 例子? b=*ptr 答:一个定义为 volatile的交量是说这变量可能会 return a x b 被意想不到地改变,这样,编详器就不会去假设 这个变量的值了。精确地说就是,优化器在用到 由于*ptr的值可能被意想不到地该变,因此a和b 这个变量时必须每次都小心地重新读取这个变量 叮能是不同的。结果,这段代码可能返不是你所 的值,而不是使用俣存在寄存器里的备份。下面 期望的平方值!正确的代码如下: 是 volatile变量的几个例子 long square(volatile int *ptr) 1)并行设各的硬件寄存器(如:状态寄存器) 2)一个屮断服务子程序屮会访问到的非自动变量 int a (Non-automatic variables) 3)多线程应用中被几个任务共享的变量 return a x a 6.下面的函数实现在一个数上加一个数,有什么 错误?请改正 int add_n( int n static int i= 100 return i QQ:107910245 zhangqqgf@ 163 当你第二次调用时得不到正确的结果,难道你写2写一个标准"宏MIN,这个宏输入两个参数并 个函数就是为了调用一次?问题就出在 static上返回较小的一个。 7A.C和B.C两个c文件中使用了两个相同名字的# define min(A,B)(A)<=(B)?(A):(B)) static变量,编译的时候会不会有问题?这两个这个测试是为下面的目的而设的: static变量会保存到哪里(栈还是堆或者其他的)?1)标识# define在宏中应用的基本知识。这是很 tatc的全局变量,表明这个变量仅在本模块中重要的。因为在嵌入( inline)操作符变为标准C 有意义,不会影响其他模块。 的一部分之前,宏是方便产生嵌入代码的唯一方 他们都放在数据区,但是编译器对他们的命名是 法,对丁嵌入式系统来说,为∫能达到娑求的性 不同的。 能,嵌入代码经常是必须的方法 如果要使变量在其他模块乜有意义的话,需要使 2)三重条件操作符的知识。这个操作符存在C语 用 extern关键字 言中的原因是它仗得编译器能产生比if-then-else 8. static变量和 static函数各有什么特点? 更优化的代码,了解这个用法是很重要的。 答∶ static变量:在程序运行期内一直有效,如果3)懂得在宏中小心地把参数用括号括起来 定义在函数外,则在编泽单元内可见,如果在函4)我也用这个问题开始讨论宏的副作用,例如: 数内,在定义的b|ock内可见; static函数:在编当你写下面的代码时会发生什么事? 译单内可见; least MINCp++, b) 9tatc全局变量与普通的全局变量有什么区别?3预处坦器标识# error的目的是什么? static全局变量以能在本模块中调用,伈能在其如果你不知道答案,请看参考文献1。这问题对区 他文件单元中被引用.而仝局变量可以使用 extern分一个正常的伙计和一个书呆子是很有用的。只 在任何地方引用 有书呆子才会读C语言课本的附录去找出象这种 10. static函数与普通函数有什么区别: 问题的答案。当然如果你不是在找一个书呆子, static函数在内存屮只有一份,普通函数在每个那么应试者最好希望自己不要知道答突。 被调用中维持一份拷贝 4用宏定义写出swap(x,y) 程序的局部变量存在于(堆栈)中,仝局变量存在答# define swap(x,y)ⅹ=X+y;y=X-y;x 于(静态区)中,动态申请数据存在于(堆)中。 预处理、宏相关 5.什么是预编泽,何时需要预编译 答:就是指程序执行前的一些预处理工作,主要 1用预处理指令# define声明一个常数,用以表指#表示的 明1年中有多少秒(忽略闰年问题) 何时需要预编译? # define sECoNds Per year(60*60*241)、总是使用不经常改动的大型代码体。 *365)UL 2)、程序由多个模块组戌,所有模块都使用一组 我在这想看到几件事情: 标准的包含文件和相同的編译选项。在这种情况 1)# define语法的基本知识(例如:不能以分号,可以将所有包含文件预编译为一个预编译 结束,括号的使用,等等) 头 2)懂得预处珥器将为你计算常数表达式的值,因6.写一个标准"宏,这个宏输入两个参数并返回 此,直接写出你是如何计算一年中有多少秒而不较小的一个。 是计算出实际的值,是更清晰而没有代价的 答# define min(x,Y)(X)(Y)?(Y):(X)∥/结 3)意识到这个表达式将使一个16位机的整型数没有; 溢出-因此要用到长整型符号L,告诉编译器这个常1.宏是方便的产生嵌入代码的唯一方法 数是的长整型数。 2.三重条件操作符对编泽器米说可以产生比 4)如果你在你的表达式中用到UL(表示无符号长f-hen-else史优化的代码。 整型),那么你有了一个好的起点。记住,第一印3.必须把宏中的参数用括号括起来 象很重要。 7. Typedef Typedef在C语言中频繁用以声明一个己经存在 QQ:107910245 zhangqqqf@163.com 的数据类型的同义字。也可以用预处理器做类似由于 unsigned char的取值范围在(0.255),++ 的事。例如,思考一下下面的例子: 以后ⅰ又为0了.无艰循环下大 #define dps structs xk 11.内联函数和宏的差别是什么? typedef struct s tP 答案:內联函数和普通函数相比可以加快程序运 以上两种情况的意图都是要定义dPS和tPS作行的速度,因为不需要中断调用。编译时内联函 为一个指向结构s指针。哪种方法更好呢?(如果数代码直接嵌入到日标代码中,而宏只是字符替 有的话)为什么? 换。内联函数要做类型检査,相对于宏更安全可 这是一个非常微妙的问趣,任何人答对这个问题靠 (正当的原因)是应当被恭喜的。答案是 inline只用于如下情况:; typed更好。思考卜面的例子 1.一个函数被不断调用。 dPS p1, p2 2.函数只有简单的几行,且函数内不包含 tPs p3, p4 for、 while、 switch等语句 第一个扩展为 struct s* p1, p2 编译调试相关 上面的代码定义p1为一个指向结构的指,p2为1.请间下列表达式哪些会被编译器禁止?为什 个实际的结构,这也许不是你想要的。第二个么? 例子正确地定义了p3和p4两个指针 int a=248: b=4 int const c=21 const int 8.已知一个数组tabe,用一个宏定义,求出数据*d=&a 的元素个数 int *const e=&b; int const *f const =&a: *define ntbl 答:米C=32;d=&b;*d=43;e=34;:e=&a;f=0X #define ntbl 321f; sizeof(table)/sizeof(table[O]) *C这是个什么东东,禁止 9.以下是求一个数的平方的程序,请找出错误: *d说」是 const,禁止 #define square(a((a (a) e=&a说了是 const禁止 nt a=5 const* F const=&a;禁止 int b: 2. ASSERT()是干什么用的 b=SQUARE(a++) 答: ASSERT()是一个调试程序时经常使用的宏, 10.下面这个程序执行后会有什么错误或者效果 在程序运行时它计算括号内的表达式,如果表达 tdefine max 255 式为 FALSE(0),程序将报告错误,并终止执行 int maino 如果表达式不为0,则继续执行后面的语句,这个 宏通常原来判断程序中是否出现∫明显非法的数 unsigned char A[MA×],i;/i被定义为据,如果出现了终止程序以免导致严重后果,同 unsigned char 时也使于查找错误。例如,变量n在程序中不应该 for (i=0; i<=MAX; i++) 为0,如果为0可能导致错误,你可以这样写程 A[i=i 序 解答:死循环加数组越界访问(C/C十十不进行数 ASSERT(n!=0); 组越界检查) k=10/n; MAX=255 数组A的下标范围为:0.MAX1,这是其 ASSERT只有在 Debug版 其二.当ⅰ循环到255时,循环内执行 为 Release版本则被忽咯。 A[255]=255; aset(的功能类似,它是 ANSI C标准中规定的 这句本身没有间题…但是返同f0函数,它与 ASSERT的一个重要区别是可以用在 (i=0;<=MAx;i++)语句时, Release版本中。 QQ:107910245 10 zhangqqgf@ 163 3.C/C++编译器中虚表是如何完成的? 内引用这个变量时,会用到同名的局部变量,而 4.分析下面的代码 不会用到全局变量。对于有些编译器而言,在同 char *a= hello" 个函数内可以定义多个同名的局部变量,比如 hello" 在两个循环体內都定义一个同名的局部变量,而 if(a==b) 那个局变量的作用域就在那个循坏体内。 printf( YeS )i 2.引用一个已经定义过的全局变量? else 答: extern可以用引用头文件的方式,也可以 printf( no"); 用 extern关键字,如果用引用头文件方式来引用 这个简单的面试题目,我选输出no(对比的应该是某个在头文件屮声明的全局变理,假定你将那个 指针地址叫),叫在VC是YES在C是NO 编写错了,那么在编译期间会报错,如果你用 z的呢,是一个常量字符串。位于静态存储区, extern方式引用时,假定你犯了同样的错淏,那 它在稈序生命期内恒定不变。如果编译器优化的 么在编译期间不会报错,而在连接期间报错。 话,会有可能a和b同时指向同一个helo的。则3. static全局变量与普通的全局变量有什么区别? 地址相同。如果编译器没有优化,那么就是两个 static局部变量和普通局部变量有什么区别? 不同的地址,则不同 static函数与普通函数有什么区别? 5.分析输出 答:1)全局变量(外部变量)的说明之前再冠 include <stdio.h> 以 static就构成了静态的全局变量。全局变量本 void foo int m, int n) 身就是静态存储方式,静态全局变量当然也是静 态存储方式。这两者在存储方式上并无不同。这 printf("m=%d, n=%d\n,m, n); 两者的区别在于非静态全局变量的作用域是整个 源程序,当一个源程序由多个源文件组成时,非 int maino 静态的全局变量在客个源文件屮都是有效的。而 静态全局变量则限制了其作用域,即只在定义该 int b= 3 变量的源文件内有效,在同一源程序的其它源文 foo(b+=3,++b); 件中不能使用它。由于静态全局变量的作用域局 printf( b=%/od\n"b) 狠丁一个源文件内,只能为该源文件内的函数公 return o 用,因此可以避免在其它源文件屮引起错误。 2)从以上分析可以看出,把局部变量改变为 输出:m=7,n=4,b=7(VC6.0) 静态变量后是改变了它的存储方式即改变了它的 这种方式和编译器中得函数调用关系相关即先后生存期。把全局变量改变为静态变量后是改变了 入栈顺序。不过不同编译器得处理不同。也是因它的作用域,限制」它的使用范围。 为C标准中对这种方式说明为未定义,所以各个 3) static函数与普通函数作用域不同,仅在本 编译器厂商都有自已得理解,所以最后产生得结文件。只在当前源文件中使用的凶数应该说明为 果完全不同。 内部函数( static),内部函数应该在当前源文件中 因为这样,所以遇见这种函数,我们首先要考虑说明和定义。对于可在当前源文件以外使用的函 我们得编详器会如何处理 数,应该在一个头文件中说明,要使用这些函数 这样得函数,其次看函数得调用方式,不同得调的源文件要包含这个头文件 用方式,可能产生不同得结果。最后是看编译器综上所述 优化 static全局变量与普通的全局变量有什么区 变量相关 别: tatic全局变量只初使化一次,防止在其他文 1局部变量能否和仝局变量重名? 件单元中被引用 答:能,局部会屏蔽全局。要用全局变量,需要 static局部变量和普通局部变量有什么区别: 使用"::";局部变量可以与全局变量同名,在函数

...展开详情
img
ling_biao
  • 签到新秀

    累计签到获取,不积跬步,无以至千里,继续坚持!

关注 私信 TA的资源

上传资源赚积分,得勋章
相关内容推荐