2022C语言基础题含解析(精选13题)!!!

2022面试题题解(2/3)

0. 我的计算器坏了?!

2^10=1024对应于十进制的4位,那么2^10000对应于十进制的多少位呢?


1.Solution
结果:3011

  • 10m<x<10(m+1)
  • m<log10x<(m+1)
  • m=⌊log10x⌋+1

#include<stdio.h>
#include <math.h>
int main()
{
  int y;
  scanf("%d",&y);
  int m;
  m=y*log10(2)+1;
  printf("%d",m);
  return 0;
}

1. printf还能这么玩?

尝试着解释程序的输出。

int main(void) {
  if ((3 + 2 < 2) > (3 + 2 > 2))
    printf("Welcome to Xiyou Linux Group\n");
  else
    printf("%d\n", printf("Xiyou Linux Group - 2%d", printf("")));               
}
  • 1.Solution

  • 输出结果为:Xiyou Linux Group - 2022
  • 这道题是对于printf的返回值与输出顺序的考察:
  • ①返回值:若成功则返回输出的字符数,输出出错则返回负值
  • ②输出顺序:printf函数从左往右读取,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的.所我们看见的结果是,从右边开始处理的.
  • -

2. 你好你好你好呀!

  • 程序的输出有点奇怪,请尝试解释一下程序的输出吧。
  • 请谈谈对sizeof()strlen()的理解吧。
int main(void)
{
    char p0[] = "Hello,Linux";
    char *p1 = "Hello,Linux";
    char p2[11] = "Hello,Linux";
    printf("p0==p1: %d, strcmp(p0,p2): %d\n", p0 == p1, strcmp(p0, p2));
    printf("sizeof(p0): %zu, sizeof(p1): %zu, sizeof(*p2): %zu \n",
           sizeof(p0), sizeof(p1), sizeof(*p2));
    printf("strlen(p0): %zu, strlen(p1): %zu\n", strlen(p0), strlen(p1));
}
  • 2.Solution
  • 运行结果:p0==p1: 0, strcmp(p0,p2): -72
  • sizeof(p0): 12, sizeof(p1): 8, sizeof(*p2): 1
  • strlen(p0): 11, strlen(p1): 11

  • 这道题的主要思想是两种字符串的表述方式:
  • ①一种是指针表示法,一种是数组名表示法
  • ②对sizeof与strlen的理解

首先是数据存储位置的概念:

  • 栈区 (stack) : 存放内容 : 局部变量, 参数;
  • 堆区 (heap) : 存放内容 : 存放程序运行中 动态分配 内存的数据;
  • 全局区/静态区 : 存放内容 : 全局变量, 静态变量;
  • 常量区 : 存放内容 : 常量; (比如char *s = “hello”,此处的hello就存储在常量区)
  • 代码区 (text segment) : 存放内容 : 存放函数体的二进制代码。

再来看看指针与数组的区别:

  • p1是一个存放在栈区的字符串指针,而它的值,是一个地址,该地址指向存放在常量区的字符串;
  • p0是一个存放在栈区的字符串数组,而它的值,就是字符串本身。

strcmp函数

  • strcmp接受字符串地址,依次比较所含字符的ASCii编码
  • 上述的差别在于\0的机制:
  • p0的大小由字符常量所决定,故最后一位可自动补\0
  • p2的大小已经确定,无位置补\0,
  • 所以p0在\0的位置时,p2对应的是该数组之后的乱码

sizeof与strlen函数

  • 共同点:都是以字节为单位返回大小
  • 区别 :strlen是函数,而sizeof是算符
  • strlen:返回字符串的大小,所以以\0为截止
  • sizeof:返回对象所占内存的大小
  • -

3. 换个变量名不行吗?

请结合本题,分别谈谈你对C语言中「全局变量」和「局部变量」的「生命周期」理解。

int a = 3;
void test()
{
    int a = 1;
    a += 1;
    {
        int a = a + 1;
        printf("a1= %d\n", a);
    }
    printf("a2= %d\n", a);
}
int main(void)
{
    test();
    printf("a3= %d\n", a);
}

3.Solution

  • 运行结果:a1= 1,a2= 2,a3= 3

  • ①全局变量 :
  • 存储位置 : 存放在静态存储区中。因此他们的生存周期是固定的,存在于程序的整个运行过程中。
  • 全局变量的作用范围 : 一般是从定义位置开始到本程序文件的末尾。在此作用域内,全局变量可以为程序中各个函数所引用。
  • ②局部变量 :
  • 局部变量的有效范围是局限于函数内部的,形参也是局部变量局部变量的改变无法影响到主调函数

-生命周期 :

  • ①把局部变量称为自动变量,即函数被调用时,系统自动为其局部变量分配存储单元;一旦该函数调用结束(不一定是整个程序运行结束),所有分配给局部变量的单元由系统自动回收
  • ②动态存储区是使用堆栈来管理的,适合函数动态分配与回收存储单元。而静态存储区相对固定,它用于存放全局变量和静态变量

  • 自动变量若没有赋初值,那么其存储单元是随机值。而静态局部变量如果定义时没有赋初值,系统会自动赋0
  • -

