返回信息流好久没有新帖。来娱乐一下
0. C/C++标准规定,源代码应当以ASCII编码保存在文件里,以便编译器编译。所以,把源代码用ms word编辑,存成.doc文件,或者用Windows画图板画一个源代码,如下图,都不是合法的C/C++程序。
1. C/C++标准规定,一个char占1字节,一个short或者int占2字节,long占4字节。
2. C/C++标准规定,一个char占1字节,一个short占2字节,一个int或者long占4字节,一个long long占8字节。
3. C/C++标准规定,一个char占1字节,一个short占2字节,一个int占4字节,一个long或者long long占8字节。
4. 对于char, short, int或者long来说,如果没有加unsigned标注,就是有符号的。
5. float和double采用IEEE754浮点数格式。
6. 有符号整数采用补码(2's complement)表记法
7. 因为上述原因,如果int占4字节,那么有符号int数2147483647(2的31次方减1)再加1,结果是-2147483648。
8. 因为上述原因,只要x是有符号的,编译器就不可以假设x<x+1这样的表达式永远为真,因为x+1有可能突然变成负的。
9. 因为上述原因,可以用判断符号的方法判断有符号整数是否溢出,如:
void f(int x, int delta) {
assert(x>=0 && delta>=0);
if (x + delta < 0) {
printf("Overflow!\n");
exit(1);
}
// continue from here...
}
10. 整数除以0的行为是:运行时报错,并立即退出程序。
11. 因为上述原因,应当在计算除法之前判断除数是否为零,这样就可以避免运行时出错,即:
int x = ..., y = ...;
if (y != 0) {
return x / y; // 这行是安全的,因为y不可能为0。
}
12. 一个IEEE754的浮点数并不表示一个数,而是表示一个范围。
13. IEEE754浮点数的计算,比如加、减、乘、除、开平方、FMA(fma(a,b,c) = a * b + c),都不一定精确。就算其数学结果可以用和参数相同的IEEE754格式表示,在不同的机器上执行的结果也可能不一样。所以,像5.0 + 3.0 == 8.0这样的表达式有可能为假。
14. 对于32位整数x,移位运算x<<32的结果是0,因为所有的位都移出去了。
15. 类似地,x << (-2)相当于x>>2。
16. register关键字的作用是指定某些变量存放在寄存器里。如果不使用register关键字,那么变量就存放在内存里。
17. C/C++求表达式的值时,按先左后右,由里而外的原则。如果表达式有副作用(如i++),那么副作用发生的时间和表达式求值相同。
18. C/C++的程序,在函数调用时,函数的参数按从右往左的顺序压到栈上,被调函数从栈上获取参数。
19. 指针就是地址。
20. 指针访问的效率比数组下标访问更高,因为少一次下标运算。比如,下面函数g的效率高于f。
int f(int ar[], int sz) {
int i, sum = 0;
for(i=0;i<sz;i++) { sum += ar[i]; }
return sum;
}
int g(int ar[], int sz) {
int sum = 0, *p, *p2 = ar+sz;
for(p=ar;p<p2;p++) { sum += *p; }
return sum;
}
21. 结构(struct)的大小是各个成员的大小的总和。如果int是4字节,char是1字节,那么struct{char a; int b;}占5字节。
22. 拥有0个元素的数组(如char data[0])很有用。它可以作为结构的最后一个成员,如struct foo { int a,b,c; char data[0]; }。C/C++标准允许这种数组并为这种结构开了一个特例:指向它的指针可以指向那个数组元素长度是任意长度结构,如,可以指向struct bar { int a,b,c; char data[1024]; }
23. 如果f是函数,那么,指向它的指针是&f,而f表示那个地址处的数据。因此,下面的程序是错误的:
int f(int n) { return n + 1; }
int main() {
int (*fp)(int);
fp = f; // 错误。fp会从函数f的代码处读取8个字节(或者4个,取决于指针长度)存在fp里。
int result = fp(100); // 运行时出错
}
24. printf,scanf等IO函数都不是线程安全的。如果在不同的线程里调用这些函数而没有使用锁等同步机制,是未定义行为,即,从什么也不发生到机器冒烟都可能发生。
25. main函数的返回值类型是int。因此如果执行到main的末尾却没有执行到return语句,是未定义行为,即,从什么也不发生到机器冒烟都可能发生。
26. 局部变量如果没有初始化就读取,结果是任意值。【已修正,现专门说“局部变量”】
27. C++的特色是面向对象编程。它有object的概念,即:一个数据和操作的结合体,具有继承、封装、多态的特性。
28. 相对地,C是一个面向过程的语言,它并没有object的概念。
29. 用//注释是C++的特性,很多C语言编译器都支持,但并没有被标准化。
30. const表示一个存储空间不能改变,但C++拥有const_cast,所以还是可以改变的,如下面程序(摘自某公司面试题):
int main() {
const int a = 42;
int *b = const_cast<int*>(&a);
*b = 43;
cout<<a<<endl; // 43
}
31. new,new[],malloc都是用来分配内存的。分配出来的内存用delete,delete[]和free回收都可以。
32. 类的大小的计算方法和struct类似,为各个成员(含当前类和所有祖先类的成员)大小的总和。【已修正,强调包含当前类和所有祖先】
33. 异常处理(即try{...}catch(...){...})会影响正常程序的性能,因为进入try块执行之前必须保存一些上下文,以便异常发生的时候恢复。所以异常处理一定会在正常的执行路径中做额外的工作。对于性能很重要的程序,应当用返回特殊值的方法处理异常情形。
34. 如果整个栈上没有任何函数可以捕获异常,那么C++会执行每个函数里的局部变量析构函数,然后强行终止程序。例如:main函数调用f,f调用g,g调用h,h抛出了异常,但h,g,f,main中都没有try-catch块能够抓住这个异常,那么C++会顺次执行h,g,f,main里局部变量的析构函数,然后强行终止。【已修正:新添加了例子】
35. 因为上述原因,如果用ofstream这样有析构函数的对象打开文件,那么程序因未捕获的异常而退出之前可以保证文件被关闭。
36. 一些工程可能同时用到C和C++语言。因为C++兼容C,所以,在C++程序里,只要用和C++函数同样的方法声明了C的函数,就可以调用该函数。如下:
// foo.c
int foo(int x) { return x + 1;}
// bar.cpp
int foo(int x); // 声明
void bar() {
int x = 10;
int y = foo(x); // 调用
}
37. vector类内部动态地维护一个数组。为了性能,vector在删除元素时只是修改一个界限指针,并不会把值从vector中去掉。所以,下面的程序总能打印出删除以前的值:
vector<int> a = {10, 20, 30, 40};
int *p = &a[3];
a.pop_back();
cout<<*p<<endl; // 这个是安全的,打印40。
38. string类通过copy-on-write高效实现字符串拷贝。在实际应用中,往往只有<1%的string赋值表达式真的造成了深拷贝。【这道题出得不太好,太经验化了,没有绝对的答案……大家自己估计吧。】
39. unique_ptr唯一地拥有一个指针,当它被赋值给另一个unique_ptr时,由于所有权转移,当前unique_ptr不再拥有该指针。所以,想操作该unique_ptr指向的内存,必须先获取它的所有权,而不可以在没有所有权的情况下绕开unique_ptr操作该内存。
40. 多线程是由计算机硬件以及操作系统实现的,和编程语言并没有太大关系。所以,即使编程语言不支持多线程(如C11和C++11之前的C/C++版本,或者别的语言,如lua),只要链接到多线程库(如pthread)并调用相关的API函数,就可以正确实现多线程了。
41. 多个线程可以被任意调度,谁先执行谁后执行,或者如何交错执行,是不一定的。但一个多线程的程序执行的结果,总是相当于各个线程执行的各个操作按某个顺序串起来一样。
42. 垃圾回收性能很差,其中一个原因是“堆”是中心资源,多个线程同时分配会造成大量阻塞,所以无法在多线程并行程序中很好地工作(这是Bjarne Stroustrup的原话,但正确性请读者自行判断)。
43. 因为垃圾回收性能很差,为了提高性能和内存管理效率,应当使用C/C++这样的非垃圾回收的语言。如果把一个需要大量new和delete的大型项目移植到有垃圾回收的语言上,往往性能会大幅度降低,其中垃圾回收是一大瓶颈。
就这些吧,祝各位爷玩儿得爽~[ema28]
答案:以上选项全部都是错的
这是一条镜像帖。来源:北邮人论坛 / cpp / #89925同步于 2016/1/16
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
Quiz:下面关于C/C++的说法,哪些是错误的?
nuanyangyang
2016/1/16镜像同步29 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
暖神。给跪。。
回答一个:如果用new[]来分配内存, 用delete或者free来释放都会出错。。一定要用delete[]
还有:移位的右操作符不能是负数。。。
0. C/C++标准规定,源代码应当以ASCII编码保存在文件里,以便编译器编译。所以,把源代码用ms word编辑,存成.doc文件,或者用Windows画图板画一个源代码,如下图,都不是合法的C/C++程序。
不知道
1. C/C++标准规定,一个char占1字节,一个short或者int占2字节,long占4字节。
不记得有这个规定
2. C/C++标准规定,一个char占1字节,一个short占2字节,一个int或者long占4字节,一个long long占8字节。
不记得有这个规定
3. C/C++标准规定,一个char占1字节,一个short占2字节,一个int占4字节,一个long或者long long占8字节。
不记得有这个规定
4. 对于char, short, int或者long来说,如果没有加unsigned标注,就是有符号的。
个人觉得,是的
5. float和double采用IEEE754浮点数格式。
我见过的是这么表示的
6. 有符号整数采用补码(2's complement)表记法
是的
7. 因为上述原因,如果int占4字节,那么有符号int数2147483647(2的31次方减1)再加1,结果是-2147483648。
不是
8. 因为上述原因,只要x是有符号的,编译器就不可以假设x<x+1这样的表达式永远为真,因为x+1有可能突然变成负的。
不是
9. 因为上述原因,可以用判断符号的方法判断有符号整数是否溢出,如:
不是
10. 整数除以0的行为是:运行时报错,并立即退出程序。
不是
11. 因为上述原因,应当在计算除法之前判断除数是否为零,这样就可以避免运行时出错,即:
x = INT_MIN; y = -1; 会发生什么呢?
12. 一个IEEE754的浮点数并不表示一个数,而是表示一个范围。
可以这么理解吧
13. IEEE754浮点数的计算,比如加、减、乘、除、开平方、FMA(fma(a,b,c) = a * b + c),都不一定精确。就算其数学结果可以用和参数相同的IEEE754格式表示,在不同的机器上执行的结果也可能不一样。所以,像5.0 + 3.0 == 8.0这样的表达式有可能为假。
貌似是的
14. 对于32位整数x,移位运算x<<32的结果是0,因为所有的位都移出去了。
不好说,看起来像是未定行为,c语言怎么会规定这么无聊的事情呢
15. 类似地,x << (-2)相当于x>>2。
同上
16. register关键字的作用是指定某些变量存放在寄存器里。如果不使用register关键字,那么变量就存放在内存里。
只能说期待编译器这样做,它不做你又有什么办法呢。
17. C/C++求表达式的值时,按先左后右,由里而外的原则。如果表达式有副作用(如i++),那么副作用发生的时间和表达式求值相同。
不是吧
18. C/C++的程序,在函数调用时,函数的参数按从右往左的顺序压到栈上,被调函数从栈上获取参数。
__fastcall/__stdcall/__thiscall/__cdecl 。。。。
19. 指针就是地址。
没这么浅薄吧
20. 指针访问的效率比数组下标访问更高,因为少一次下标运算。比如,下面函数g的效率高于f。
听说有个东东叫SIB
21. 结构(struct)的大小是各个成员的大小的总和。如果int是4字节,char是1字节,那么struct{char a; int b;}占5字节。
不是吧
22. 拥有0个元素的数组(如char data[0])很有用。它可以作为结构的最后一个成员,如struct foo { int a,b,c; char data[0]; }。C/C++标准允许这种数组并为这种结构开了一个特例:指向它的指针可以指向那个数组元素长度是任意长度结构,如,可以指向struct bar { int a,b,c; char data[1024]; }
没有考虑过这个事,待查
23. 如果f是函数,那么,指向它的指针是&f,而f表示那个地址处的数据。因此,下面的程序是错误的:
函数指针不是这样的。
24. printf,scanf等IO函数都不是线程安全的。如果在不同的线程里调用这些函数而没有使用锁等同步机制,是未定义行为,即,从什么也不发生到机器冒烟都可能发生。
不是很了解,不过我没遇到多线程printf出错。。。
25. main函数的返回值类型是int。因此如果执行到main的末尾却没有执行到return语句,是未定义行为,即,从什么也不发生到机器冒烟都可能发生。
至少返回值是未定义的
26. 变量如果没有初始化就读取,结果是任意值。
你得看是什么变量吧
27. C++的特色是面向对象编程。它有object的概念,即:一个数据和操作的结合体,具有继承、封装、多态的特性。
对呀
28. 相对地,C是一个面向过程的语言,它并没有object的概念。
个人觉得,是的
29. 用//注释是C++的特性,很多C语言编译器都支持,但并没有被标准化。
不知道
30. const表示一个存储空间不能改变,但C++拥有const_cast,所以还是可以改变的,如下面程序(摘自某公司面试题):
是
31. new,new[],malloc都是用来分配内存的。分配出来的内存用delete,delete[]和free回收都可以。
配对使用
32. 类的大小的计算方法和struct类似,为各个成员大小的总和。
类的大小计算,要考虑自己和父类的情况
33. 异常处理(即try{...}catch(...){...})会影响正常程序的性能,因为进入try块执行之前必须保存一些上下文,以便异常发生的时候恢复。所以异常处理一定会在正常的执行路径中做额外的工作。对于性能很重要的程序,应当用返回特殊值的方法处理异常情形。
貌似是?
34. 如果整个栈上没有任何函数可以捕获异常,那么C++会执行每个函数里的局部变量析构函数,然后强行终止程序。
没太明白什么意思
35. 因为上述原因,如果用ofstream这样有析构函数的对象打开文件,那么程序因未捕获的异常而退出之前可以保证文件被关闭。
RAII
36. 一些工程可能同时用到C和C++语言。因为C++兼容C,所以,在C++程序里,只要用和C++函数同样的方法声明了C的函数,就可以调用该函数。如下:
name mangling
extern "C"
37. vector类内部动态地维护一个数组。为了性能,vector在删除元素时只是修改一个界限指针,并不会把值从vector中去掉。所以,下面的程序总能打印出删除以前的值:
stl的实现又不是一种,我高兴我也可以写一个,怎么敢这么做呢。
38. string类通过copy-on-write高效实现字符串拷贝。在实际应用中,往往只有<1%的string赋值表达式真的造成了深拷贝。
不知道小于多少。。。
39. unique_ptr唯一地拥有一个指针,当它被赋值给另一个unique_ptr时,由于所有权转移,当前unique_ptr不再拥有该指针。所以,想操作该unique_ptr指向的内存,必须先获取它的所有权,而不可以在没有所有权的情况下绕开unique_ptr操作该内存。
绕开?想访问怎么都有办法的,又不是做了隔离
40. 多线程是由计算机硬件以及操作系统实现的,和编程语言并没有太大关系。所以,即使编程语言不支持多线程(如C11和C++11之前的C/C++版本,或者别的语言,如lua),只要链接到多线程库(如pthread)并调用相关的API函数,就可以正确实现多线程了。
不太了解
41. 多个线程可以被任意调度,谁先执行谁后执行,或者如何交错执行,是不一定的。但一个多线程的程序执行的结果,总是相当于各个线程执行的各个操作按某个顺序串起来一样。
听起来是这样的啊
42. 垃圾回收性能很差,其中一个原因是“堆”是中心资源,多个线程同时分配会造成大量阻塞,所以无法在多线程并行程序中很好地工作(这是Bjarne Stroustrup的原话,但正确性请读者自行判断)。
没研究过,但是malloc什么的多线程时不是每个线程分自己的嘛
43. 因为垃圾回收性能很差,为了提高性能和内存管理效率,应当使用C/C++这样的非垃圾回收的语言。如果把一个需要大量new和delete的大型项目移植到有垃圾回收的语言上,往往性能会大幅度降低,其中垃圾回收是一大瓶颈。
大量的new和delete用c/c++来做,也要慎重啊。
【 在 zx723 的大作中提到: 】
: 0. C/C++标准规定,源代码应当以ASCII编码保存在文件里,以便编译器编译。所以,把源代码用ms word编辑,存成.doc文件,或者用Windows画图板画一个源代码,如下图,都不是合法的C/C++程序。
: 不知道
: 1. C/C++标准规定,一个char占1字节,一个short或者int占2字节,long占4字节。
: ...................
做得不多。对对答案吧。
26、32、34我叙述得有点不严谨,修正了。38题出得不太好,就都算对吧。
【 在 nuanyangyang 的大作中提到: 】
:
: 做得不多。对对答案吧。
: 26、32、34我叙述得有点不严谨,修正了。38题出得不太好,就都算对吧。
显然我只是个初学者,距离语言律师还有很远的路。。。