https://xw.qq.com/cmsid/20211228A01UKK00
https://www.youkuaiyun.com/tags/Ntjacg5sMDQ3Mi1ibG9n.html
一、判断
-
C语言中, 016218表示为一个八进制整数。
错,八进制是0-7. -
switch( c ) 语句中,c可以是int, long, unsigned char, char, unsigned int类型。()
错,Float不行。C只可以是整型类的变量,上述列表中, 除float不可以外, 其余均可。 -
有数组定义
int a1[2][2]={{1,2},{2}};
则a1[1][1]的值为不确定的。()
错,因为这里的数组已经初始化一部分,所以其他的初始化为0;
对于未初始化的数组,全局为0,局部随机。 -
有
#define MYPRINT(x) printf("#x")
则MYPRINT(test)
的输出结果为 test.()
错,结果是#x。 -
a=(b=4)+(c=6)
是一个合法的赋值表达式。()
对。 -
自增运算符(++)和自减运算符 – 只能用于变量,不能用于常量和表达式。()
官方答案:错误。但是好像是正确的。 -
若有说明
static int a[3][4];
则数组a中各元素可在程序的编译阶段得到初值0。()
对。 -
char const * const p;
与const char * const p;
是一样,但是char * const p;
与char const *p;
是不一样的。()
对,关键看 const 修饰谁,若出现const *
的形式,则 const 其实是修饰前面的,因为没有 const* 的运算。
–char *const p
能够当作char <- *const p,
,意思是一个常指针 p 指向 char 类型数据的地址,既然是常指针,那么 p就不可指向其余地址,而被指向的值可改变,由于被指向的是char类型数据,固然是可改变的。
–const char *p
等价于char const *p
,意思是一个指针 p 指向一个 const char 常字符类型数据的地址,p 是可指向其余地址的,而被指向的值是个不能改变的常量。
–char const * const p;
与const char * const p;
一个常指针指向一个常量。常指针:不能改变p指向的地址值,常量:不能改变p指向地址值的值。 -
C++中 const 成员函数对于任何本类的数据成员都不能进行写操作。()
对,有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内,如 void fun() const ),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。 -
C++中所有的函数都是纯虚函数的才是纯虚类。()
错,含有一个纯虚函数的类为纯虚类。 -
在 C++ 中两个指针相加没有意义。
对。 指针的数值是该地址相对于最低位地址也就是0位地址的偏移量,也可称之为坐标。坐标相加得到的新值是没什么意义的,坐标相减则是距离,坐标加距离则是新坐标,后两者是有意义的。 -
定义数组时可以不确定元素个数。
错。 -
指针是一种特殊的变量,只能用来保存地址。
对。
14. 可以用swicth结构实现的程序都可以使用if语句来实现。
对。(都可以用 if-else if结构实现)
15. 所有的函数调用前都必须进行函数原型说明。
错。(只要函数的定义在调用之前就不用声明。)
16. 通过return语句,函数可以带回一个或一个以上的返回值。
错。
(只能有一个返回值,但是这个返回值可以是一个结构体或者是一个类,而结构体和类中可以容纳很多信息;或者也可以参考函数参数的方式来实现返回你所需要的信息,可以是多个。)
二、选择
-
冒泡排序算法的时间复杂度是什么?
a. O(n^2)
b. O(log(n))
c. O(2n) -
下面哪种排序法对12354最快?
a. quick sort
b. buble sort
c. merge sort -
什么函数不能声明为虚函数?
a. 带有 static 关键字的函数
b. constructor构造函数
c. 返回值为 null 的函数
虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public
普通函数(非成员函数)、静态成员函数、内联成员函数、构造函数、友元函数 不能声明成虚函数。
-
下列关于static关键字使用错误的是那一项?
a. static全局变量只初使化一次
b. static局部变量可以初始化很多次
c. static函数在内存中只有一份 -
哪种结构,平均来讲,获取一个值最快?
a. binary tree
b. hash table
c. stack -
定义一个变量使之保存值的范围是0-65535,应该选择( )类型。
A.unsigned short int
B. int
C.short int
D.long int -
( )不是构造函数的特征
a.构造函数的函数名与类名相同
b.构造函数可以重载
c.构造函数可以设置缺省参数
d.构造函数必须指定类型说明 -
设x、y、z都是整型变量,x、y的初值都是5,执行
z=(++x)+(y--)+1
后,x、y、z三变量的值按顺序是( )。
A.5, 5, 11
B.6, 6, 13
C.4, 6, 12
D.6, 4, 12 -
下列字符中不属于转义字符的是( )
A. \n — 换行
B.\t — 水平制表(HT) ,跳到下一个TAB位置
C.\b — 退格
D.\k -
下列不正确的标识符是( )
A. _char
B. a?b
C. x
D. st2_flag -
C语言的源程序( )主函数
A. 可以没有
B.可以有多个
C.有且只有一个
D.若有,只有一个 -
在内存中应该开辟( )多少个字节来存放字符 ‘\n’.
A. 1
B. 2
C. 3
D. 4 -
下面的( )不是合法的c语言常量,
A. 123
B. ‘M’
C. 0892 (八进制0-7)
D. “Flag” -
下面( )对变量的说明是错误的。
A. char c1, int x; (中间不能用逗号)
B. int a,b; float x, y;
C. int a; int b;
D. char c1; int x; -
有变量说明 int a=3;, 则表达式 a<1 && --a>1的运算结果和a的值应该是( )
A. 0和2
B. 0和3 ( a<1 错误之后不会进行后面的运算判断)
C. 1和2
D. 1和3 -
设 int a=12; , 则执行完语句 a+=a-=a*a; 后,a的值是( )
A. 552
B. 264
C. -264
D. 144
1、先计算
a -= a*a
,得到a=12-12*12=-132
;
2、a+=-132
,得到a=-132-132=-264
。
赋值运算符的计算顺序是从右到左,大多数运算符结合性是从左到右,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。而且它的优先级别低于其他的运算符,所以对该运算符往往最后读取。
-
c语言中,运算对象必须是整型数的运算符是( )
A. %
B. /
C. %和\
D. %和/ -
以下关于break语句的描述,只有( )是正确的。
A. 在循环语句中必须使用break语句。
B. break语句只能用于switch语句中。
C. 在循环语句中可以根据需要使用break语句。
D. break语句可以强制跳出所有循环。 -
下面的叙述中,不正确的是( )
A. 在main函数中说明的变量的作用域是整个程序。
B. 全局变量在程序运行期间一直占用分配给它的存储单元。
C. 形式参数是局部变量.
D. return()语句中括号内可以是常量、有确定值的变量或表达式。 -
定义函数时,默认的函数类型是( )
A. auto
B. register
C. static
D. extern -
c语言中的函数( )
A. 可以嵌套定义
B. 嵌套调用和递归调用均可 (不可嵌套定义 [在函数内部定义函数] )
C. 不可以嵌套调用
D. 可以嵌套调用,但不可以递归调用 -
已知:print( )函数是一个类的常成员函数,它无返回值,下列表示中,( )是正确的。
a.void print( ) const;
b.const void print( );
c.void const print( );
d.void print(const); -
关于虚函数的描述中,( )是正确的。
a.虚函数是一个static类型的成员函数
b.虚函数是一个非成员函数
c.类中说明了虚函数后,派生类中将其对应的函数可不必说明为虚函数
d.派生类的虚函数与基类的虚函数具有不同的参数个数和类型 -
关于new运算符的下列描述中,( )是错的。
a.它可以用来动态创建对象和对象数组
b.使用它创建的对象和对象数组可以使用运算符delete删除
c.使用它创建对象时要调用构造函数
d.使用它创建对象数组时必须指定初始值 -
在一个函数中,要求通过函数来实现一种不太复杂的功能,并且要求加快执行速度,选用( )。
a.内联函数
b.重载函数
c.递归调用
d.嵌套调用
二维数组声明
- 以下二维数组声明中,正确的是( )。
A. char b[2][3]={"a","b","c"};
B. char b[][3]={0};
C. char b[2][]={0};
D. char b[][]={0}
A.char str[2][3]表示声明了一个字符串数组,最多可以存放两个字符串,每一个字符串的长度为3。题中{“a”,“b”,“c”}为三个字符串。
C.在声明数组时,数组个数可以缺省,数组长度不能缺省。该项中数组长度缺省。(只有靠近数组名的那一维在定义时可以缺省)
D.同上。
- 下面代码不能正确输出hello的选项为()
#include<stdio.h>
struct str_t{
long long len;
char data[32];
};
struct data1_t{
long long len;
int data[2];
};
struct data2_t{
long long len;
char *data[1];
};
struct data3_t{
long long len;
void *data[];
};
int main(void)
{
struct str_t str;
memset((void*)&str,0,sizeof(struct str_t));
str.len=sizeof(struct str_t)-sizeof(int);
snprintf(str.data,str.len,"hello");//VS下为_snprintf
____________________________________;
____________________________________;
return 0;
}
A. struct data3_t *pData = (struct data3_t*) &str;
printf(“data:%s%s\n”, str.data, (char*) (&(pData->data[0])));
B. struct data2_t *pData = (struct data2_t*) &str;
printf(“data:%s%s\n”, str.data, (char*) (pData->data[0]));
C. struct data1_t *pData = (struct data1_t*) &str;
printf(“data:%s%s\n”, str.data, (char*) (pData->data));
D. struct str_t *pData = (struct str_t*) &str;
printf(“data:%s%s\n”, str.data, (char*) (pData->data));
选项A和B中的pData->data[0]不是数组的地址,而是数组的首元素,相当于是原结构体里面的char,因此必须取地址之后再强制转换成char *类型。
- 下列代码输出为()
class Test {
int a;
public:
Test() : a(0) {cout << "void";}
explicit Test(int i) : a(i) {cout << "int";}
Test(short s) : a(s) {cout << "short";}
Test &operator=(int n) {a = n; cout << "operator=";}
};
int main() {
int n;
Test a = n;
}
A. int
B. short
C. void
D. void operator=
接受一个参数的构造函数允许使用赋值语句隐式调用来初始化对象short s = 1; Test a = s;
;而 explicit 构造函数只能被显式调用int a = 1; Test a(n);
。
所以,构造函数的调用发生在以 n 为参数创建临时变量期间。由于 int 参数的构造函数声明为explicit,所以不能够调用这个函数,于是,会调用 short 参数的构造函数。
- 对于下面程序说法正确的是
int main() {
int a=5,b=0,c=0;
if (a=b+c) printf ("***\n");
else printf("$$$\n");
return 0;
}
A. 有语法错不能通过编译
B. 可以通过编译但不能通过连接
C. 输出***
D. 输出$$$
if 后面的表达式可以是任何类型的表达式,当然可以是赋值表达式,所以答案A和B是错误的,因赋值表达式的值 a = 0(即为假),所以执行 else 后的语句,输出$$$。
三、填空
注:以下填空题目都是以32位机为主
1、 给定结构
#pragma pack(4)
struct A{
int a1:30;
char a2:2;
int a3:16;
int a4:16;
char a5;
int a6:3;
};
union B{
int b1:16;
char b2:2;
};
则
sizeof(A) = ____
sizeof(B) = ____ (5分)
12;4
a1:30表示的是a1在int里边只占30个位,以此类推…
2、 下面代码实现统计一个整数二进制格式中包含多少个’1’请补充完整(5分)
int GetBitNumber(int number)
{
int cnt=0;
while(number!=0)
{
__________________________;
_________________________;
}
return cnt;
}
++cnt;
number &= (number - 1); // 将最后一位 1 翻转
3、 有如下定义
char *a1[]={"hello!","tclmob"};
char a2[]="\thello\0";
char a3[][8]={"hello!","tclmob"};
char *p1="hello";
char **p2=a1;
char a4[]={'h','e','l','l','o','\0'};
int a5[]={'h','e','l','l','o','\0'};
请问
sizeof(a1) = 8 (指针数组,两个指针大小)
因为 [] 的优先级要比 * 要高,所以 a1 先与 [] 结合,构成一个数组的定义,数组名为 a1,而 char* 修饰的是数组的内容,即数组的每个元素。
sizeof(a2) = 8 (七个字符 + ‘\0’结束符,即使字符串有’\0’结尾)
strlen(a2) = 6 (字符串内容长度)
sizeof(a3) = 16 (两个长度为8的字符数组)
sizeof(p1) = 4
sizeof(p2) = 4
sizeof(a4) = 6
sizeof(a5) = 24 (4分)
4、 在一棵二叉树上第 8 层的结点数最多是____个。(2分)
128 ( 2 n − 1 2^{n-1} 2n−1)
5、 进程之间通信的途径有____..._____.(4分)
匿名管道、有名管道、内存映射、共享内存、信号量、信号、消息队列、socket
6、写出执行结果
#include<stdio.h>
main()
{
int x,m,n,a,b;
m=n=a=b=8;
x=(m=a>b)&&(n=a>b);
printf("x=%d,m=%d,n=%d\n",x,m,n);
}
x=0,m=0,n=8
m=a>b 为假,停止后续运算
7、写出执行结果
#include<stdio.h>
main()
{
int a,b,c;
a=2;b=3;c=1;
if(a>b)
if(a>c)
printf("%d\n",a);
else
printf("%d\n",b);
printf("end\n");
}
end
8、写出执行结果
int main()
{
int s = 0, k;
for(k=7; k>=0; k--)
{
switch(k)
{
case 1:
case 4:
case 7: s++; break;
case 2:
case 3:
case 6: break;
case 0:
case 5: s+=2; break;
}
}
printf("s=%d\n",s);
return 0;
}
s=7
只有遇到break才会跳出不然继续执行下一条语句:
进入k=7的循环
因为k=7,所以执行s++,现在s=1
进入k=6的循环
因为k=6,所以执行break,现在s=1
进入k=5的循环
因为k=5,所以执行s+=2,现在s=3
进入k=4的循环
因为k=4,所以执行s++,现在s=4
进入k=3的循环
因为k=3,所以执行break,现在s=4
进入k=2的循环
因为k=2,所以执行break,现在s=4
进入k=1的循环
因为k=1,所以执行s++,现在s=5
进入k=0的循环
因为k=0,所以执行s+=2,现在s=7
9、假定 x = 9999,写出执行结果
int func (x)
{
int countx = 0;
int x = 9999;
while(x)
{
countx++;
x = x & (x-1); // 反转最低位的1
}
return countx;
}
countx = 8.
9999 = B1001 1100 0011 11,八个零
10、写出执行结果
union
{
int i;
char x[2];
} a;
int main()
{
a.x[0] = 10;
a.x[1] = 1;
cout << a.i;
return 0;
}
266
10 = B0000 1010
1 = B0000 0001
i = B 1 0000 1010 = 266
11、写出执行结果
int main()
{
int a, b, c, d;
a = 10;
b = a++; // b = 10, a = 11
c = ++a; // a = 12, c = 12
d = 10 * a++; // d = 120, a = 13
cout <<"b, c, d: " << b << ", "<< c << ", " << d;
return 0;
}
b, c, d: 10, 12, 120
12、程序改错
void getMemory(char *p){
p = (char*)malloc(100);
}
int main()
{
char *str = nullptr;
getMemory(str);
strcpy(str, "hello");
cout << str;
return 0;
}
getMemory(&str)时,str 没有得到分配内存的地址值。
内存空间状态:首先申请了四个字节的栈空间,存放 str 指针,此时str的值为0,存放 str 的这块内存的地址值为0x0012ff7c。调用函数 GetMemory,指针P入栈,也分配了四个字节的栈空间,P 被赋 str 的值,即此时 P 的值也为0,存放指针 P 的内存地址是0x0012ff2c。然后将新开辟的100个字节的内存空间地址赋给 P,此时P的值为0x00372b70。函数调用结束时str的值仍为0,str并没有得到那块100个字节的内存空间地址值!
修改方法1:(双二级指针)
void getMemory(char **p){ // **p = &str
*p = (char*)malloc(100); // *p = str
}
int main()
{
char *str = nullptr; // str存放的是指针
getMemory(&str); // &str,指向str指针的指针
strcpy(str, "hello");
cout << str;
return 0;
}
str可以得到分配内存的地址值。
内存空间状态:首先申请了四个字节的栈空间,存放 str 指针,此时 str 的值为0,存放 str 的这块内存的地址值为0x0012ff7c。调用函数GetMemory,指针P入栈,也分配了四个字节的栈空间,此时 P 是一个二级指针,存放了指针 str 的地址值,即 P 的值是0x0012ff7c,存放指针 P 的内存空间的地址值是0x0012ff2c。然后将新开辟的100个字节的内存空间地址值 0x00372b70 赋给*P,即str,所以 str 的值为0x00372b70。函数返回时str的值为分配的100个字节的内存空间的地址!
修改方法2:(返回 char*)
char* getMemory(){
char* p = (char*)malloc(100);
return p;
}
int main()
{
char *str = nullptr;
str = getMemory();
strcpy(str, "hello");
cout << str;
return 0;
}
13、代码输出结果是:
int a = 2; // a0
int f(int n){
static int a = 3; // a1
int t = 0;
if(n%2){
static int a = 4; // a2
t += a++; // a2
}else {
static int a = 5; // a3
t += a++; // a3
}
return t+a++; // a1
}
int main()
{
int s = a, i; // a0
for(i = 0; i< 3; i++){
s += f(i);
}
cout << s <<endl;
return 0;
}
29
代码中定义了一个全局变量,三个静态局部变量;
四个 a 的生命周期都是程序的运行周期,他们的作用域不同,但都满足就近原则。
静态局部变量赋初值是在编译时进行值的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值(忽略改行定义的代码)而只是保留上次函数调用结束时的值。
如代码所示,不同的函数代码段对应调用不同的 a 值,相当于三个不同的静态局部变量。
14、一个32K×32位的主存储器,其地址线和数据线的总和为____.
47
32K = 32 * 2(10) = 2(15) = 15条地址线;32位 = 32条数据线。
在微机原理中,CPU 分为地址线、数据线和控制线;
CPU 在内存或硬盘里寻找一个数据时,先通过地址线找到地址,然后通过数据线将数据取出来。
地址线是用来传输地址信息的,也就是说,地址线一次确定一个存储单元,地址线上的值可能取得的所有组合确定了存储单元个数,即存储容量;一个存储单元占一个字节。
数据线是用来传递数据信息的,数据线确定存储字长,数据线有多少条,字长就是多少位。字长为32位时,则1字 = 32bit = 4B,表明处理器一次可以处理4个存储单元,指令长度为4个存储单元。
15、假定T是一个C++类,下列语句执行之后,内存里创建了()个T对象。 9
T b(5); // 1
T c[6]; // 6
T &d = b; // 0
T e=b; // 1
T *p = new T (4); // 1
16、以下函数用法正确的个数是: 0
void test1(){
unsigned char array[MAX_CHAR+1],i;
for(i = 0;i <= MAX_CHAR;i++){
array[i] = i;
}
}
char*test2(){
char p[] = "hello world";
return p;
}
char *p = test2();
void test3(){
char str[10];
str++;
*str = '0';
}
- char 取值范围为 -128~127,unsigned char 取值范围为 0~255,即 i 的取值为 0~255,当 i = 255 时,i++ 将变为 0;那么如果 MAX_CHAR >= 255,将导致无限循环。
- 如果是指针 p,则 p 指向存放字符串常量的地址,返回 p 则是返回字符串常量地址值,调用函数结束字符串常量不会消失(是常量)。所以返回常量的地址不会出错。
而 test2() 中为数组 p,则函数会将字符串常量的字符逐个复制到 p 数组里面,返回 p 则是返回局部变量数组 p,但是调用函数结束后 p 被销毁,里面的元素不存在了。
因此,正确做法为把char p[] = "hello world";
改成char* p = "hello world";
- 重点在于 str++,这实际的语句就是 str = str + 1; 而 str 是数组名,数组名是常量,所以不能给常量赋值。(可以执行 str + 1,但是不能作为左值 str =.)
char p[] = "hello world";
首先会在栈上分配 13 字节的空间,然后把常量存储区的 hello world 拷贝到栈上,用来初始化数组 p,p 的类型是char[],不是字符串首元素地址,因为数组在栈上!也不是说栈中数组首元素的地址,虽然*p可以获取p数组的第一个元素,因为p[]它是一个数组,类型是char[],而不是指针,这也是为什么p不能做左值。函数退出后,栈内存被自动回收,p[]数组就不存在了,所以return p指向一个危险地址,但是常量区的“hello world”还在,直到程序结束。
16、以下程序的输出结果是() 5 20
int main() {
char st[20]="hello\0\t\\\"";
printf ("%d %d \n",strlen (st),sizeof (st));
return 0;
}
strlen 计算字符串的长度,以 \0
为字符串结束标记;
sizeof 来返回类型以及静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系;具体而言,当参数分别如下时,sizeof返回的值表示的含义如下:
数组——编译时分配的数组空间大小;
指针——存储该指针所用的空间大小(存储该指针的地址的长度,是长整型,应该为4);
类型——该类型所占的空间大小;
对象——对象的实际占用空间大小;
函数——函数的返回类型所占的空间大小。函数的返回类型不能是void
17、关于运算符的优先顺序是
赋值运算符 < 逻辑运算符 < 关系运算符 < 算术运算符,
例如,a=x+y>2 && x+y<8;
等价于a=(((x+y)>2)&&((x十y)<8));
18、下面程序输出结果为? 15
#include<iostream.h>
#define SUB(X,Y) (X)*Y
int main(){
int a=3,b=4;
cout<<SUB(a++,++b);
return 0;
}
SUB(a++,++b) = (a++)*++b = (3++)* ++4 = 3 * 5 = 15.
表达式中的 3++ 得先结束表达式再自加,而 ++4 是先自加再执行表达式。
19、下列代码的输出是?
main(){
char str[] = "Geneius";
print (str);
}
print(char *s){
if(*s){
print(++s);
printf("%c", *s);
}
}
suiene
主要有两个知识点,一个是递归,相当于栈是FILO,另一个考察点是print(++s),指针先移动然后调用函数。
20、Linux下 printf 和 sleep 共同使用
#include "stdio.h"
main()
{
printf("Hello world.");
// fflush(stdout);
sleep(1);
}
运行以上程序,系统沉睡1秒后,输出 Hello world.
printf 默认是输出到标准输出,而 Linux 标准输出默认使用的是行缓冲,遇到 \n 回车符、 flush 操作 或 exit(0)程序结束时,开始进行IO操作,输出在命令行上。
printf 在windows上没有缓冲区,直接进行IO。
全缓冲: 全缓冲就是等待标准IO缓冲区填满或者flush操作,才进行IO操作输入输出
行缓冲:当遇到 \n 回车换行符时,进行IO操作输入输出
无缓冲:没有缓冲,直接进行IO操作
四、多选
1、对于浮点变量f,能实现对 f 中的值在小数点后第三位进行四舍五入的表达式有_____
A) f=(f*100+0.5)/100.0
B) f=(f*100+0.5)/100
C) f=(int)(f*100+0.5)/100.0
// 1.253 – 125.3 – 125.8 --125 – 1.25 (+0.5是为了第三位四舍五入)
D) f=((int)(f*100+0.5))/100.0
2、 若x、b、m、n均为 int 型变量,执行下面语句后b的值为_____
m=20;n=6;
x=(--m==n++)?--m:++n // m = 19, n = 7, n = 8, x = 8
b=m++; // b = 19, m = 20
A)11
B)6
C)19
D)18
3、下列选项中可以将变量 n 清零的表达式有____
A) n = ~n & ~n
B) n = n & ~n
C) n = n ^ n
D) n = n | n
4、若有以下说明 int a[5][9]; 则下列选项中对数组元素 a[i][j] 的正确引用有________(0<=i<4,0<=j<9)
A)*(&a[0][0]+9*i+j)
B)*(a+i)(j)
C)*(*(a+i)+j)
D)*(a[i]+j)
a[i] = *(a+i)
5、下列选项中没有构成死循环的程序段有______
A) int i=100; while(1) { i=i%100+1; if(i>=100) break; }
B) for( ; ; )
C) int k=0; do{++k;} while(k>=0); // k溢出时变成负数
D) int s = 36; while(s); - -s;
6、有如下程序:
void fun(int i)
{
printf("%d,",i);
}
void main()
{
int i=5;
fun(i);
fun;
}
则运行结果是_____
A)5,0,
B)5,
C)5,5,
D)5,随机值
E)可能出现运行异常
1)func(i)
2)func就是一个地址,此处没有调用,只是相当于一个指针,所以警告无效语句,就跟你写了一个 55;语句,不会报错,但是会警告。
3)func()没有传参,报错了ERROR
7、若变量已正确定义,要求程序段完成求 5! 的计算,下列选项中能完成此操作的程序段
A) for (i=1,p=1;i<=5;i++) p*=i;
B) for (i=1;i<=5;i++) {p=1;p*=i;}
C) i=1;p=1;while(i<=5) p*=i;i++;
// 没有大括号
D) i=1;p=1;do{p*=i;i++;}while(i<=5);
8、有如下代码:
int a,b,c; a = b = c = 0;
0>1? a++ : 1>0? b++ : c++;
printf("%d%d%d\n", a, b, c);
则输出结果是_________
A)010
B)110
C)111
D)语法错误
9、 OSI 模型中,会话层的主要任务有______
A) 向用户提供可靠的端到端服务,透明地传送报文 (传输层)
B) 组织两个会话进程之间的通信,并管理数据的交换
C) 处理两个通信系统中交换信息的表示方式 (表示层)
D) 确定进程之间通信的性质,以满足用户的需要 (应用层)
10、有以下程序
main()
{
int x=102,y=012; // 学= 102 = B1100110, y = 012 = 10 = B1010
printf("%2d,%2d\n",x^y,x|y);
}
执行后输出结果是是()
A) 4,110
B) 002,112
C) 108,110
D) 106,110
11、设有如下的程序段:
char str[]="Hello";
char *ptr;
ptr=str;
执行上面的程序段后,*(ptr+5)
的值为______
A) ‘o’
B) ‘\0’
C) 不确定的值
D) 'o’的地址
12、一个栈的输入序列为1 2 3,则可能是栈的输出序列的是_____
A) 231 (1 2 进 2 出 3 进 3 出 1 出)
B) 321 (1 2 3 进 3 2 1出)
C) 312
D) 123 (1 进 1 出 2 进 2 出 3 进 3 出)
13、下面关于完全二叉树的叙述中,正确的有______
A) 除了最后一层外,每一层上的结点数均达到最大值
B) 可缺少若干个左右叶子结点 (在最后一层上只缺少右边的若干叶子结点的二叉树)
C) 完全二叉树一般不是满二叉树
D) 具有 n 个结点的完全二叉树的深度为[log2n]+1
14、下面概念中,属于面向对象方法的有___________
A) 对象、消息
B) 继承、多态
C) 类、封装
D) 过程调用
15、在下列几种排序方法中,要求内存量最大的是__________.
A) 插入排序 O(1)
B) 选择排序 O(1)
C) 快速排序 O(logn)
D) 归并排序 O(n)
16、类的静态数据成员和静态成员函数的目的是_______.
A. 供所有对象使用
B. 打破类的封装限制 ?
C. 节省内存
D. 增加对象的访问权限
17、面向对象的程序设计有特征:_______.
A. 抽象
B. 封装
C. 继承
C. 多态
一、抽象和封装
类和对象体现了抽象和封装
抽象就是解释类与对象之间关系的词。类与对象之间的关系就是抽象的关系。一句话来说明:类是对象的抽象,而对象则是类的特例,即类的具体表现形式。
封装两个方面的含义:一是将有关数据和操作代码封装在对象当中,形成一个基本单位,各个对象之间相对独立互不干扰。二是将对象中某些属性和操作私有化,已达到数据和操作信息隐蔽,有利于数据安全,防止无关人员修改。把一部分或全部属性和部分功能(函数)对外界屏蔽,就是从外界(类的大括号之外)看不到,不可知,这就是封装的意义。
二、继承
面向对象的继承是为了软件重用,简单理解就是代码复用,把重复使用的代码精简掉的一种手段。如何精简,当一个类中已经有了相应的属性和操作的代码,而另一个类当中也需要写重复的代码,那么就用继承方法,把前面的类当成父类,后面的类当成子类,子类继承父类,理所当然。就用一个关键字extends就完成了代码的复用。
三、多态
没有继承就没有多态,继承是多态的前提。虽然继承自同一父类,但是相应的操作却各不相同,这叫多态。由继承而产生的不同的派生类,其对象对同一消息会做出不同的响应。
编译时多态体现在函数重载和模板上,
运行时多态体现在虚函数上。
18、以下说法中正确的是_______。
A.C语言程序总是 main 函数开始执行
B.在C语言程序中,要调用函数必须在main()函数中定义
C.C语言程序由函数组成,且必须包含 main 函数
D.C语言程序中的main()函数必须放在程序的开始部分
程序执行总是从main函数开始,如果有有其他函数,则完成对其他函数的调用后再返回到主函数,最后由main函数结束整个程序。
在执行程序时,由系统调用main函数 。main 函数是在程序启动中完成对具有静态存储期的非局部对象的初始化之后被调用的。
C语言的程序是由主函数 main 开始运行,由主函数来调用其他函数,函数必须是并列的,定义后使用,不能在一个函数中定义其他函数,main 函数不一定要放在程序的开始部分。
19、对类中声明的变量,下列描述中不正确的是( )
A. 属于全局变量
B. 只属于该类
C. 属于该类,某些情况下也可被该类不同实例所共享
D. 任何情况下都可被该类所有实例共享
20、多重继承时,如果派生类的两个父类有一个共同的虚基类,那么虚基类的初始化参数由()的构造函数来传递。 虚基类 多重继承
A. 第一个父类
B. 第二个父类
C. 派生类
D. 以上都不是
21、(虚表指针)关于pA,pB,pC的取值,下面的描述中正确的是:
class ClassA
{
public:
virtual ~ ClassA() {};
virtual void FunctionA() {};
};
class ClassB
{
public:
virtual void FunctionB() {};
};
class ClassC : public ClassA,public ClassB
{
public:
};
ClassC aObject;
ClassA* pA=&aObject;
ClassB* pB=&aObject;
ClassC* pC=&aObject;
A. pA,pB,pC的取值相同
B. pC=pA+pB
C. pA和pB不相同
D. pC不等于pA也不等于pB
E. pC和pA相同
这种情况下,派生类的指针和第一个基类的指针是一样的,和第二个基类是不一样的。
pC = pA = pB - 4 (class A 的大小,C先继承A再集成B)
五、简答
1、写出程序执行结果,并解释原因(5分)
void getstr(char *p)
{
p = (char *)malloc(100);
strcpy(p,"TCL");
}
void main()
{
char *str;
getstr(str);
if(str)
{
str[3]='\0';
printf("%s,%d\n", str, strlen(str));
free(str);
}
}
无任何输出,
类似于填空题第12题, str 传递给 getstr 函数时,只是将 str 的地址值赋值给 p,此后 p 的值与 str 无关,函数调用结束时 str 的值仍为0,str 并没有得到那块100个字节的内存空间地址值!
void getstr(char **p) // **p = &str
{
*p = (char *)malloc(100); // *p = str
strcpy(*p,"TCL");
}
int main()
{
char *str; // 指向指针的指针 &str -> 指向字符串的指针 str -> 字符串
getstr(&str); // 取指针传递
if(str)
{
str[3]='\0'; // 结束符,避免乱码
printf("%s,%d\n", str, strlen(str));
free(str);
}
return 0;
}
输出:TCL, 3
2、写一个“标准”宏,这个宏返回一个数组最高维的下标 (如数组 a[2][4][6]
,执行宏之后结果是2)。(5分)
#define firstdem(array) sizeof(array)/sizeof(array[0])
3、 比较说明什么是Big-Endian,Little-Endian,网络字节序。(5分)
字节序:就是大于一个字节类型的数据在内存中的存放顺序。
大端字节序:高位字节在低地址,低位字节在高地址;
小端字节序:高位字节在高地址,低位字节在低地址;
网络字节序:即大端字节序。
4、 下面程序的运行结果是什么,为什么
main()
{
char *p1="abc", *p2="ABC", str[8]="xyz";
strcpy(str+2,strcat(p1,p2));
printf("%s \n",str);
}
xyabcAB
strcat()
函数:
其调用方式是:strcat(字符数组,字符串),功能是把"字符串”连接到"字符数组”中的字符串尾端,并存储于"字符数组”中。“字符数组”中原来的结束标志,被“字符串”的第一个字符覆盖,而“字符串”在操作中未被修改。
使用该函数时注意:
① 由于没有边界检查,编程者要注意保证“字符数组”定义得足够大,以便容纳连接后的目标字符串;否则,会因长度不够而产生问题。
② 连接前两个字符串都有结束标志’\0’,连接后“字符数组”中存储的字符串的结束标志’\0’被舍弃,只在目标串的最后保留一个’\0’。
strcpy()
函数:
该函数的调用方式是:strcpy(字符数组,字符串),其中“"字符串”可以是字符串常量,也可以是字符数组。
函数的功能是:将“字符串”完整地复制到“字符数组”中,字符数组中原有内容被覆盖。
使用该函数时注意:
① 字符数组必须定义得足够大,以便容纳复制过来的字符串。复制时,连同结束标志’\0’一起复制。
②不能用赋值运算符“=”将一个字符串直接赋值给一个字符数组,只能用strcpy()函数来处理。
六、编程
-
用两个栈实现一个队列的功能,给出步骤和思路
-
写一段代码实现把一个单向链表反向
-
文件中有一组整数,要求排序后输出到另一个文件
-
整型数组 a 有五个元素,分别为1、2、3、4、5,移动该数组的数,使其变成 2、3、4、5、1.
-
用户从键盘输入一个字符串(不包含空格),当输入回车时认为输入结束,统计输入字符串中小写英文字母、大写英文字母、数字字符、其他字符的个数。
-
有两个单向链表,函数find_node作用是判断两个链表是否有交点(两个链表有相同的节点),如果有返回第一个交点。请编程实现。
type struct tag_node { int key; struct tag_node * next; } node; 函数原型: node* find_node(node *head1,node *head2) 入参说明: head1,head2:待检查的两个链表 返回: 相交的节点
两个单向链表相交,意味着从相交节点开始,后半部分的节点完全相同,
那么遍历两条链表,记录两个长度分别为 len1, len2,假设 len2 > len1,然后再分别从头结点开始,先从 list2 头结点开始移动 (len2 - len1) 次,此时两条剩下的链表长度相同,每走一步判断一次,第一个相同的节点即为交点。