4. 内存对不齐

unionstruct各有什么特点呢,你了解他们的内存分配模式吗。

typedef union
{
    long l;
    int i[5];
    char c;
} UNION;
typedef struct
{
    int like;
    UNION coin;
    double collect;
} STRUCT;
int main(void)
{
    printf("sizeof (UNION) = %zu \n", sizeof(UNION)); 
    printf("sizeof (STRUCT) = %zu \n", sizeof(STRUCT));
}

4.Solution

  • 运行结果:sizeof (UNION) = 24 , sizeof (STRUCT) = 40

  • 共同点:都涉及到内存的对齐–>既要能够储存所有的数值,又要是各个数据类型的整数倍
  • 不同点:
  • 在union中,所有的联合成员共用一个空间,并且同一时间只能储存其中一个成员变量的值。
  • 在struct中,地址必须是从这个数据类型大小的整数倍开始,且内存大小为每个数据内存的加和。
  • ┑( ̄。。 ̄)┍

5. Bitwise

  • 请使用纸笔推导出程序的输出结果。
  • 请谈谈你对位运算的理解。
int main(void)
{
    unsigned char a = 4 | 7;
    a <<= 3;
    unsigned char b = 5 & 7;
    b >>= 3;
    unsigned char c = 6 ^ 7;
    c = ~c;
    unsigned short d = (a ^ c) << 3;
    signed char e = -63;
    e <<= 2;
    printf("a: %d, b: %d, c: %d, d: %d \n", a, b, c, (char)d);
    printf("e: %#x \n", e);
}

5.Solution

  • 运行结果:
    a: 56, b: 0, c: 254, d: 48
    e: 0x4

符号描述运算规则实例
&两个都为1,结果为10001 & 0001 = 1
|两个位都为0时,结果才为0。0000|0001=0001
^异或两个位相同为0,相异为10001 ∧ 0001 = 0000
~取反0变1,1变0。∼ 0 = 1 , ∼ 1 = 0
<<左移各二进位全部左移若干位,高位丢弃,低位补0。0001 < < k = 0100
>>右移各二进位全部右移若干位,对无符号数,高位补0,有符号数,右移补1 11。0100 > > k = 0001

6. 英译汉

请说说下面数据类型的含义,谈谈const的作用。

  1. char *const p
  2. char const *p
  3. const char *p

6.Solution

  • 第一个:它不能在指向别的变量,但指向(变量)的值可以修改。
  • 第二个:它不能在指向别的变量,但指向(变量)的值可以修改。
  • 第三个:它指向的值不能修改
  • ┑( ̄Д  ̄)┍

7. 汉译英

请用变量p给出下面的定义:

  1. 含有10个指向int的指针的数组。
  2. 指向含有10个int数组的指针。
  3. 含有3个「指向函数的指针」的数组,被指向的函数有1个int参数并返回int

7.Solution

  • 1.int num[10];
  • 2.int (*num)[10];
  • 3.int (*num[3])(int );
  • -

8. 混乱中建立秩序

你对排序算法了解多少呢?
请谈谈你所了解的排序算法的思想、稳定性、时间复杂度、空间复杂度。

提示:动动你的小手敲出来更好哦~

8.Solution


排序算法

  • 需要使用额外空间的排序:桶排序,归并排序
  • 平均情况为O(n^2):冒泡,简单插入,直接插入,
  • 平均情况为O(nlogn):归并,快排
  • 平均情况为0(nlogn~n^2):希尔

  • 思想
  • 本质上一般利用两个for循环进行逐一交接,交换
  • 优化:因为排序本质是对逆序数的改变,所以这是一个数学问题,通过分块操作,使前面的块普遍较小,后面的块普遍较大,这样可以在平均情况下突破O(n^2)的限制
  • 稳定性:
  • 数列中有相同的元素时,排序之后两个的顺序不变
  • 空间复杂度:
  • 运行时所额外占的空间体积
  • ┑( ̄▽  ̄)┍

9. 手脑并用

请实现ConvertAndMerge函数:
拼接输入的两个字符串,并翻转拼接后得到的新字符串中所有字母的大小写。

提示:你需要为新字符串分配空间。

char* convertAndMerge(/*补全签名*/);
int main(void) {
  char words[2][20] = {"Welcome to Xiyou ", "Linux Group 2022"};
  printf("%s\n", words[0]);
  printf("%s\n", words[1]);
  char *str = convertAndMerge(words);
  printf("str = %s\n", str);
  free(str);
}

9.Solution

#include <Stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *converAndMerge(char (*words)[20]);
int main()
{
char words[2][20]={"welcome to xi you ","linux group 2022"};
// printf("%s\n",words[0]);
// printf("%s\n",words[1]);
char *str=converAndMerge(words);
printf("str=%s\n",str);
free(str);
}
**************************************************
converandmerge的代码如下:

char *converAndMerge(char (*words)[20])
{
  char *NEW;
  char *OK;
  NEW=(char *)malloc(40);
  NEW=strcat(words[0],words[1]);
  OK=NEW;
  while(*NEW)
  {
    if(islower(*NEW))
        *NEW=toupper(*NEW);
    else if(isupper(*NEW))
        *NEW=tolower(*NEW);
    NEW++;
  }
return OK;
}

