2016/10/30 C++/C错题

本文详细解析了C++编程中的各类技巧与注意事项,包括位运算、引用行为、内存对齐规则、函数重载与覆盖的区别等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下一些答案解析转自牛客网牛友的分析,侵删

int a =1,b =32 ;
printf("%d,%d",a<<b,1<<32);

答案:10
执行a<<b时,编译器会先将b与31进行and操作,以限制左移的次数小于等于31。b&31=0,则a<<b=1
执行1<<32时,编译器直接执行算术左移的操作。
char *p="hello"; return p == "hello";
C项:p存的是常量字符串“hello”的地址,p=="hello"的值是1。如果改为char p[ ]="hello",那p=="hello"的值就是0。因为此时p指向了一段(新开辟的)长度为6字节的内存区域,存储的值是“hello”的拷贝(也就是说不是原来的常量字符串)。
如果再修改为char p[ ]="hello"returnstrcmp(p,“hello”));则又返回1
如果MyClass为一个类,执行”MyClass a[5], *b[6]”语言会自动调用该类构造函数的次数是()

MyClass a[5],会创建5个对象,所以会自动调用5次构造函数,但是MyClass *b[6],这不会自动调用构造函数,因为这是声明一个指向6个元素的数组的指针,指针声明的时候是不分配空间的,所以不会调用构造函数,没有指向一个有效的内存空间。
关于引用以下说法错误的是()。
正确答案: E   你的答案: B (错误)

引用必须初始化,指针不必
引用初始化以后不能被改变,指针可以改变所指的对象
不存在指向空值的引用,但是存在指向空值的指针
一个引用可以看作是某个变量的一个“别名”
引用传值,指针传地址
函数参数可以声明为引用或指针类型




首先,E明显是不对的。引用也是传递的地址,否则你在函数内部操作的就不可能是实参,而只能是形参。实参的内容是不会改变的。其次B项说法不明确,“引用初始化以后不能被改变 ”有歧义。如果已有&a = b; 则不能再有&a = c;  若b = 2; &a = b; a = 5;则是可以的,b的值也将被赋为5。考虑到B项后面又说:“指针可以改变所指的对象 ”,该题考察的应该是前一种意思。综上所诉,选E
在linux下64位c程序,请计算输出的三个sizeof分别是()

void func(char str_arg[100])
{
     cout<<sizeof(str_arg)<<endl;
}
int main(int argc,char* argv[])
{
     char str[]="Hello";
     char *p=str;
     cout<<sizeof(str)<<endl;
     cout<<sizeof(p)<<endl;
     func("test");
     return 0;
}
答案:688
sizeof对数组求长度为数组的真实长度,字符串数组的长度要加上最后的'\0'字符。
最后一个:数组作为函数的参数传递时,char str_arg[100]实际为 char *str_arg,传递的是指向数组首元素的指针 sizeofchar *str_arg)=864位)
static int a=1;
void fun1(void)
{
    a=2;
}
void fun2(void)
{
    int a=3;
}
void fun3(void)
{
    static int a=4;
}
int main()
{
  printf(“%d”,a);
  fun1( );
  printf(“%d”,a);
  fun2( );
  printf(“%d”,a);   
  fun3( )
  printf(“%d”,a); 
}
正确答案: B   你的答案: A (错误)

1 2 3 4
1 2 2 2
1 2 2 4
1 1 1 4

首先声明了一个静态全局变量i,首次输出我就不说了,妥妥的1。第二次输出,访问到了早已定义的全局变量i,并改写值,第二次为2。第三次输出,内部定义了一个同名的变量, 它并没有返回值或者被该次执行程序以外任何程序读取a值,所以第三次输出仍然是a。第四次输出,定义了一个静态的局部变量,静态局部变量在函数调用结束后仍然存在,及它的内存空间不会被释放,但其他函数是不能引用它的,所以,两个静态变量虽然同名,但是并不是一样的东西,为2。答案是B
64位系统中,有如下类:
class C
{
public:
    char a;
    static char b;
    void *p;
    static int *c;
    virtual void func1();
    virtual void func2();
};
那么sizeof(C)的数值是()
正确答案: D   你的答案: A (错误)

