c/c++bing(练习题)

Posted 月屯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c/c++bing(练习题)相关的知识,希望对你有一定的参考价值。

1.下面程序的结果是:( )

#include <stdio.h>
#include <string.h>
int main()

    printf("%d\\n", strlen("c:\\test\\121"))
    return 0;

strlen:获取字符串的有效长度,不包括’\\0’
“c:\\test\\121”: 在该字符串中,\\t是转移字符,水平制表,跳到下一个tab的位置;而\\121表示一个字符,是讲121看做8进制数组,转换为10进制后的81,作业为ASCII码值的字符,即:字符’Q’ ,故上述字符串实际为:“c: esty”,只有7个有效字符

2.

#include <stdio.h>
int sum(int a)

    int c = 0;
    static int b = 3;
    c += 1;
    b += 2;
    return (a + b + c);

int main()

    int i;
    int a = 2;
    for (i = 0; i < 5; i++) 
     
        printf("%d,", sum(a)); 
     
 

本题主要考察static修饰局部变量的特性,static修饰局部变量,该变量不会随函数的结束而消失,并且只在第一次调用时进行初始化,后序调用该函数时,使用的都是上次结束前该变量的值。
8,10,12,14,16

3.

关于switch说法不正确的是:( )
A.switct语句中的default子句可以放在任意位置
B.switch语句中case后的表达式只能是整形常量表达式
C.switch语句中case子句必须在default子句之前
D.switch语句中case表达式不要求顺序

答案解析:
A:正确,可以放在任意位置,但是一般建议最好还是放在最后
B:正确,case语句后一般放整形结果的常量表达式或者枚举类型,枚举类型也可以看成是一个特殊的常量
C:错误,没有规定case必须在default之前,一般case最好放在default之前
D:正确,但一般还是按照次序来
因此:选择C

4.

关于函数的声明和定义说法正确的是:( )
A.函数的定义必须放在函数的使用之前
B.函数必须保证先声明后使用
C.函数定义在使用之后,也可以不声明
D.函数的声明就是说明函数是怎么实现的

答案解析:

A:错误,函数的定义可以放在任意位置,函数的声明必须放在函数的使用之前
B:正确
C:错误,函数定义在使用之后,使用之前没有声明时,编译器编译时识别不了该函数
D:错误,函数的声明只是告诉编译器函数返回值类型、函数名字以及函数所需要的参数,函数定义才是说明函数是怎么 实现的

5.编写一个函数 reverse_string(char * string)(递归实现)

实现:将参数字符串中的字符反向排列,不是逆序打印。
要求:不能使用C函数库中的字符串操作函数。
比如:
char arr[] = “abcdef”;

void reverse_string(char *str)
	char begin_char = *str;
	int str_len = strlen(str); 
	*str = *(str + str_len - 1);
	*(str + str_len - 1) = '\\0';
	if (strlen(str + 1) >= 2) 
		reverse_string(str + 1);
	
	*(str + str_len - 1) = begin_char;

6.

给出以下定义:

char acX[] = “abcdefg”;
char acY[] = ‘a’,’b’,’c’,’d’,’e’,’f’,’g’;
以下说法正确的是( )
A.数组acX和数组acY等价
B.数组acX和数组acY的长度相同
C.数组acX的长度大于数组acY的长度
D.数组acX的长度小于数组acY的长度
acX和acY都是字符数组,但是初始化表达式不同,acX和acY的区别如下:
acX:数组中总共有8个元素,分别是:‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘g’,‘\\0’
acY:数组中总共有7个元素,分别是:‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘g’
c

7.

#include <stdio.h>
int main()

    int i = 1;
    int ret = (++i)+(++i)+(++i);
    printf("ret = %d\\n", ret);
	return 0;

答案解析:
表达式(++i)+(++i)+(++i),只有操作符的优先级和结合性,没法确定唯一计算路径
所以这个表达式可能因为计算顺序的差异导致结果是不一致的,所以表达式是错误的表达式。
可以在VS和Linux gcc测试,结果可能有差异。

8.

