1、下面程序段的运行结果是()
1
2
3
4
intx, y;
x = y = 0;
while(x < 15) y++, x += ++y;
printf("%d,%d", y, x);A 、20,7
B、6,12
C、20,8
D、8,20
答案:D
解析:本题主要是分为两个语句来看,首先是y++,然后是x += ++y,这样一说这个题就变得很清楚了,第一次x=2,y=2;第二次x=6,y=4;第三次x=12,y=6;第四次x=20,y=8
2、下列程序的功能是将 s 中的字符串按长度由小到大排列,请为横线处选择合适的程序()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <string.h>
voidf(char*p[],intn) {
char*t;
inti, j;
for(i = 0; i < n - 1; i++)
for(j = i + 1; j < n; j++)
if(strlen(*(p + i)) >strlen(*(p + j))) {
t = *(p + i);
*(p + i) = *(p + j);
*(p + j) = t;
}
}
intmain() {
char*s[] = {"abc","abcdef","abbd"};
f(s, 3);
for(inti = 0; i < 3; i++)
printf("%s\n", ____);
return0;
}A、s+i
B、s[i]
C、*s[i]
D、&s[i]
答案:B
解析:该题主要考察指针数组的遍历,因此直接看主函数部分即可;这是一个指针数组,数组中的每一个元素都是一个指向字符(实际上是字符串字面量的首字符)的指针。
A选项:s是数组名,代表数组首元素的内存位置(但不是一个可以修改的左值),在大多数表达式中
s会被隐式转换为char**(指向字符指针的指针),指向数组的首元素(即s[0]),因此它+i并不能遍历数组。B选项:s[i]是数组s中第
i个元素的值,类型是char*(字符指针),指向第i个字符串的首字符,通过它可以遍历数组C选项:s[i]是指向第i个字符串的首字符,再加*得到的就是该字符串的第一个字符,而不是整个字符串
D选项:s[i]本身是指向字符指针的一个指针,对它取地址得到的是这个指针的地址,并不是这个字符串
指针数组的类型本质上是一个二级指针类型
3、参考以下代码,在大端字节机器中x.c的值为
1
2
3
4
unionA {
shortc;
charbuf[4];
} x = {0x01, 0x02, 0x03, 0x04}A、0x102
B、0x201
C、0x304
D、0x403
答案:A
解析:首先我们看到题目说的是大端字节机器,在大端字节机器中数据的高位字节存放在内存的低地址处,而低位字节则存放在高地址处,如下图所示:
在大端机器中,数据的读取是从低位地址开始,即内存的低地址处开始的,但存储时高位字节存放在低地址,因此在我们输出x.c的时候因为是short所以只会读取2个字节所以从低地址开始读取读到的就是0x01和0x02,省略第一个0得到的就是0x102;
在小端机器中,数据的存储如图右,如果还是同样读取2个字节,则读取到的就是0x04和0x03,我在我自己的小端机器上将一个int强转为2个字节的short输出得到的结果是0x304,
这跟0x04 0x03不同,原因是我使用的是十六进制输出,尽管在小端机器上低位字节首先存储,但在打印时,十六进制数仍然按照高位在前、低位在后的方式显示(这是十六进制数的标准表示方式)。
4、则以下程序段的执行结果是( )
1
2
3
4
charch ='a';
intk = 12;
printf("%x,%o,", ch, ch, k);
printf("k=%%d\n",k);A、因变量类型与格式描述符的类型不匹配,输出无定值
B、输出项与格式描述符个数不符,输出为零值或不定值
C、61,141,k=%d
D、61,141,k=%12
答案:C
解析:本题主要考察输出,我们直接看第一个printf,首先注意双引号,双引号里面只有%x和%,但是后面却有三个参数,这就会导致参数k被忽略,只会输出ch的十六进制和八进制结果;我们再来看第二个printf,%是控制符,%%会输出一个%,而d就会原样输出,k的值也不会被输出,要想输出选项D中的k=%12,我们的第二个输出语句就应该改为printf("k=%%%d\n",k);,这样才能以%d来打印k的值。
5、在C程序中,可把整型数以二进制形式存放到文件中的函数是()
A、fprintf函数
B、fread函数
C、fwrite函数
D、fputc函数
答案:C
解析:fprintf函数:这个函数用于将格式化的数据写入文件,它通常用于文本文件的写入,而不是二进制文件。就是将数据按照指定的格式写入,数据可以是可以是整数、浮点数、字符、字符串等;
fread函数:这个函数用于从文件中读取数据,因此不适用于将数据写入文件;
fwrite函数:这个函数用于将内存中的数据块(包括整型数)以二进制形式写入文件;
fputc函数:这个函数用于将单个字符写入文件,不适用于写入整型数,特别是以二进制形式。
6、下面的代码输出是()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
intmain() {
unionData {
struct{
intx;
inty;
} s;
intx;
inty;
} d;
d.x = 1;
d.y = 2;
d.s.x = d.x * d.x;
d.s.y = d.y + d.y;
printf("%d %d\n", d.s.x, d.s.y);
return0;
}A、1 4
B、4 4
C、1 2
D、4 8
答案:D
解析:我们先来分析代码,代码中是一个共用体(联合体)里面嵌套了一个结构体,共用体是用同一片空间地址,因此我们在对共用体里面的x和y赋值的时候,只会保留最后一次的赋值结果,在执行完
d.y = 2;这个语句后,d.y、d.x和结构体里面的x的值都为2,在执行d.s.x = d.x * d.x;这个语句之后结构体中的x就为4,同时因为结构体在共用体里面,它们共用同一片空间地址,所以此时d.x和d.y的值也变成了4,最后再把结构体里面的y赋值,此时y就为8,故答案为D。
7、以下函数用法正确的个数是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
voidtest1(){
unsignedchararray[MAX_CHAR+1],i;
for(i = 0;i <= MAX_CHAR;i++){
array[i] = i;
}
}
char*test2(){
charp[] ="hello world";
returnp;
}
char*p = test2();
voidtest3(){
charstr[10];
str++;
*str ='0';
}A、0
B、1
C、2
D、3
答案:A
解析:首先来看第一个函数,定义了一个无符号的字符数组,在这里我们就要考虑到一个范围的问题,无符号的字符型范围是0~255,因此这里的i的范围也就是0~255,故当i++超过256之后就无法表示了,以此第一个函数错误;
第二个函数,定义了一个字符数组,数组名为P,这个函数是一个指针函数,它的返回值是P,而这个P是数组名,函数会将字符串常量的字符逐个复制到p数组里面,返回p则是返回数组p,p是局部变量是在栈区开辟的,在执行完函数之后会被计算机自动释放,它的内部创建的数组,变量等会随着函数体的结束而销毁,P会指向一段无效的空间,因此第二个也不对;
第三个函数,str是一个数组名,在下面对str++是错误的,因为数组名是一个常量,不能修改它的值。
8、设有如下的说明和定义
1
2
3
4
5
6
struct{
inta;
char*s;
} x, *p = &x;
x.a = 4;
x.s ="hello";则以下叙述中正确的是()
A、(p++)->a与p++->a都是合语法的表达式,但二者不等价
B、语句 ++p->a; 的效果是使p增1
C、语句 ++p->a; 的效果是使成员a增1
D、语句 *p->s++; 等价于 (*p)->s++;
答案:C
解析:题目是定义了一个结构体,结构体里面是一个整形变量a和一个字符型的指针,然后定义了这个结构体类型的变量x,指向这个结构体类型的指针p,并且将p初始化指向x;然后对a和s赋值;
首先我们需要清楚的是在c语言中,成员运算符->的优先级高于单目运算符++,接下来看选项,对于A选项,p++是后++,所以会先访问结构体的成员a之后p再自加指向另一个地址,这是合法的,对于第二个p++->a是不合法的,p++是一个右值,它不能作为->的左侧操作数。
B选项:首先会访问结构体的成员a,之后使成员a增1,因此C选项就是正确的
D选项:对于*p->s++,p会先跟->结合,先访问s,这里访问的s是一个指针,现在指针指向的是第一个元素h,将指针s++,则指针会指向第二个元素e,此时再加*,就会取到指针指向的内容,也就是字母e;对于 (*p)->s++;先对p解引用得到x,然后访问x中的成员s,再对指针进行++操作,这样得到的是指向e的指针,是一个地址,所以两者并不等价。
这里提到了左值和右值,那就顺便解释一下:
左值通常指的是一个具有持久性和位置依赖性的表达式。在C和C++中,左值通常表示一个具体的对象或变量,它们可以在内存中有明确的存储位置,并且可以通过取地址运算符(&)获取其地址。左值最显著的特征是它可以出现在赋值操作的左侧,即可以将另一个值赋给它。这种属性让左值在需要存储和修改数据时成为首选。例如,变量名、数组的元素等都是左值的典型示例。
右值通常表示一个临时的、不具有持久性和位置依赖性的表达式。右值通常代表的是在表达式计算过程中产生的临时结果,这种结果无需长时间存储,只在表达式计算的瞬间有用。在C和C++中,右值不能出现在赋值操作的左侧,因为它们不具备可修改性。右值也没有明确的内存位置,因此不能通过取地址运算符获取其地址。例如,常量、字面值、临时对象、函数返回的临时结果等都是右值的示例。
- 持久性:左值强调长期性和位置的固定,而右值则强调数据的临时性和即刻消失。
- 位置依赖性:左值可以具有明确的内存位置,而右值则通常没有。
- 赋值操作:左值可以出现在赋值操作的左侧,而右值则不能。
- 用途:左值适用于进行修改操作和作为函数参数传递,而右值则适用于一次性计算和资源转移等场景。
9、下列代码输出是()
1
2
3
4
5
6
7
8
9
char*a[] = {"BEIJING","SHENZHEN","SHANGHAI","GUANGZHOU"};
char**pa[] = {a+3, a+2, a+1, a};
char***ppa = pa;
intmain(void) {
printf("%s, ", **++ppa);
printf("%s, ", *--*++ppa+3);
printf("%s, ", *ppa[-2]+3);
printf("%s", ppa[-1][-1]+1);
}A、BEIJING, SHENZHEN, SHANGHAI,GUANGZHOU
B、SHANGHAI, JING, NGZHOU, HENZHEN
C、SHANGHAI,BEIJING, GUANGZHOU, SHENZHEN
D、SHANGHAI,EIJING,ZHOU,ZHEN
答案:B
解析:
优先级:++与 * 同优先级,自右向左结合,+的优先级低于它俩
**++ppa:首先ppa与++结合,ppa指向pa[1],*pa[1]得到的是指针a[2],再对a[2]取内容得到的就是SHANGHAI
*--*++ppa+3:在第一个输出中,ppa就指向了pa[1],它再自加,则它指向pa[2],对它取内容就得到指向a[1]的指针,然后这个指针自减1,则此得到的是指向a[0]的指针,再取内容就得到了指向BEIJING的指针a[0],此时这个指针指向的是首字母B,然后+3,此时指针指向第四个字母J,然后进行打印出的结果就为JING;
*ppa[-2]+3:在这里ppa[-2]就相当于*(ppa-2),在前面两个输出执行之后,现在ppa指向的是pa[2],现在-2之后指针指向pa[0],但是此时ppa本身指向pa[2],pa[0]又指向a[3],现在又取内容*ppa[-2],这时得到的是一个指向字符串GUANGZHOU的指针,这个指针指向首字母G,然后再+3,之后指针指向的是字母N,这时候打印出来的就是NGZHOU;
ppa[-1][-1]+1:首先ppa[-1][-1]等价于*(*(ppa-1)-1),ppa指向的是pa[2],先进行-1,这时候ppa指向pa[1],然后*pa[1],得到的是指向a[2]的指针,这个指针再-1,减一之后这个指针指向a[1],然后*a[1],得到的是指向字符串SHENZHEN的指针,这个指针指向首字母S,然后指针+1,这时指针指向第二个字母H,然后打印得到的是HENZHEN。
关键点:本题的关键在于指针++与+n(n为具体数字),的区别,++是指针自加,加完之后指针的指向发生了改变,但是+n之后是指针指向当前位置的后面第n个位置,这时指针本身的指向并没有改变;还有一个是变址符[]和*的互换,例如p[3]可以换成*(p+3)。
10、有如下所示程序,请问输出的结果为什么?
1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 212;
char *p = (char*)&a;
printf("%d\n", *p);
return 0;}
答案:-44
解析:首先程序定义了一个整形变量并赋值为212,计算机存储这个数需要把它转为二进制存储,212转为二进制为1101 0100,之后因为它是int型变量,计算机会给它开辟四个空间地址,但是由于它没有超过256,因此在第一个地址就能存完,后面三个地址上存的全部都为0;存完之后第二步把它强转为了char类型,char类型之占一个字节,但是由于计算机默认存储的是有符号的数,这时一个字节8位就只能最大存128,最高位为符号位,但是在转之前我们的数已经存到了第一个字节空间地址上,因此在我们强转之后由于存储不下212,因此计算机会把该空间地址上的数的第一位默认为符号位,这时符号位为1,是负数,因此输出我们需要去找它的补码,1101 0100的补码就为1010 1100,转为十进制输出就为-44。




&spm=1001.2101.3001.5002&articleId=143055388&d=1&t=3&u=a972e20c166a4f3f986690f4274a9fe7)
1735

被折叠的 条评论
为什么被折叠?



