目录
🔒2.以下程序运行时,若输入1abcedf2df<回车>输出结果是()
4.下面两个结构体,在#pragma pack(4) 和 #pragma pack(8)的情况下,结构体的大小分别是()
7.设有定义char* p[] = {"Shanghai","Beijing","Honkong"};结果 j 字符的表达式是()
13. 由多个源文件组成的C程序,经过编辑、预处理、编译、链接等阶段会生成最终的可执行程序,下面哪个阶段可以发现被调用的函数未定义()
14.有以下宏定义,则执行语句:z = 2*(N+Y(5+1))后,z的值为:()
一:选择题
🔒1.请问该程序输出是多少?
int main()
{
unsigned char i = 7;
int j = 0;
for (; i > 0; i -= 3)
{
++j;
}
printf("%d\n", j);
return 0;
}
A:2 B: 死循环 C:173 D:172
💡解析:
本题考察的是对无符号(unsigned)理解;
字符 i 是无符号的,永远不会小于0;而循环结束的条件是i>0; 终止循环的唯一条件就是 i等于0的情况;
i -=3. 7-4-1 ;当i等于1时,再执行会变成-2;但是由于i是无符号的,所以此时 -2的补码会认为是无符号型,变成一个超大数字;
我们先复习char数据类型范围:
char和signed类型:-128~+127;
unsigned char类型:0~255;
-2的补码是 11111110 ;这个数当作无符号数看待就是254;
所以此时 i 不是 -2 而是254,再循环-=3;循环了84后 i 等于2;然后又变成-1;
-1的补码就是:11111111;这个数当作无符号数是 255;而255循环-3,循环了85次后变成0;
所以是 7 4 1 254....5 2 255...3 0;
7~1三次,254~5有84次,2一次,255~3 85次;一共173次;选C
🔒2.以下程序运行时,若输入1abcedf2df<回车>输出结果是()
int main()
{
char a = 0, ch;
while ((ch = getchar()) != '\n')
{
if (a % 2 != 0 && (ch >= 'a' && ch <= 'z'))
ch = ch - 'a' + 'A';
a++;
putchar(ch);
}
printf("\n");
return 0;
}
A:1abcedf2df B:1ABCEDF2DF C:1AbCeDf2dF D:1abceDF2DF
💡解析:
本题考察的是字符Ascii码理解
我们先看 ch = ch -'a' + 'A' ; 发现后面其实就是-32;相当于小写转大写了;思路一下明了了
第一次,0%2 等于0;0!=0 条件为假;直接输出1了;后面循环基本是满足if条件就进入,将小写转大写; 选C
🔒3.以下哪个选项一定可以将flag的第二个bit置0()
A:flag &=~2 B:flag |= 2 C:flag ^= 2 D:flag >>2
💡解析:
本题考查是是对位操作符理解
我们先假设flag二进制为 11111111;
要保证其他位不变,第二位置0;可以按位& 上一个 11111101;
怎么得到这个数呢?我们先看2的二进制为:00000010;是不是将2取反就可以得到此数字,然后将该数字按位&上flag就可以啦!!!
知识点:
1.&: //按位与 :只有两个数的二进制同时为1,结果才为1,否则为0。
&1可以得到该二进制最后一位是0还是1
2. ~ 对一个数的二进制按位取反
🔒4.下面两个结构体,在#pragma pack(4) 和 #pragma pack(8)的情况下,结构体的大小分别是()
#pragma pack(4) //设置默认对齐值 4
struct One
{
double d;
char c;
int i;
};
struct Two
{
char c;
double d;
int i;
};
#pragma pack() 恢复默认字节对齐方式
#pragma pack(8) //设置默认对齐值 8
struct One
{
double d;
char c;
int i;
};
struct Two
{
char c;
double d;
int i;
};
#pragma pack() 恢复默认字节对齐方式
A:16 24,16 24 B:16 20,16 20 C:16 16 ,16 24 D:16 16 , 24 24
💡解析:
本题考察的是内存对齐,结构对齐
知识点1:
#pragma pack(4): 表示原先VS默认的对齐值改为 4;
#pragma pc(): 表示回复默认的字节对齐;
知识点2:
结构体的内存对齐:
首先得掌握结构体的对齐规则:
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍;
所以这里直接画图计算就好啦!!! 选C
🔒5.在上下文和头文件均正常情况下,以下程序的输出结果是()
int main()
{
int x = 1;
do {
printf("%2d\n", x++);
} while (x--);
return 0;
}
A: 1 B:无任何输出 C:2 D:陷入死循环
💡解析:
知识点:
%0.2d的意思是输出占2位,若位数不够则补0.
%2d的意思是输出占2位,若位数不够则补空格
主要区别是要用0补位,还是用空格补位。默认右对齐;左对齐加 -
因为这里1进入后,后++也变成了2;然后while(x--)又变成1;如此往复死循环;选D
🔒6.下列C程序执行后c输出结果为() (32位)
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = -3;
unsigned int b = 2;
long c = a + b;
printf("%ld\n", c);
}
A:-1 B:4294967295 C:0x7FFFFFFF D:0xFFFFFFFF
💡解析:
本题依旧考察的是无符号类型;
-3的补码:11111111111111111111111111111101
2的补码:00000000000000000000000000010
c的补码:111111111111111111111111111111111
按照原码打印:补码->原码:取反加+;
所以为: 10000000000000000000000000001
这个数字当作有符号数看待就是 -1;选A
🔒7.设有定义char* p[] = {"Shanghai","Beijing","Honkong"};结果 j 字符的表达式是()
A:*p[1] + 3 B:*(p[1] + 3) C:*(p[3] + 1) D:p[3] [1]
💡解析:
本题考查的是指针数组
数组下标 0 1 2 分别对应了三个字符串首元素地址;
A:*p[1] 这一步解引用找到的是字符B,然后+3得到acssi码值 为字符E
C和D 直接越界访问了;
B:就是找到首元素地址后+3到了j 位置,解引用就是j啦;选B
🔒8.执行如下函数,i的值为()
int f(int x)
{
return ((x > 2) ? x * f(x - 1) : 3);
}
int i;
i = f(f(2));
A 30 B 无限递归 C 9 D 2160
💡解析:
这里考察的是三目操作符
知识点:
考察的是三目运算符, exp1?exp2:exp3;
exp1为真,执行exp2;
exp1为假,执行exp3;
C语言规定:0为假,非0为真。
所以 若要求与M等价,则要满足M取0时为假,取非0数值时为真。2>2? 2*f(2-1):3 这里return 的是3;
3>2? 3*f(3-1): 3 这里执行 3*f(2) 也就是 3*3 选C
🔒9.在此句中,p[1][2]的值是()
int p[][4] = {{1},{3,2},{4,5,6},{0}}
A 1 B 0 C 6 D 2
💡解析:
本题考查的是二维数组
没有初始化的位置为0;秒杀;选B
🔒10.fun(21)运行结果是()
int fun(int a)
{
a ^= (1 << 5) - 1;
return a;
}
A 10 B 5 C 3 D 8
💡解析:
本题考察的是操作符;
21的二进制:00010101
1<<5:1向左移动5位:00010000;
然后-1后:00001111;
异或后:00001010; 这个数为10;选A
🔒11.下列关于C/C++的宏定义,不正确的是()
A:宏定义不检查参数正确性,会有安全隐患
B 宏定义的常量更容易理解,如果可以使用宏定义常量的话,要避免使用const常量
c 宏的嵌套定义过多会影响程宁的可读性,而且很容易出错
D相对于函数调用,宏定义可以提高程序的运行效率
💡解析:
因为宏定义的常量,没有类型,不够安全,严谨,
而const定义的具有类型,
C语言中const 修饰的变量叫 常变量
C++ 中 const 修饰的对象 就是 常量!! 选B
🔒12.下面关于指针的描述不正确的是()
A 当使用free释放掉一个指针内容后,指针变量的值被置为NULL
B 32位系统下任何类型指针的长度都是4个字节
C 指针的数据类型声明的是指针实际指向内容的数据类型
D 野指针是指向未分配或者已经释放的内存地址
💡解析:
考察对free的理解
free释放指针后,并不会主动将指针变量置NULL;需要我们手动置NULL;
🔒13. 由多个源文件组成的C程序,经过编辑、预处理、编译、链接等阶段会生成最终的可执行程序,下面哪个阶段可以发现被调用的函数未定义()
A 预处理 B 编译 C 链接 D 执行
💡解析:
考察的是对 程序编译,翻译环境的理解
预编译阶段:
1.头文件包含#include 预处理指令
2.define定义的符号替换
#define 预处理指令
3.注释删除
以上这些都是文本操作
编译阶段:
把c语言代码翻译成了汇编代码1、语法分析
2、词法分析
3、语义分析
4、符号汇总
汇编阶段:
把汇编指令翻译成了二进制的指令形成符号表,这样就能够找到源文件外部的符号(只能汇总全局符号)
链接阶段:
1、合并段表2、符号表的合并和重定位
选C
🔒14.有以下宏定义,则执行语句:z = 2*(N+Y(5+1))后,z的值为:()
#define N 3+1
#define Y(n) ((N+1)*n)
A 60 B 190 C 248 D 上述答案都不对
💡解析:
本题考察的是对宏定义的理解
宏定义的值都是直接替换的,所以我们直接数据代入即可;
#define N 3+1
#define Y(n) ((3+1+1)*5+1)则执行语句 z=2*(3+1+((5)*5+1)) 等于60选A
🔒15.有如下定义,则表达式a*b+d-c值的类型为()
char a;
int b;
float c;
double d;
A float B int C char D double
💡解析:
考察的是整型提升,算数转换
知识点:
整型提升:
C语言中字节数少于整型字节数的数据类型在进行整型运算时,该类型的数据会被默认转为整型数据。其中,该类型的数据被转化为整型数据的过程就称为整型提升
算数转换:
当字节长度大于 int 类型的数据参与运算时,如果某个操作符的两个操作数是不同类型,其中一个操作数需要按级别(级别低的数据转换为级别高的数据)转换为另一个操作数的类型,这样的转换即为算数转换
算数转换的数据级别(由高到低)
long double
double
long float
float
unsigned long int
long int
unsigned int
int
选D
二:编程题
🔒1.添加逗号
对于一个较大的整数 N(1<=N<=2.000,000,000)比如980364535,我们常常需要一位一位数这个数宁是几位数,但是如果在这 个数宁每三位加一个过号,它会变得更加易于朗读.因此,这个数字加上逗号成如下的模样: 980,364,535请写一个程序帮她完成这件申情
💡思路:
将这个输入进来的数,从低数位开始一个一个放到一个数组中,这个数组是个char类型的,因为要存放’ , ‘,所以每一位数在存放进去之前还要把它转成字符,而数组的长度是14,因为N的取值范围是(1<=N<=2,000,000,000),还要考虑逗号和’ \0 ';因为是每三位就要放一个逗号,所以用一个count来判断是否满足条件,这个判断条件就是count % 3,当这个值为0,证明就够三位了,就要添加逗号;
int main()
{
int n = 0, i = 0, count = 0;
scanf("%d", &n);
char arr[14];
//当n还不为0的时候循环继续
while (n)
{
//判断是否已经够三位数,并且不能为0
if (count != 0 && count % 3 == 0)
{
arr[i++] = ',';
}
//将每一位数转成字符再放进数组
arr[i++] = n % 10 + '0';
count++;
n /= 10;
}
//从后往前打印数组
for (--i; i >= 0; i--)
{
printf("%c", arr[i]);
}
return 0;
}
🔒2.删除公共字符
输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。
例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”
💡思路:
先输入两个字符串,这里用gets输入,然后在遍历第一个字符串str1的同时,判断当前str1的字符是否在第二个字符串中出现过,所以每一个str1的字符判断都要遍历一遍str2,如果在str2中找到了这个字符,就不打印这个字符,如果没找到,就打印;
注:这里也可以用
scanf("%[^\n]s",arr1); //遇到\n结束 getchar(); //吸收掉\n 避免被下面的scanf吸入而结束输入 scanf("%[\n]s", arr2); //输入
int func(char* str, char ch)
{
while (*str)
{
if (*str == ch)
{
return 0;
}
str++;
}
return 1;
}
int main()
{
char str1[100];
char str2[100];
gets(str1);
gets(str2);
int i = 0;
while (str1[i])
{
//在str2中找当前str[i]的字符
//找到返回0,不进入if语句,不打印
//找不到返回1,进入if语句打印
if (func(str2, str1[i]))
{
printf("%c", str1[i]);
}
//无论找没找到,i遍历下一个字符
i++;
}
return 0;
}
❤致谢:
感谢你看到这里,本篇为博主呕心沥血写下,采取图文并茂,思路讲解,知识点考察和知识点讲解及拓展..保姆式介绍,在解析中,我尽量用白话去解析某些晦涩的知识点;如果你觉得此文对你在C语言综合知识点有帮助,可以点赞为博主后面发更多的博文,感谢!!!
愿我们都是优秀程序员!!。
星光照亮每一位赶路人,我们都是前行者。