#include <stdio.h>
int i;
int main()

    i--;
    if (i > sizeof(i))
    
        printf(">\\n");
    
    else
    
        printf("<\\n");
    
    return 0; 

答案解析:
C语言中,0为假,非0即为真。
全局变量,没有给初始值时,编译其会默认将其初始化为0。
i的初始值为0,i–结果-1,i为整形,sizeof(i)求i类型大小是4,按照此分析来看,结果应该选择B,但是sizeof的返回值类型实际为无符号整形,因此编译器会自动将左侧i自动转换为无符号整形的数据,-1对应的无符号整形是一个非常大的数字,超过4或者8,故实际应该选择A

9.

结构体访问成员的操作符不包含:( )
A… 操作符
B.-> 操作符
C.* 解引用操作符
D.sizeof
D:错误,sizeof是求结构体类型大小的

10. C程序常见的错误分类不包含:( c)

A.编译错误
B.链接错误
C.栈溢出
D.运行时错误
栈溢出是运行时错误的一种,因此C程序为将栈溢出单独列出,栈溢出包含在运行时错误中。

11.关于Debug和Release的区别说法错误的是:( )

A.Debug被称为调试版本,程序调试找bug的版本
B.Release被称为发布版本,测试人员测试的就是Release版本
C.Debug版本包含调试信息,不做优化。
D.Release版本也可以调试,只是往往会优化,程序大小和运行速度上效果最优
答案解析:

A:正确,Debug为调试版本,一般在开发完成后发布工程前,调试代码都是在Debug模式下进行的
B:正确,Release版本最终是要发送给用户的,发给用户的版本必须要没有问题,测试人员就是最后一个把关的
C:正确,Debug版本是调试版本,编译器编译时会增加一些调试信息,编译器基本不会对其进行优化
D:错误,Release版本是不能调试的,一般都是在Debug版本下调试的,Release版本一般编译器会进行大量的优化,删除无用的代码,指令的次序调整等,让其速度更快

11.

大小端字节序指的是数据在电脑上存储的字节顺序

12.

错误的是A

int main()

  int arr[10] = 0;
  return 0;

A.数组名arr和&arr是一样的
B.sizeof(arr),arr表示整个数组
C.&arr,arr表示整个数组
D.除了sizeof(arr)和&arr中的数组名,其他地方出现的数组名arr,都是数组首元素的地址。
答案解析
A选项错误明显。arr的类型是int [10],而&arr的类型是int (*)[10],根本不是一个类型,不可能是一样的。而在 sizeof(arr)和&arr中,arr都是看成整体的,而一般它代表一个数组的首地址。

13.

#define MAX_SIZE A+B
struct _Record_Struct

  unsigned char Env_Alarm_ID : 4;
  unsigned char Para1 : 2;
  unsigned char state;
  unsigned char avail : 1;
*Env_Alarm_Record;
struct _Record_Struct *pointer = (struct _Record_Struct*)malloc
(sizeof(struct _Record_Struct) * MAX_SIZE);

当A=2, B=3时,pointer分配( )个字节的空间。

说明:结构体向最长的char对齐,前两个位段元素一共4+2位,不足8位,合起来占1字节,最后一个单独1字节,一共3字节。另外,#define执行的是查找替换, sizeof(struct _Record_Struct) * MAX_SIZE这个语句其实是3*2+3,结果为9,故选D。

14.

int main()

  unsigned char puc[4];
  struct tagPIM
  
    unsigned char ucPim1;
    unsigned char ucData0 : 1;
    unsigned char ucData1 : 2;
    unsigned char ucData2 : 3;
  *pstPimData;
  pstPimData = (struct tagPIM*)puc;
  memset(puc,0,4);
  pstPimData->ucPim1 = 2; 
  pstPimData->ucData0 = 3;
  pstPimData->ucData1 = 4;
  pstPimData->ucData2 = 5;
  printf("%02x %02x %02x %02x\\n",puc[0], puc[1], puc[2], puc[3]);
  return 0;


