文章目录
- 🌏大小端与传参
- 🌏类型范围
- 🧭逻辑判断
- 🧭进制数与格式化输出
- 🍉计算次数
- 🍉常量指针与指针常量
- 🌌字符指针与字符数组
- 🌌指针与数组
- 🪐内存对齐
- 🎄动态内存分配
🌏大小端与传参
假设在一个 32 位 little endian 的机器上运行下面的程序,结果是多少?
#include <stdio.h>int main(){ long long a = 1, b = 2, c = 3; printf("%d %d %dn", a, b, c); return 0;}
A 1,2,3
B 1,0,2
C 1,3,2
D 3,2,1
正确答案:B
这题的考点就是大小端字节序与函数传参顺序
关于大小端问题就是数据在内存中的存储顺序
大端模式(大端字节序):数据的低字节
保存在内存的高地址
中,高字节
保存在低地址
中
小端模式(小端字节序):低位
存低地址
,高位
存高地址
下图这就是标准的小端存储
还有一个就是函数传参顺序,调用printf函数需要压栈建立函数栈帧,函数传参是从右向左的,下面就可以看到,不管a,b,c是谁先定义,都只与传参顺序有关。栈底是高地址,栈顶是低地址
a,b,c都是long long类型8字节,而%d只会获取4字节
🌏类型范围
如下代码输出的是
char a=101;int sum=200;a+=27;sum+=a;printf("%dn",sum);
A: 327
B: 99
C: 328
D: 72
正确答案:D
这题的考点就是类型的范围,char类型是8位,也就是-128~127
所以a+=27后a的值为-128
🧭逻辑判断
以下程序的输出结果是
#include <iostream>int main() { int x = 3, y = 3; switch (x % 2) { case 1: switch (y) { case 0:cout << "first"; case 1:cout << "second"; break; default: cout << "hello"; } case 2:cout << "third"; }}
A second third
B hello
C first second
D hellothird
正确答案:D
这题的考点就是switch case语句的理解,当进入case语句没有break时,就会继续按顺序执行,还有break与continue,continue只会跳出当前循环,然后判断是否满足下一次的循环条件
#include <stdio.h>int main(){ int a = 1, b = 2, c = 3, d = 0; if (a == 1 && b++ == 2) if (b != 2 || c-- != 3) printf("%d,%d,%dn", a, b, c); else printf("%d,%d,%dn", a, b, c); else printf("%d,%d,%dn", a, b, c); return 0;}
下面程序输出的是
A 1, 2, 3
B 1, 3, 2
C 3, 2, 1
D 1, 3, 3
正确答案:D
这题的考点就是逻辑语句的短路原则
if(表达式一 || 表达式二)当表达式一为真时,就不会执行表达式二
if(表达式一 &&表达式二) 当表达式一为假 时,就不会执行表达式二
所以b != 2位真后就不会执行后面的
比如要拿栈顶的元素与val比较时,只有栈不为空时才能取栈底元素
if (!st.empty() && st.top() == val)
🧭进制数与格式化输出
#include<iostream>using namespace std;int main(){ int m = 0123, n = 123; printf("%o %on", m, n); return 0;}
程序运行后的输出结果是()
A 0123 0173
B 0123 173
C 123 173
D 173 173
正确答案:C
这题就是C语言常见进制的表示形式以及打印格式化数据的方式
二进制: 101b
八进制:0123 printf打印时 %o
十进制: 101 printf打印时 %d
十六进制:0x123 printf打印时 %x
m是八进制,所以直接打印123
以下程序的运行结果是()
int main(){ printf("%s , %5.3sn", "computer", "computer"); return 0;}
A computer, puter
B computer, com
C computer, computer
D computer, compu.ter
正确答案:B
这题考点与上面类似,也是打印格式化的数据
%m.ns,m表示宽度,n表示打印字符的个数,右对齐,不足补空格,当n大于m时直接打印n个字符。-m就是左对齐,还有%04d右对齐打印,宽度为4,不足补0
🍉计算次数
求函数返回值,输入x = 9999
int func(int x) { int count = 0; while (x) { count++; x = x & (x - 1); } return count;}
A:8
B:9
C:10
D:12
正确答案:A
这题的考点就是计算一个数中1的个数,x=x&(x-1)会不断将x中的1变为0,到最后所有位都为0时循环也就结束了,9999转化为2进制有8个1
同样的还有计算一个数中0的个数
while (x + 1){ x = x | (x + 1);//计算0的个数 ++count;}
#include<stdio.h>int cnt = 0;int fib(int n){ cnt++; if (n == 0) return 1; else if (n == 1) return 2; else return fib(n - 1) + fib(n - 2);}int main(){ fib(8); printf("%d", cnt);}
下列程序执行后, 输出的结果为()
A 41
B 67
C 109
D 177
正确答案:B
这题的考点就是计算函数调用的次数,实际上就是计算斐波那契的次数,因为fib(8)最后递推到fib(0)和fib(1),利用递归的思想,我们可以直接回归到f(0)开始计算
fib(0) 1
fib(1) 1
fib(2) 1+fib(1)+fib(0) = 3
fib(3) 1+fib(2)+fib(1) = 5
fib(4) 1+fib(3)+fib(2) = 9
fib(5) 1+fib(4)+fib(3) = 15
fib(6) 1+fiib(5)+fib(4) = 25
fib(7) 1+fib(6)+fib(5) = 41
fib(8) 1+fib(7)+fib(6) = 67
🍉常量指针与指针常量
请声明一个指针,其所指向的内存地址不能改变,但内存中的值可以被改变。
A const int const *x = &y;
B int * const x = &y;
C const int *x = &y;
D int const *x = &y;
E const int * const x = &y;
正确答案:B
这题的考点就是常量指针与指针常量的认识。
指针常量
:指针本身是一个常量,指针的指向不能改变,但指针所指向的值可以发生改变,可以通过解引用改变指针所指向空间的值
常量指针
:指向常量的指针,不能通过解引用改变指针所指向的空间的值,但指针的指向可以发生改变
区分:const与*的相对位置
const在*左边修饰的是指针所指的空间,所以是常量指针,const在*右边修饰的是指针,所以是指针常量
🌌字符指针与字符数组
下面叙述错误的是()
char acX[] = "abc";char acY[] = { 'a','b','c' };char* szX = "abc";char* szY = "abc";
A acX与acY的内容可以修改
B szX与szY指向同一个地址
C acX占用的内存空间比acY占用的大
D szX的内容修改后,szY的内容也会被更改
正确答案: D
这题考点和上面类似,判断的是字符数组与字符指针的区别,字符数组是从常量区将字符串拷贝到数组,数组中存放的字符串是可以修改的,而字符指针是指向在常量区的常量字符串,不可修改,szX与szY指向的都是那个常量字符串,所以指向的是同一个地址
C选项,因为acY里面没有0,而acX会带0,所以正确
🌌指针与数组
下面程序打印的结果是
#include <stdio.h>int main(){ char p1[15] = "abcd", *p2 = "ABCD", str[50] = "xyz"; strcpy(str + 2, strcat(p1 + 2, p2 + 1)); printf("%s", str);}
A xyabcAB
B abcABz
C ABabcz
D xycdBCD
E 运行出错
正确答案:D
这题的考点就是对字符函数stcpy和strcat的认识,拷贝和追加的目的地空间都要足够大,不然程序就会崩溃运行出错。strcat会返回追加后的目的地址,也就是p1+2
假设函数原型和变量说明如下,则调用合法的是( )
void f(int **p);int a[4]={1,2,3,4};int b[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int *q[3]={b[0],b[1],b[2]};
A: f(a);
B: f(b);
C: f(q);
D: f(&a);
正确答案:C
这题的考点就是对指针和数组的掌握
A选项:数组名是首元素地址,应该用int* p接收
B选项:数组名是首元素地址,也就是一维数组的地址,应该用int(*p)[ ]接收
C选项:q是一个指针数组,数组ing是首元素地址,也就是b[o]的地址,b[o]是一个一维数组,但数组传参会退化成指针,所以是一个一级指针的地址,可以用int** p接收
D选项:&数组名,应该用int(*p)[ ]接收
#include<iosteam.h>int main() { int n[][3] = { 10,20,30,40,50,60 }; int(*p)[3]; p = n; cout << p[0][0] << "," << *(p[0] + 1) << "," << (*p)[2] << endl;}
下面程序的输出结果是
A 10, 30, 50
B 10, 20, 30
C 20, 40, 60
D 10, 30, 60
正确答案:B
这题的考点同样是对数组与指针的掌握情况n是一个2行3列的二维数组,p是一个数组指针,指向的是一个有3个元素的int型数组
数组 a 的定义为: int a[3][4]; 下面哪个不能表示 a[1][1] ( )
A: *(&a[0][0]+5)
B: *(*(a+1)+1)
C: *(&a[1]+1)
D: *(a[1]+1)
正确答案:C
C选项实际表示的是a[2][0]
void (*s[5])(int) 表示意思为( )
A: 函数指针 B: 函数指针数组 C: 数组指针函数 D: 语法错误
正确答案:B
s先和[ ]结合,所以是一个数组有5个元素,元素类型是void(*)(int)函数指针,所以s是一个函数指针数组
🪐内存对齐
下面两个结构体
struct One{ double d; char c; int i;};struct Two{ char c; double d; int i;};
在#pragma pack(4)和#pragma pack(8)的情况下,结构体的大小分别是
A 16 24, 16 24
B 16 20, 16 20
C 16 16, 16 24
D 16 16, 24 24
正确答案: C
这题的考点就是内存对齐问题,在#pragma pack(4)的情况下,最大对齐数是4,在#pragma pack(8)的情况下,最大对齐数是8,所以在计算struct(Two)时,本来是20但要是对大对齐数的整数倍,所以就变成了24了
在32位cpu上选择缺省对齐的情况下,有如下结构体定义:
struct A{ unsigned a : 19; unsigned b : 11; unsigned c : 4; unsigned d : 29; char index;}
则sizeof(A)的值为
A 9
B 12
C 16
D 20
正确答案:C
这题考察的是对位段的认识,位段的成员可以是 int
、 unsigned int
、 signed int
或者是 cha
r 类型的整形家族,位段的成员名后边有一个冒号和一个数字。每次开辟4字节
或1字节
冒号后面接的是所需要的的比特位
🎄动态内存分配
关于内存管理,以下有误的是( )(不定项选择)
A: malloc在分配内存空间大小的时候是以字节为单位
B: 如果原有空间地址后面还有足够的空闲空间用来分配,则在原有空间后直接增加新的空间,使得增加新空间后的空间总大小
是:newSize
C: 如果原有空间地址后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存,并把先前内存空间中的数
据复制到新的newSize大小的空间中,然后将之前空间释放
D: free函数的作用是释放内存,内存释放是标记删除,会修改当前空间的所属状态,并且会清除空间内容
E: 可以通过内存分配函数malloc(size_t)直接申请物理内存
正确答案:DE
free函数,作用是释放内存,内存释放是标记删除, 只会修改当前空间的所属状态,并不会清除空间内容
free释放的内存不一定直接还给操作系统,可能要到进程结束才释放。malloc不能直接申请物理内存,它申请的是虚拟内存
以上就是C语言的基础选择提了,如果这些题都做对了,那你的C语言基础还是很扎实的,希望我的文章对你有所帮助,欢迎👍点赞 ,📝评论,🌟关注,⭐️收藏