9
17
32
24

应该是D
sizeof(类)计算的是类中存在栈中的变量的大小,而类中的b和*c都是static静态变量,存在全局区中,因此不在计算范围之内,于是只剩下char a,void *p和两个virtual虚函数,a是char类型,占用一个字节,p是指针,在64位系统的指针占用8个字节,而两个虚函数只需要一个虚函数表指针,也是八个字节,加上类中的对齐方式(char a对齐时后面补上7个字节),故答案为24.


虽然大家选的D,但是看分析居然很不一样。。首先需要明确几点:
1 sizeof是用来计算栈大小,不涉及全局区,故类的静态成员大小sizeof不涉及。
2 本题中的虚函数属于同一个类,故只需要一个指针指向虚函数表,所以在64位系统中占用8个字节。就算本题有100个虚函数,那么也只占用8个字节。
综上,占用栈空间的成员有:a, p, func1, func2,由于64位对其,故总空间为8+8+8=24字节。
以下代码有什么问题?

struct Test
 {
     Test( int ) {}
     Test() {}
     void fun() {}
 };
 void main( void )
 {
     Test a(1);
     a.fun();
     Test b();
     b.fun();
 }

正确答案: A   你的答案: C (错误)

b.fun()会出错
Test结构的定义中应该加上public修饰符,这样才能main函数中调用改类的方法
Test(int){} 应该改成Test(int a){}
以上说法都不正确


Test a(1); //新建了一个对象
a.fun(); //因此可以调用函数
Test b(); //声明了一个函数,并没有新建对象
b.fun(); //没有新建对象,则不能调用函数



A  Test b(); 
 request for member 'fun' in 'b', which is of non-class type 'Test()'
默认构造函数直接写 Test b;就可以


其实Test b();并不会出错,只不过是声明了一个函数b返回类型为Test,但是b.fun()会出错
void swap_int(int *a,int *b){
  *a=*a+*b;
  *b=*a-*b;
  *a=*a-*b;
}
以下说法正确的是:
结果不正确,因为会溢出,用位与的方式就没问题
结果正确,即使会溢出
结果正确,不会溢出
其他选项都不对

此题可以参考《深入理解计算机》P58页习题2.30
大致思路:即使会产生溢出,但是运算法则仍然成立,举个例子,假设int只有4bit,那么-8 + (-5) = -13(溢出), 实际结果为3,而3-(-8) = 11(依然溢出),实际结果是-5,
所以,swap程序中的第二句: *b=*a-*b,相当于*b = *a+*b-*b;溢出并没有影响。
下面有关回调函数的说法,错误的是?
正确答案: C   你的答案: 空 (错误)

回调函数就是一个通过函数指针调用的函数
回调函数可能被系统API调用一次,也可能被循环调用多次
回调函数本身可以是全局函数 ,静态函数和某个特定的类的成员函数
回调函数可用于通知机制
添加笔记
收藏
纠错
本题知识点



考察点:this指针

核心就是类成员函数需要this指针访问函数,而全局或者静态函数不需要this指针。
简言之,类的成员函数需要隐含的this指针 而回调函数没有办法提供。

基础概念:
      回调函数就是一个通过函数指针调用的函数。
       如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
       回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。


参考讨论:
http://bbs.youkuaiyun.com/topics/380257801
http://baike.baidu.com/view/414773.htm
编辑于 2015-02-02 15:47:36
类成员函数的重载、覆盖和隐藏区别描述正确的有?
正确答案: C D   你的答案: D (错误)