puc是一个char数组,每次跳转一个字节,结构体不是,它只有第一个元素单独享用一字节,其他三个元素一起共用一字节,所以puc被结构体填充后,本身只有两个字节会被写入,后两个字节肯定是0,至此AD排除,然后第一个字节是2就是2了,第二个字节比较麻烦,首先ucData0给了3其实是越界了,1位的数字只能是0或1,所以11截断后只有1,同理ucData1给的4也是越界的,100截断后是00,只有5的101是正常的。填充序列是类似小端的低地址在低位,所以排列顺序是00 101 00 1。也就是0010 1001,即0x29,故选B。

15.

下列关于文件名及路径的说法中错误的是:( )
A.文件名中有一些禁止使用的字符
B.文件名中一定包含后缀名
C.文件的后缀名决定了一个文件的默认打开方式
D.文件路径指的是从盘符到该文件所经历的路径中各符号名的集合

B选项中,文件名可以不包含后缀名。A的话,文件中不能包含这些字符:/😗?"<>|,C表述了后缀名的作用,D是路径的基本概念。故选B。

16.

C语言中关于文件读写函数说法不正确的是:( )
A.fgetc是适用于所有输入流字符输入函数
B.getchar也是适用于所有流的字符输入函数
C.fputs是适用于所有输出流的文本行输出函数
D.fread是适用于文件输入流的二进制输入函数

答案解析
B选项中,getchar只针对标准输入流stdin。即使对stdin重定向,getchar针对的也只是stdin。f系列的输入输出函数都是作用于所有流的的,所以AC没问题,D的表述也没问题,fread做的就是二进制的活。

17.

int main()
 
  long num=0;
  FILE *fp = NULL;
  if((fp=fopen("fname.dat","r"))==NULL)
  
    printf("Can’t open the file! ");
    exit(0):
  
  while(fgetc(fp) != EOF)
   
    num++
  printf("num=%d\\n",num);
  fclose(fp);
  return 0;

A.拷贝文件
B.统计文件的字符数
C.统计文件的单词数
D.统计文件的行数

程序只通过只读方式打开了一个文件,所以A排除,文中使用的fgetc,且没有’ ‘和’\\n’相关的统计,所以排除CD,直接选B。

18.

以下关于头文件,说法正确的是( )
A.#include<filename.h>,编译器寻找头文件时,会从当前编译的源文件所在的目录去找
B.#include“filename.h”,编译器寻找头文件时,会从通过编译选项指定的库目录去找
C.多个源文件同时用到的全局整数变量,它的声明和定义都放在头文件中,是好的编程习惯
D.在大型项目开发中,把所有自定义的数据类型、函数声明都放在一个头文件中,各个源文件都只需要包含这个头文件即可,省去了要写很多#include语句的麻烦,是好的编程习惯。

答案解析
AB说反了,尖括号是直接去库找,双引号是先从当前目录找,再去库里找。C选项头文件不能定义全局变量,否则如果有多个文件,那链接时会冲突。故选D。D也不是十全十美,在大型项目的开发中,这也并不是一个很好的编程习惯,分类放在不同的头文件并根据特点命名是更好的选择,因为这样更加方便代码的管理和维护,就目前而言,算是一个好习惯吧。

19.

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。

#define SwapIntBit(n) (((n) & 0x55555555) << 1 | ((n) & 0xaaaaaaaa) >> 1)

20.概念区分:栈、栈帧、栈区?

栈:一般指的是数据结构中栈结构—后进先出的数据结构
栈区:一块特殊的内存空间,该内存空间中存储的是与函数调用相关的信息–栈帧:一个特殊的数据结构–该结构组织的是与函数调用相关信息(一个函数调用对应一个栈区,调用结束栈区结束,存储在栈区中)

21.下面关于栈和队列的说法中错误的是( )

A.队列和栈通常都使用链表实现
B.队列和栈都只能从两端插入、删除数据
C.队列和栈都不支持随机访问和随机插入
D.队列是“先入先出”,栈是“先入后出”

答案:AB
解析:
顺序表的结构相比链表简单,不影响效率的情况下会优先使用顺序表。所以栈一般用顺序表实现,队列一般用链表实现。栈只能在一端插入和删除数据。

22.将一个顺序表整理成堆的时间复杂度为

