2021.1.5
1.
A.在语句char str[ ]=“string!”;中 数组str的大小等于字符串的长度
错误
--数组的长度包含终止符\0
--字符串的长度不包含\0
B.语句char str[10]=“string!”; 和 char str[10] = {“string!”}不等价
错误 对于字符串来讲 未赋值的部分自动赋值“\0” 两个时等价的
C. 对于一位字符数组,不能使用字符串常量来赋初值
错误 char str[10] = "string";成立
D 对于字符串常量"string",系统已自动在最后加入了"\0"字符表示串尾
正确
#include < stdio. h >
int d = 1;
void fun( int p )
{
int d=5;
d += p++;
printf("%d", d );
}
main()
{
int a=3;
fun(a);
d += a++;
printf( "%d\n",d);
}
//最终打印结果为8 4
i++ 在进行运算的时候 用i 参与运算 然后i自增
++i 先对i进行自增 然后用自增后的i参与运算
3.用变量 a 给出下面的定义
一个有10个指针的数组,该指针指向一个函数,该函数有一个二整形参数并返回
/*
int *a[10] //指向int类型的指针数组a[10]
int (*a)[10] //指向有10 个int类型数组的指针a
int(*a)(int) //函数指针, 指向有一个参数并且返回类型均为int的函数
int (*a[10])(int);//函数指针的数组,指向有一个参数并且返回类型均为int的函数的数组
*/
4.当/的两边都是整数时。/表示整除,是否正确?
// 5/3得到的时一个float数,
5.下列选项中正确的语句时
A.char s[8]; s={“Beijng”};
B char *s; s={“Beijing”};
C char s[8]; s=“Beijing”;
D char *s; s=“Beijing”;
/*
数组名是不可修改的常量
char s[8];写完之后就已经初始化了数组 每个元素默认为 "\0" 而后只能是对某个元素进行修改 或是令其等于另一个数组。
AB两个已经进行了初始化,在惊醒初始化就得修改数组名,而数组名是不允许修改的,所以A B 错误
*/
若有以下语句:
int a[4][5],(*p)[5];
p=a;
下面哪个选项表示a数组中的元素?
A. p+1
B *(p+3)
C *(p+1)+3
D *(*p+2)
/*
首先明确 a是一个二维数组 p 是一个二维数组的指针
那么此时 p表示的是a[0] 的地址 而p+1 表示的是 a[1]的地址
*(p+1) 表示进入该行,在此处表示的是第二行即a[1][0]的地址 , 那么*(P)+1表示的是第二行第二个元素的地址
(*(p)+1) 表示的是第二行第二个元素
因此本题 ABC 表示的都是地址,只有D表示的是元素
*/
不考虑任何编译器优化(如:NRVO),下述代码的第10行会发生
#include <stdio.h>//1
class B//2
{//3
};//4
B func(const B& rhs){//5
return rhs;//6
}//7
int main(int argc,char **argv){//8
B b1,b2;//9
b2=func(b1);//10
}//11
A.一次默认构造函数,一次拷贝构造函数,一次析构函数,一次(拷贝赋值运算符)operator=
B.二次拷贝构造函数,一次析构函数
C.一次(拷贝赋值运算符)operator=,一次析构函数
D.一次拷贝构造函数,一次析构函数,一次(拷贝赋值运算符)operator=
b2=func(b1);//10
一次拷贝构造函数发生在func函数调用完成,返回B类型的对象时,因为返回的不是引用类型,所以会生成一个对象,
不妨称为TEMP,将返回的对象通过拷贝构造函数复制给TEMP,然后,返回值所对应的对象会被析构。如果返回值是引用类型,
则不会调用拷贝构造函数。
赋值运算符在func函数执行完成后,将上面提到的TEMP,通过赋值运算符赋值给b2,值得注意的是赋值运算符重载函数如果不自己定义,
程序会认为是调用缺省的赋值运算符重载函数。
下面哪种情况下,B不能隐式转换为A?
A.class B:public A{}
B.class A:public B{}
C.class B{operator A();}
D.class A{A(const B&);}
A 派生类转换为基类
B 基类转派生类,不能隐式转换
C 是隐式类型转换操作符
D 通过拷贝构造函数进行隐式转化
关于浅复制和深复制的说法,下列说法正确的是
A.浅层复制:只复制指向对象的指针,而不复制引用对象本身。
B.深层复制:复制引用对象本身。
C.如果是浅复制,修改一个对象可能会影响另外一个对象
D.如果是深拷贝,修改一个对象不会影响到另外一个对象
答案 ABCD
浅拷贝:只复制指针内容,不复制指针所指对象,结果为两个指针指向同一块内存;
深拷贝:重新为指针分配内存,并将原来指针所指对象的内容拷贝过来,最后结果为两个指针指向两块不同的内存;
浅拷贝是指针拷贝,深拷贝是对象拷贝
10.设fp已定义,执行语句fp=fopen(“file”,“w”);后,以下针对文本文件file操作叙述的选项错误的是:
A.可以随意读和写
B.只能写不能读
C.可以在原有内容后追加写
D.写操作结束后可以从头开始读
2020.1.7
1.
已知int i=0, x=1, y=0;,在下列选项中,使i的值变成1的语句是( )。
A.if( x&&y ) i++;
B.if( x==y ) i++;
C.if( x||y ) i++;
D.if( !x ) i++;
选C
if()中 括号中为真 则执行
&& 与运算
|| 或运算
! 取非
== 相等
如果不使用多态机制,那么通过基类的指针虽然可以指向派生类对象,但是只能访问从基类继承的成员。
正确
不使用多态机制(虚函数),派生类就不会生成虚函数表,用基类指针指向派生类对象时,通过基类指针只能访问派生类的成员变量,不能访问派生类的成员函数
再看题干:如果不使用多态机制,那么通过基类的指针虽然可以指向派生类对象,但是只能访问从基类继承的成员。
划线处我认为叙述有问题,派生类添加的新的成员变量也是可以通过基类指针访问的。
#include < stdio. h >
main ( )
{
char w [20] , a[ 5 ][ 10 ] = { "abcdef", "ghijkl", "mnopq", "rstuv", "wxyz"} ;
int p [ 6 ] [ 2 ] = { {0,1},{1,5},{0,0},{0,2},{1,4},{4,4}}, i ;
for (i =0; i < 6 ; i + +)
w[i] = a[p[i][0]][p[i][1]];
printf( w ) ;
}
运行结果为:black 此题按照程序执行即可
语言源程序的基本结构单位是 main 函数。请问这句话的说法是正确的吗?
错误
对于语言源程序来讲 基本组成单位是 函数 而非主函数
当顺利执行了文件关闭操作时,fclose.函数的返回值是()。
顺利执行返回0 否则返回1
main()
{
char a[7]="a0\0a0\0";
int i,j;
i=sizeof(a); j=strlen(a);
printf("%d %d\n",i,j);
}
程序输出结果为
sizeof 输出的是a的内存空间大小所以会包含终止符 输出7
strlen() 输出的是字符串的长度 遇到"\0"就停止输出2
int a[]={1,2,3,4};
int *b=a;
*b+=2;
*(b+2)=2;
b++;
printf("%d,%d\n",*b,*(b+2));
代码的运行结果为
2,4
首先确定 b是 一维数组的指针
那么此时 b 表示的是a[0]的地址
*b 表示的是此时b所指向的值 即1 所以第二行改变的是值 地址未变
以下正确的说法是( )。
A.用户调用标准库函数前,必须重新定义
B.若已包含标准库头文件及相关命名空间,用户也可以重新定义标准库函数,但是该函数将失去原有含义
C.若已包含标准库头文件及相关命名空间,则系统不允许用户重新定义标准库函数
D.用户调用标准库函数前,不必使用预编译命令将该函数所在文件包括到用户源文件中
A 调用库函数是 需要的是利用#include对其进行声明
B C 标准库函数可以被重载而不能重新定义,重载后函数具有不同的形参,但是原有的定义并不失效
D 当用户调用标准库的函数前,必须使用#include 进行预编译命令 将函数所在文件包括到用户源当中
int main(){
int i=-2147483648;
return printf("%d,%d,%d,%d",~i,-i,1-i,-1-i);
}
打印结果为
1、~i:对每一位 取反运算。为01...1(31个1),是正数,补码即原码,即231-1=2147483647;
2、 -i: 对该数求补运算,即【每位】取反运算,再加1。取反, 10...0(31个0)-> 01...1(31个1),再加1得 10...0(31个0),该 补 码表现为 最小负数- 2147483648,并没有原码和反码;
3、1-i:补码形式相加,再推回原码得十进制结果。-i( 10...0(31个0) )+(0 ...1(31个0) )= 10...1(30个0),此为补码形式,补码转 原码为补码减1,再非符号位取反,即原码1...1(32个1)= -(231-1)= - 2147483647 ;
4、 -1-i :补码形式相加,再推回原码得十进制结果。即-i( 10...0(31个0) )+(1 ...1(32个1) )= 01...1(31个1),是正数形式,原码即补码,为231-1= 2147483647 。
201.1.8
1.
下列选项中,合法的 C 语言关键字是()
A.var
B.defaut
C.integer
D.cher
A 数据库字符关键字
B 争取
C Java的整型包
D char
int u=010, v= 0x10, w=10;
printf(“%d,%d,%d/n”,u,v,w);
输出结果为
0开头表示8进制
0x开头表示16进制
所以 u=8
v=16
w=10
int main()
{
int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int*)(&a + 1);
printf("%d, %d", *(a + 1), *(ptr - 1));
return;
}
输出结果为
a 是长度为5的一位数组
*ptr为一个指针
再此处要辨析
&(a+1)表示的是a[2]的地址
&a+1 表示的a[5]的位置的地址 因为数组的地址都是连续的,在这里只是没有给数组a分配a[5]的空间,但并不代表a[5]的空间不存在
所以ptr - 1 指的是a[4]的地址
多以打印为2 5
int func(int x,int y)
{
return(x+y);
}
main()
{int a=1,b=2,c=3,d=4,e=5;
printf("%d\n",func((a+b,b+c,c+a),(d+e)));
}
求输出结果
再c语言中有 逗号表达式
(表达式1,表达式2,表达式3......)从左到右依次计算,最终表达式的值等于最后一个式子的值
所以最终等于
func(4,9)=13
请问经过表达式a = 5 ? 0 : 1的运算,变量a的最终值是?
三目运算
bool?值1:值二 为真等于值一 为假等于值二
a=5!=0 为真 最终为0
6.有以下结构体说明和变量的定义,且指针p指向变量a,指针q指向变量b。则不
能把结点b连接到结点a之后的语句是()。
struct node
{
char data;
struct node *next;
} a,b,*p=&a,*q=&b;
A.a.next=q;
B.p.next=&b;
C.p->next=&b;
D.(*p).next=q;
【解释】p是一指向结构体类型的指针变量,其初始值是让其指向结构体变量a,要通
过指针变量p来引用结构体变量的成员next,通常可使用两种形式:p->next 或(*p).next,
而p.next是非法的引用。故选择答案是B。
以下选项中合法的常量是?
A.9 9 9
B.2.7e
C.0Xab
D.123E 0.2
A:9 9 9 数字间不能有空格
B:e前后必须有数字,且后面的数字必须为整数。
C:十六进制 0X...
D:同B
常 量:整型常量: 123 实型常量:3.14 字符常量: 'a' 逻辑常量:true、false
常 量:final int i = 0; i的值不可变
s12和s2已正确定义并分别指向两个字符串。若要求:当s1所指串大于s2所指串时,执行语句S;则以下选项中正确的是 ( )
A.if(s1>s2)S;
B.if(strcmp(s1,s2))S;
C.if(strcmp(s2,s1)>0) S;
D.if(strcmp(s1,s2)>0)S;
答案 D
C语言库函数 int strcmp(str1,str2)
如果str1 > str2 return >0
str1 < str2 return <0
str1 == str2 return 0
下面关于数组的初始化正确的是:
A.char str[2] = {“a”,“b”};
B.char str[2][3]={“a”,“b”};
C.char str[2][3]={{‘a’,‘b’},{‘e’,‘d’},{‘e’,‘f’}};
D.char str[] = {“a”, “b”};
区分单引号‘’与双引号“”的区别,单引号为单个字符;’双引号为字符串,系统会默认添加‘\0’
char a=101;
int sum=200;
a+=27;sum+=a;
printf("%d\n",sum);
求输出
char为有符号类型,占1个字节,也就是8位,其中最高位位符号位,取值范围为-128~127;
a=101+27=128>127; 表示为1000 0000,计算机中以补码形式存储, 即为-128;
sum=200+(-128)=72;
2020.1.9
1.
int f(int a)
{ return a%2; }
main()
{ int s[8]={1,3,5,2,4,6},i,d=0;
for
(i=0;f(s[i]);i++) d+=s[i];
printf("%d\n",d);
}
本题按照程序执行即可
2.
设float x=2.5,y=4.7;int a=7;,printf(“%.1f”,x+a%3*(int)(x+y)%2/4)的结果为()
A.2.5
B.2.8
C.3.5
D.3.8
本题要注意的是在强制转换和一般运算同事存在是,强制转换优先执行
最终答案为 2.5
3.若有定义语句: char a =’\82’; 则变量a
A.说明不合法
B.包含一个字符
C.包含两个字符
D.包含三个字符
有一个‘\’,那么首先想到的是转义字符常量,‘\ddd’ 是用八进制数的ASCII码表示一个字符,但是本题中'\82',有一个8,显然已经不是八进制,那么这个时候实际上就'\82'中包含3个字符,分别是‘\’,'8','2',赋值时是将字符'2'给了a,实际上这个题和 char a = 'fdz'变量a的值是‘z’是一个道理,只是\具有迷惑作用而已,可以试验把‘\82’换成‘\zz’,则a的值为z,因此这道题选择包含一个字符。
在构造函数XB的下列定义中,正确的是()
A.XB::XB(int a,int b):x(a),y(b){ }
B.XB::XB(int a,int b):XA(a),y(b){ }
C.XB::XB(int a,int b):x(a),XB(b){ }
D.XB::XB(int a,int b):XA(a),XB(b){ }
派生类中的数据成员有基类中的数据成员和新增加的数据成员构成,如果新增加的数据成员中还包含有对象成员,则这些新增加的数据成员还会间接的包含这些对象中的成员,因此如果要对派生类中的成员进行初始化,就应该对以上这些数据成员进行初始化。
在类外定义派生类的构造函数的一般形式有两种为:
(1) <派生类名>::<派生类名>(参数总表):基类名(参数表),对象名1(参数表1),对象名2(参数表2),...对象名n(参数表n)
{
初始化语句;
}
参数总表中是需要进行初始化的三类数据成员(基类中的数据成员、派生类中新增加的普通类型的数据成员、派生类中新增加的对象中的数据成员)。对于使用默认构造函数的基类和对象成员,可以不给出类名或对象名以及参数表。
(2)也可以有另一种形式,那就是像本题中的,写成成员列表初始化的形式,也就是将(1)中构造函数体内的初始化语句搬到冒号后面去:
<派生类名>::<派生类名>(参数总表):基类名(参数表),对象名1(参数表1),对象名2(参数表2),...对象名n(参数表n),派生类中的成员(参数表){ }
(3)中成员列表初始化的方式更常用。
XB::XB(int a,int b): XA(a),y(b){} 派生类构造函数不能直接初始化类中的基类成员,因为它们在基类中可能是私有的,不能访问赋值。要想初始化这些基类成员,必须通过基类的构造函数才能完成。
调用基类构造函数 语法形式:
派生类构造函数名(形参列表):基类名(形参1),基类名(形参2),····
{
······初始化派生类成员变量
}
假定x=65530,下面函数的返回值是多少?()
int func(x)
{
int countx = 0;
while (x)
{
countx++;
x = x & (x - 1);
}
return countx;
}
求代码输出
做对此题有两个关键点:
1、知道函数的功能是求1的个数
2、能够快速将65530换算成二进制
65535是16个1,65530=65535-5,5是101,有2个1,则65530有14个1。
union X
{
int x;
char y[4];
};
如果
X a;
a.x=0x11223344;//16进制
则:()
A.y[0]=11
B.y[1]=11
C.y[2]=11
D.y[3]=11
这里需要考虑存储模式:大端模式和小端模式。
大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
union 型数据所占的空间等于其最大的成员所占的空间。对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存取都是从union 的首地址位置开始。
数组在大端小段情况下的存储
在这里一、以value=0x12345678为例
Big-Endian 大端 :低地址存放高段位
buf[3] (0x78) – 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) – 高位
`Little-Endian:低地址存放低位,如下:
高地址
buf[3] (0x12) – 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) – 低位
C代码中可能会出现如下类型的结构体定义:
typedef struct holder {
struct holder *next;
struct holder *prev;
char buffer[ 0 ];
}holder;
A.方便管理内存缓冲区
B.减少内存碎片化
C.是结构题数据对其
D.没有作用
答案 A B
下面是网络上一些关于柔性数组的知识
typedef struct{
char a;
char b[0];
};
其中 char b[0], 叫做柔性数据。
这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:
1.不需要初始化,数组名直接就是所在的偏移
2.不占任何空间,指针需要占用int长度空间,空数组不占任何空间。
“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和他后面的元素的地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当做指针使用。
方便管理内存缓冲区
减少内存碎片化
若变量已正确的定义为float类型,要通过输入函数scanf(“%f%f%f”,&a,&b,&c)给a赋值10,b赋值22,c赋值33,以下不正确的输入形式是
A 10
22
33
B 10.0,22.0,33.0
C 10.0
22.0,33.0
D 10 22
33
答案为BC
scanf的引号内不存在逗号