覆盖是指在同一个类中名字相同,参数不同
重载是指派生类函数覆盖基类函数,函数相同,参数相同,基类函数必须有virtual关键字
派生类函数与基类函数相同,但是参数不同,会"隐藏"父类函数
函数名字相同,参数相同,基类无virtual关键字的派生类的函数会"隐藏"父类函数
添加笔记
收藏
纠错
本题知识点

C/C++  微软
参考解析 添加解析
52

推荐
Python头像Python
CD
答案:
a.成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4virtual 关键字可有可无。
b.覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
编辑于 2016-01-11 13:56:58
分析以下函数,该函数的功能是()

void sca_from_file(int a[], int n, char fn[])
{
    FILE *fp;
    int i;
    fp = fopen(fn, "r");
    for (i = 0; i < n; i++)
    {
        fscanf(fp, "%d", &a[i]);
    }
    fclose(fp);
}
正确答案: A   你的答案: B (错误)

打开文件fn,从文件中读出n个整数到数组a中
打开文件fn,将数组a的n个元素写到文件中
打开文件fn,从文件中读出n,再读n个整数到数组a中
打开文件fn,将n和数组a的n个元素依次写到文件中
fscanf()作用是从文件流中读取数据,fprintf()是将数据写入到文件。不要搞混。
格式:int fscanf(FILE*stream,constchar*format,[argument...]);
参数:%d:读入一个十进制整数.
%s : 读入一个字符串,遇空字符‘\0'结束。
%c : 读入一个字符。无法读入空值。空格可以被读入。
所以这里是从文件中读出n个整数到数组a中
考虑函数原型void hello(int a,int b=7,char* pszC="*"),下面的函数调用钟,属于不合法调用的是
正确答案: C   你的答案: B (错误)

hello(5)
hello(5,8)
hello(6,"#")
hello(0,0,"#")
添加笔记
收藏
纠错
本题知识点

C/C++  腾讯
参考解析 添加解析
17

推荐
小雨落梧桐头像小雨落梧桐
C.  默认参数 是从 左往右依次赋值.所以C不对.

补充. 1. 默认参数严格遵守从左往右赋值
      2. 在定义函数原型的时候,如果一个参数有默认值,后面一个参数也必须有默认值,比如本题void hello(int a, int b = 7, char *pszC);  这样是不行的,因为 b 的后一个参数没有默认值.
      3.一般把函数的默认参数在函数声明中声明,一般函数声明在.h的头文件里面.如果在函数定义中声明默认参数,那么只能在这个cpp文件中使用. 原因是,你在其它地方使用链接到头文件中并没有关于默认参数的声明
      4.函数重载时候要注意,比如void fun(int a), 重载一个函数void fun(int a, int b = 1);你调用时候写   fun(1); 编译器也不知道你要用哪个,造成混淆.所以要避免这样产生混淆的使用 
两个线程并发执行以下代码,假设a是全局变量,初始为1,那么以下输出______是可能的?
1
2
3
4
void foo(){
    ++a;
    printf("%d ",a);
}
正确答案: A B C D   你的答案: B (错误)

3 2
2 3
3 3
2 2
添加笔记
求解答(45)
收藏
纠错
本题知识点

操作系统  并发  C/C++  阿里巴巴
假设线程x和y同时执行,x和y可随时被抢占,a的初始值为1

A3, 2
y先执行++aa2;
y再执行printf,a入栈,在打印到终端之前切换到x
x执行++aa3;
x执行printf,输出3;再切换到y
y执行打印,输出2

B:2 3
x先执行++aa2;
x再执行printf,输出2;切换到y
y执行++aa3;
y执行printf,输出3;

C:3 3
x先执行++aa2;切换到y
y执行++aa3;
y执行printf,输出3;切换到x
x执行printf,输出3

D:2 2
类似C,a的初始值为0即可

这里关键有两点:
(1)两个线程可随时被抢占
(2)++a和printf不是原子指令,可随时被打断;特别注意函数printf,a作为参数压栈后,a再变化则不会影响输出(printf实际打印的是压栈的参数,是值拷贝的栈变量)
C语言程序中,运算对象必须是整型数的运算符是?
正确答案: C   你的答案: A (错误)