A.O(nlogn)
B.O(logn)
C.O(1)
D.O(n)
建立堆的顺序是bottom-top的。
正确的证明方法应当如下:
A.具有n个元素的平衡二叉树,树高为㏒n,我们设这个变量为h。

B.最下层非叶节点的元素,只需做一次线性运算便可以确定大根,而这一层具有2(h-1)个元素,我们假定O(1)=1,那么这一层元素所需时间为2(h-1) × 1。
C.由于是bottom-top建立堆,因此在调整上层元素的时候,并不需要同下层所有元素做比较,只需要同其中之一分支作比较,而作比较次数则是树的高度减去当前节点的高度。因此,第x层元素的计算量为2^(x) × (h-x)。
D.又以上通项公式可得知,构造树高为h的二叉堆的精确时间复杂度为:
S = 2^(h-1) × 1 + 2^(h-2) × 2 + …… +1 × (h-1) ①
E.通过观察第四步得出的公式可知,该求和公式为等差数列和等比数列的乘积,因此用错位相减法求解,给公式左右两侧同时乘以2,可知:
2S = 2^h × 1 + 2^(h-1) × 2+ …… +2 × (h-1) ②
用②减去①可知: S =2^h × 1 - h +1 ③
将h = ㏒n 带入③,得出如下结论:
S = n - ㏒n +1 = O(n)

23.2-3树是一种特殊的树,它满足两个条件:

(1) 每个内部结点有两个或三个子结点
(2) 所有的叶结点到根的距离相同
如果一颗2-3树有10个结点,那么它有( )个叶结点。
A.7
B.8
C.7 或 8
D.6
解析:
根据题目意思,每一个非叶子节点至少有两个孩子节点,并且叶子节点都在同一层,所以,假设树的高度为h, 则二三树种最小的节点个数为满二叉树的个数:2^h - 1, 最大个数: (3^h - 1) / 2。所以 2^h - 1 < 10 < (3^h - 1) / 2, h为3,结构是1(3(2,2,2))。所以叶节点个数为6

关于c++的inline关键字,以下说法正确的是( )

A.使用inline关键字的函数会被编译器在调用处展开
B.头文件中可以包含inline函数的声明
C.可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数
D.定义在class声明内的成员函数默认是inline函数

A.不一定,因为inline只是一种建议,需要看此函数是否能够成为内联函数
B.inline函数的声明不能放在头文件,需要放在源文件中
C.inline函数在不同额文件实现和调用会导致函数链接错误,故不能
D.在class内部实现的函数默认为inline函数,故正确

设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?( )

C c;

int main()



A a;

B b;

static D d;

  return 0

分析:1、类的析构函数调用一般按照构造函数调用的相反顺序进行调用,但是要注意static对象的存在, 因为static改变了对象的生存作用域,需要等待程序结束时才会析构释放对象
2、全局对象先于局部对象进行构造
3、局部对象按照出现的顺序进行构造,无论是否为static
4、所以构造的顺序为 c a b d
5、析构的顺序按照构造的相反顺序析构,只需注意static改变对象的生存作用域之后,会放在局部 对象之后进行析构
6、因此析构顺序为B A D C

以下代码共调用多少次拷贝构造函数: ( )

Widget f(Widget u)

  

  Widget v(u);

  Widget w=v;

  return w;


main()

  Widget x;

  Widget y=f(f(x));


A.调用拷贝构造函数的时机,从代码上看会有三种情形,1.对象初始化对象 2.函数参数以对象传递 3.函数的返回值以对 象返回,因此乍眼一看,超过1次,A错误
B.整个程序分别在,x初始化u、u初始化v、v初始化w、w返回时,注意w返回时初始u不在调用拷贝构造函数,第二次调用 f()函数时,相当于u的结合会少调用一次,其他不变,所以总体次数为4+3=7次

以上是关于c/c++bing(练习题)的主要内容,如果未能解决你的问题,请参考以下文章

c语言练习题

9.以下说法中正确的是( ) a.C语言比其他语言高级 b.C语言不用编译就能被计算机执行 c.C语言以接近英语国

食物链

食物链

食物链

食物链