10. 给你我的指针,访问我的心声

程序的输出有点奇怪,请尝试解释一下程序的输出吧。

int main(int argc, char **argv) {
  int arr[5][5];
  int a = 0;
  for (int i = 0; i < 5; i++) {
    int *temp = *(arr + i);
    for (; temp < arr[5]; temp++) *temp = a++;
  }
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
      printf("%d ", arr[i][j]);
    }
  }
}

10.Solution
运行结果:

  • 0 1 2 3 4 25 26 27 28 29 45 46 47 48 49 60 61 62 63 64 70 71 72 73 74

  • 分析:
  • 这道题主要是二维数组的顺序问题:
  • arr[0],arr[1],arr[2]……都存储着相对应数组的地址
数组名对应地址
arr[0]&arr[0][0]
arr[1]&arr[1][0]
…………
arr[4]&arr[4][0]

其次的有关于指针与数组名的运算

  • 进行+,-的运算,每次移动所指向对象所占的字节乘以+与-的大小的距离
  • 指针可以进行单目++,–运算
  • 数组名不可以进行单目运算,否则首地址位置一变,所指向对象就变了

11. 奇怪的参数

你了解argc和argv吗?
直接运行程序argc的值为什么是1?
程序会出现死循环吗?

#include <stdio.h>
int main(int argc, char **argv)
{
    printf("argc = %d\n", argc);
    while (1)
    {
        argc++;
        if (argc < 0)
        {
            printf("%s\n", (char *)argv[0]);
            break;
        }
    }
}

11.Solution

  • 运行结果:argc = 1
  • /home/XYT公共的/code/no-name

  • argc : 命令行传入参数的总个数
  • argv : *argv[]是一个指针数组,里面存放的指针指向所有的命令行参数,argv[0]指向程序的全局路径,argv[1]指向在命令行中执行程序名后的第一个字符串,argv[2]指向第二个。

  • 可执行完,argc为int型,范围为-231~231
  • ヽ(ˋ▽ˊ)ノ

12. 奇怪的字符

程序的输出有点奇怪,请尝试解释一下程序的输出吧。

int main(int argc, char **argv)
{
    int data1[2][3] ={{0x636c6557, 0x20656d6f,    0x58206f74} 
    {0x756f7969, 0x6e694c20, 0x00000000}};
    int data2[] = {0x47207875, 0x70756f72, 0x32303220, 0x00000a32};
    char *a = (char *)data1;
    char *b = (char *)data2;
    char buf[1024];
    strcpy(buf, a);
    strcat(buf, b);
    printf("%s \n", buf);
    if(*buf='W') printf("LE");
    else printf("BE");
}

12.Solution

  • 运行结果:

  • Welcome to Xiyou Linux Group 2022

    LE


对于一段16进制的解析:

  • 对于一个,如(0X636c6557)16进制数,在计算机中以二进制来储存:0110 0011 0110 1100 0110 0101 0101 0111
二进制代码ASCII编码字符
0110001199c
01101100108l
01101010101e
0101011187W

  • 其次在计算机中对于读取一段数据采用小端序读取
  • 就是从后往前的读取
  • -

13. 小试宏刀

  • 请谈谈你对#define的理解。
  • 请尝试着解释程序的输出。
#include <stdio.h>
#define SWAP(a, b, t) t = a; a = b; b = t
#define SQUARE(a) a *a
#define SWAPWHEN(a, b, t, cond) if (cond) SWAP(a, b, t)
int main() {
  int tmp;
  int x = 1;
  int y = 2;
  int z = 3;
  int w = 3;
  SWAP(x, y, tmp);
  printf("x = %d, y = %d, tmp = %d\n", x, y, tmp);
  if (x > y) SWAP(x, y, tmp);
  printf("x = %d, y = %d, tmp = %d\n", x, y, tmp);
  SWAPWHEN(x, y, tmp, SQUARE(1 + 2 + z++ + ++w) == 100);
  printf("x = %d, y = %d,tmp=%d\n", x, y, tmp);
  printf("z = %d, w = %d ,tmp = %d\n", z, w, tmp);
}

13.Solution

  • 运行结果:
  • x = 2, y = 1, tmp = 1
  • x = 1, y = 2, tmp = 2
  • x = 2, y = 2,tmp=2
  • z = 5, w = 5 ,tmp = 2

分析:

  • 这道题主要时考察define替换时的括号问题
  • ①SQUARE(a) a *a中应该为 (a)乘(a);
  • ②SWAP(a, b, t) t = a; a = b; b = t也应该有大括号,否则SWAP只包含t=a这一个语句
  • ③SWAP的未定义的行为,将SWAP的表达式展开后,有两个z++与w++,而程序对于先执行那个的结果是未定义的,在c语言中编译器可以自行选择优先对函数中哪个参数求值,这样加快了编译器的效率,详见cpp(p102)
  • -

14. GNU/Linux命令

你知道以下命令的含义和用法吗:

  • ls
  • rm
  • whoami

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值