&&
/
%
*
添加笔记
收藏
纠错
本题知识点

C/C++
参考解析 添加解析
2

推荐
野猪头像野猪
%取余运算是二目运算符,且要求运算对象必须为整数,所以选C。
编辑于 2015-02-03 20:53:37 回复(0)
更多回答(3条)
1

牛客896934号头像牛客896934号
怎么能对一个小数取余呢
C++是否支持嵌套函数定义,如下代码所示?
fun1() { 
    fun2() { 
        fun3() { 
        } 
    }
}
函数可以嵌套调用,但不可以嵌套定义。
这里是三层嵌套,所以不包括内联函数
在重载一个运算符为成员函数时,其参数表中没有任何参数,这说明该运算符是 ( )。
正确答案: C   你的答案: D (错误)

无操作数的运算符
二元运算符
前缀一元运算符
后缀一元运算符
添加笔记
求解答(10)
收藏
纠错
本题知识点

C/C++
共有3条讨论 添加解析
28

Delia头像Delia
首先可以判断是一元操作符。

因为++和--有前缀和后缀两种形式,为了区分,要求在后缀形式加一个int参数。  const Fraction operator ++(int)   中 int不过是个哑元(dummy),是永远用不上的,它只是用来判断++是prefix  还是  postfix  。如果有哑元,则是postfix,否则,就是prefix 。 
下面有关c++线程安全,说法错误的是?
正确答案: C   你的答案: A (错误)

线程安全问题都是由全局变量及静态变量引起的
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全
c++标准库里面的string保证是线程安全的
POSIX线程标准要求C标准库中的大多数函数具备线程安全性
标准库里面的string在多线程下并不保证是都是安全的,只提供两种安全机制:
1.多个线程同时读取数据是安全的。
2.只有一个线程在写数据是安全的。
对于下面的说法,正确的是____。

对于 struct X { short s; int i; char c; },sizeof(X) 的值等于 sizeof(s) + sizeof(i) + sizeof(c)
对于某个double变量 a,可以使用 a == 0.0 来判断其是否为零
初始化方式 char a[14] = "Hello, world!"; 和初始化方式 char a[14]; a = "Hello, world!"; 的效果相同
在gcc编译器下,对于 int i = 3; printf("%d %d", ++i, ++i),运行输出为:4 5
选项A、B、C、D中至少有两个是正确的
以上选项均不正确

选F
A结构体要按高位对齐,int占四个字节,short占两个,char占一个 字节,所以4+4+4=12;
B要判断一个双精度浮点数:if( abs(f) <= 1e-15 )
C数组初始化两种方式:一种逐个赋值 char a[14] ={‘H’,‘e’,'l','l','o'};另一种 char a[14] = "Hello, world!"

char a[14]; a = "Hello, world!";错误 a为数组首地址是常量不能改变
D 5,5

发表于 2015-09-04 10:58:41回复(0)
6

JNYM
选F,
    对于A,sizeof(X)=4+4+4=12(内存对齐结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐)
    对于B,要判断一个双精度浮点数:if( abs(f) <= 1e-15 )
    对于C,第二种初始化方式是错误的,无法通过编译
    对于D,输出为54(从右向左)

“`
在c++中,

const int i = 0;
int j = (int ) &i;
*j = 1;
printf(“%d,%d”, i, *j)

答:0,1
这就是C++中的常量折叠:指const变量(即常量)值放在编译器的符号表中,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。
而在此基础上加上volatile修改符,即告诉编译器该变量属于易变的,不要对此句进行优化,每次计算时要去内存中取数。
这里也有个小细节:每种编译器对volatile修饰符的修饰作用效果不一致,有的就直接“不理会”
参考:http://blog.youkuaiyun.com/heyabo/article/details/8745942

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值