首页 > 其他分享 >2024年C语言最新经典面试题汇总(1-10)

2024年C语言最新经典面试题汇总(1-10)

时间:2024-03-23 19:00:42浏览次数:31  
标签:语句 10 面试题 函数 int C语言 数组 指针

C语言文章更新目录

C语言学习资源汇总,史上最全面总结,没有之一
C/C++学习资源(百度云盘链接)
计算机二级资料(过级专用)
C语言学习路线(从入门到实战)
编写C语言程序的7个步骤和编程机制
C语言基础-第一个C程序
C语言基础-简单程序分析
VS2019编写简单的C程序示例
简单示例,VS2019调试C语言程序
C语言基础-基本算法
C语言基础-数据类型
C语言中的输入输出函数
C语言流程控制语句
C语言数组——一维数组
C语言数组——二维数组
C语言数组——字符数组
C语言中常用的6个字符串处理函数
精心收集了60个C语言项目源码,分享给大家
C语言核心技术——函数
C代码是怎样跑起来的?
C语言实现字符串的加密和解密
C语言——文件的基本操作
使用C语言链表创建学生信息并且将信息打印输出
图解C语言冒泡排序算法,含代码分析
实例分析C语言中strlen和sizeof的区别
开发C语言的3款神器,VS2019、VScode和IntelliJ Clion
动图图解C语言选择排序算法,含代码分析
动图图解C语言插入排序算法,含代码分析
C语言指针数组和数组指针详解
5分钟搞懂C语言中的传值和传址
C语言——动态数组的创建和使用

C语言实例专栏(持续更新中…)

正文

在这里插入图片描述

问题1

C语言中的空指针是什么?为什么我们需要它?

参考答案

空指针是指不指向任何有效内存地址的指针,在C语言中用NULL来表示。NULL是一个预定义的宏,它的值通常为0或者((void *)0)

我们需要空指针的原因是:

空指针在C语言中具有重要作用。它可以用于初始化指针变量、防止野指针、判断指针有效性和动态内存分配等方面。

  • 初始化指针变量:在定义指针变量时,我们可以将其初始化为NULL,表示该指针变量当前不指向任何有效的内存地址。这样做可以避免指针未经初始化的问题,确保程序的可靠性。

  • 防止野指针:野指针是指指向未知或无效内存地址的指针。使用野指针可能导致程序崩溃或产生不可预料的行为。将指针初始化为NULL可以有效地避免野指针的问题,因为我们可以在使用指针之前检查其是否为NULL,从而避免对无效内存地址的访问。

  • 判断指针是否有效:在某些情况下,我们需要判断指针是否指向有效的内存地址。通过将指针与NULL进行比较,我们可以确定指针是否为空指针,从而判断指针是否有效。这在编写程序时非常有用,可以帮助我们进行错误处理和异常处理。

  • 动态内存分配:在C语言中,我们经常使用malloc()等函数动态分配内存。当内存分配失败时,malloc()函数会返回一个空指针,我们可以通过检查返回的指针是否为NULL来判断内存分配是否成功。

问题2

请解释C语言中的递归。你可以给出一个递归的例子吗?

参考答案

递归是指函数调用自身的过程。在C语言中,递归函数是一种非常有用的编程技巧,它可以将一个大问题分解成一个或多个相同类型的子问题,然后通过不断调用自身来解决这些子问题,最终得到问题的解。

递归函数通常包含两个部分:基本情况(base case)和递归调用(recursive call)。基本情况是递归函数中的停止条件,当满足基本情况时,递归函数将不再调用自身,递归过程结束。递归调用是指递归函数在执行过程中,通过调用自身来解决子问题。

下面是一个简单的递归函数的例子,用于计算一个正整数的阶乘:

#include <stdio.h>

int factorial(int n) {
  // 基本情况
  if (n == 0 || n == 1) {
    return 1;
  }
  // 递归调用
  else {
    return n * factorial(n - 1);
  }
}

int main() {
  int num = 5;
  int result = factorial(num);
  printf("The factorial of %d is %d\n", num, result);
  return 0;
}

运行结果:

在这个例子中,factorial函数通过调用自身来计算一个正整数的阶乘。当n等于0或1时,满足基本情况,递归结束,函数返回1。否则,函数通过调用自身来计算n-1的阶乘,并将结果与n相乘,最终得到n的阶乘。

需要注意的是,在使用递归时,必须确保递归调用最终会遇到基本情况,否则递归将进入无限循环,导致堆栈溢出。此外,递归在处理大规模问题时可能会导致性能问题,因为每次递归调用都需要保存当前的状态。

问题3

解释一下什么是C语言中的动态内存分配,以及如何使用malloc()free()函数。

参考答案

动态内存分配是在程序运行时分配内存的过程。在C语言中,我们通常使用malloc()calloc()realloc()函数来动态分配内存,而使用free()函数来释放已分配的内存。

malloc()函数是用来动态分配指定字节数的未初始化的内存空间。它的函数原型是:

void* malloc(size_t size);

其中,size参数表示要分配的字节数。malloc()函数返回一个指向被分配的内存空间的指针,如果分配失败,则返回NULL。

例如,下面的代码动态分配了一个大小为100的int类型数组:

int* ptr = (int*)malloc(100 * sizeof(int));

如果成功,ptr将指向一个大小为100的int类型数组。注意,我们需要在malloc()函数的返回值上进行强制类型转换,将其转换为适当的指针类型。

当我们不再需要动态分配的内存时,我们应该使用free()函数来释放它。free()函数的原型是:

void free(void* ptr);

其中,ptr参数是指向要释放的内存空间的指针。需要注意的是,我们不能对一个未通过malloc()等函数分配的内存空间调用free()函数。此外,我们应该避免产生“内存泄漏”,即分配了内存但未能及时释放。

例如,下面的代码释放了上面分配的内存:

free(ptr);

这样,ptr就不再指向有效的内存空间。注意,释放后的指针不能再次使用,除非再次通过`malloc()等函数进行分配。

问题4

C语言中的breakcontinue语句有什么不同?

参考答案

break语句和continue语句都是控制流语句,但它们的作用不同:

break语句用于终止循环(forwhiledo-while循环)或switch语句块的执行,并跳出当前的循环或switch语句。

continue语句用于提前结束当前循环迭代,跳过循环体余下的语句,直接开始下一轮循环。

具体来说:

当在forwhiledo-while循环内使用break语句时,会直接跳出当前循环。

当在switch语句块内使用break语句时,会跳出整个switch语句块。

当在forwhiledo-while循环内使用continue语句时,会跳过循环体余下的语句,直接开始下一轮循环。

举个例子:

for(int i = 0; i < 10; i++) {
  if(i == 5) {
  break; // 会直接跳出整个for循环
  }
  printf("%d", i);
}

for(int i = 0; i < 10; i++) {
  if(i == 5) {
  continue; // 会跳过printf,直接开始下一轮循环
  } 
  printf("%d", i);
}

所以总结来说,break语句用于终止循环或switch语句的执行,跳出整个循环或语句块;continue语句用于跳过当前循环迭代的余下语句,直接开始下一轮循环。它们在控制程序流程上有明显的区别。

问题5

请解释一下C语言中的指针数组和数组指针。它们有什么不同?

参考答案

当面试官问到C语言中的指针数组和数组指针时,可以从概念、示例和区别几个方面详细说明了它们的含义和区别。

指针数组和数组指针是C语言中涉及指针和数组的两个不同概念,虽然它们都涉及到数组和指针的结合使用,但在语法和语义上存在一些区别。

  1. 指针数组:
    指针数组是一个数组,其中的每个元素都是一个指针。这意味着每个元素可以指向一个不同的内存位置。这些指针可以指向不同类型的数据,如整数、字符、结构体等。通常,指针数组用于存储一组指针,每个指针可以指向一个独立的数据对象。
    示例:
int num1 = 10, num2 = 20, num3 = 30;
int *ptrArray[3]; // 声明一个指针数组,每个元素是指向int的指针
ptrArray[0] = &num1;
ptrArray[1] = &num2;
ptrArray[2] = &num3;
printf("%d\n", *ptrArray[0]); // 输出 10
  1. 数组指针:
    数组指针是一个指针,它指向一个数组。数组指针本身并不存储数据,而是指向一个数组的首元素。数组指针可以通过指针算术运算遍历数组的元素。数组指针通常用于在函数中传递数组,或者用于动态分配多维数组。
    示例:
int arr[3] = {10, 20, 30};
int (*ptrToArr)[3]; // 声明一个指向包含3个int元素的数组的指针
ptrToArr = &arr;
printf("%d\n", (*ptrToArr)[0]); // 输出 10

区别:

  • 主要区别在于数组指针本身是一个指针,而指针数组本身是一个数组。指针数组的元素是指针,数组指针指向数组的首元素。
  • 数组指针可以通过指针算术运算遍历数组的元素,而指针数组的元素是指针,不能通过指针算术运算直接访问数组元素。
  • 数组指针在函数参数传递中常用于传递数组,指针数组用于存储多个指针,每个指针可以指向不同的数据。

总结来说,指针数组和数组指针是C语言中两个涉及指针和数组的不同概念。指针数组是一个数组,其中的每个元素是指针;数组指针是一个指针,指向一个数组的首元素。

问题6

什么是C语言中的位运算符?请解释一下&、|和^运算符。

参考答案

当面试官问到C语言中的位运算符时,可以这样回答:
位运算符是用于在二进制位级别上进行操作的运算符,它们直接操作变量的各个位,而不考虑它们的整体值。C语言中的常见位运算符包括按位与(&)、按位或(|)和按位异或(^)。

  1. 按位与(&)运算符:
    按位与运算符将两个操作数的对应位进行逻辑与操作。如果两个对应位都为1,则结果位为1,否则为0。
    示例:
unsigned int num1 = 12; // 二进制表示为 1100
unsigned int num2 = 9;  // 二进制表示为 1001
unsigned int result = num1 & num2; // 结果为 1000 (8的二进制)
  1. 按位或(|)运算符:
    按位或运算符将两个操作数的对应位进行逻辑或操作。如果两个对应位中至少有一个为1,则结果位为1,否则为0。
    示例:
unsigned int num1 = 12; // 二进制表示为 1100
unsigned int num2 = 9;  // 二进制表示为 1001
unsigned int result = num1 | num2; // 结果为 1101 (13的二进制)
  1. 按位异或(^)运算符:
    按位异或运算符将两个操作数的对应位进行逻辑异或操作。如果两个对应位不相同,则结果位为1,否则为0。
    示例:
unsigned int num1 = 12; // 二进制表示为 1100
unsigned int num2 = 9;  // 二进制表示为 1001
unsigned int result = num1 ^ num2; // 结果为 0101 (5的二进制)

这些位运算符在某些情况下可以用于位级操作,例如在嵌入式系统中处理寄存器、位掩码、权限控制等。需要注意的是,位运算符只能用于整数类型的操作数。

总结来说,位运算符(&、| 和 ^)是C语言中用于操作变量二进制位的运算符,按照位对应进行逻辑操作。

问题7

解释一下C语言中的switch语句是如何工作的?它有哪些限制?

参考答案

当面试官问到C语言中的switch语句时,可以这样回答:
switch语句是一种用于根据表达式的值选择不同执行路径的控制流语句。它可以使代码更加简洁和可读,并且可以根据不同的条件执行不同的代码块。
switch语句的工作原理如下:

  1. 执行表达式:首先,计算switch语句后面的表达式的值。
  2. 匹配case:将表达式的值与每个case标签进行比较,如果匹配成功,则执行与该case标签关联的代码块。如果没有匹配到任何case标签,将执行default标签下的代码块(如果有的话)。
  3. 执行代码块:一旦找到匹配的case标签,将执行与该标签关联的代码块。在执行代码块后,程序将继续执行switch语句后面的代码,除非遇到break语句或者switch语句结束。

语法结构:

switch (expression) {
  case constant1:
    // code to be executed if expression equals constant1;
    break;
  case constant2:
    // code to be executed if expression equals constant2;
    break;
  ...
  default:
    // code to be executed if expression doesn't match any constants;
}

示例:

int day = 3;
switch(day) {
  case 1:
    printf("Monday\n");
    break;
  case 2:
    printf("Tuesday\n");
    break;
  case 3:
    printf("Wednesday\n");
    break;
  default:
    printf("Other day\n");
    break;
}

在上面的示例中,当day的值为3时,将匹配到case 3,然后执行与之关联的代码块,输出"Wednesday"。

switch语句的一些限制包括:

  1. switch语句的expression必须是一个整型或枚举类型。:switch语句的表达式必须是整数类型(如int、char等)或者是枚举类型,不能是浮点数、字符串或其他类型。
  2. case标签必须是常量表达式:case标签必须是常量表达式,不能是变量或运算结果。这是因为switch语句使用跳转表(jump table)来实现快速查找,需要在编译时确定case标签的值。
  3. 每个case内部需要显式地使用break语句:在每个case代码块的末尾需要使用break语句,以防止代码继续执行下一个case代码块。如果没有break语句,程序将会继续执行下一个case代码块,这可能导致意外的结果。
  4. default标签是可选的:default标签是可选的,用于处理没有匹配到任何case标签的情况。如果没有default标签,程序将继续执行switch语句后面的代码。

5.每个case标签必须是唯一的,不能有重复的case常量。

问题8

请解释一下C语言中的函数指针,并且给出一个例子进行说明?

参考答案

当面试官问到C语言中的函数指针时,可以这样回答:
函数指针是指向函数的指针变量。它可以用于在程序中传递函数作为参数,或者将函数作为返回值。函数指针提供了一种灵活的方式来调用不同的函数,以适应不同的需求和场景。
函数指针的定义格式如下:

返回类型 (*指针变量名)(参数列表)

其中,指针变量名是用于存储函数地址的变量名,返回类型是函数返回值的类型,参数列表是函数的参数类型和个数。
示例:

int add(int a, int b) {
  return a + b;
}
int subtract(int a, int b) {
  return a - b;
}
int main() {
  int (*funcPtr)(int, int); // 声明一个函数指针变量
  funcPtr = add; // 函数指针指向add函数
  int result = funcPtr(2, 3); // 调用add函数,返回结果为5
  funcPtr = subtract; // 函数指针指向subtract函数
  result = funcPtr(5, 2); // 调用subtract函数,返回结果为3
}

在上面的示例中,声明了一个函数指针变量funcPtr,它可以指向返回类型为int、参数类型为int和int的函数。首先,将funcPtr指向add函数,然后通过funcPtr调用add函数并返回结果。接着,将funcPtr指向subtract函数,再通过funcPtr调用subtract函数并返回结果。
函数指针的应用场景包括:

  • 回调函数:将函数指针作为参数传递给其他函数,以便在适当的时候调用该函数。
  • 函数指针数组:使用函数指针数组可以根据不同的索引值调用不同的函数。
  • 函数指针作为返回值:函数可以返回一个指向另一个函数的指针。
    需要注意的是,函数指针的类型必须与指向的函数具有相同的返回类型和参数列表,否则会导致不可预测的行为。

总结来说,函数指针是指向函数的指针变量,它提供了一种灵活的方式来调用不同的函数。

问题9

请解释一下C语言中的文件I/O操作,以及如何使用fopen()、fprintf()和fclose()函数。

参考答案

在面试中,当被问到C语言中的文件I/O操作,以及如何使用fopen(), fprintf(), 和 fclose()函数,可以从以下几个方面进行回答:

文件I/O操作

文件I/O(输入/输出)是计算机程序与磁盘文件进行数据交换的一种方式。C语言提供了一系列函数来执行文件I/O操作,例如读取文件、写入文件、打开文件和关闭文件等。

fopen()函数

fopen()函数用于打开一个文件。这个函数的原型如下:

FILE* fopen(const char* path, const char* mode);

path参数是要打开的文件的路径,mode参数指定了文件被打开的方式,如只读(“r”)、写入(“w”)、添加(“a”)等。这个函数成功时返回一个FILE指针,失败时返回NULL

fprintf()函数

fprintf()函数用于将格式化的数据写入文件。这个函数的原型如下:

int fprintf(FILE* stream, const char* format, ...);

stream参数是一个FILE指针,指向要写入的文件。format参数是一个格式化字符串,它可以包含一些格式说明符,例如%d(表示整数)、%s(表示字符串)等。这个函数返回写入的字符数,失败时返回一个负数。

fclose()函数

fclose()函数用于关闭一个打开的文件。这个函数的原型如下:

int fclose(FILE* stream);

stream参数是一个FILE指针,指向要关闭的文件。这个函数成功时返回0,失败时返回EOF

示例

以下是一个简单的示例,演示如何使用这些函数来写入一个文件:

#include <stdio.h>
int main() {
    FILE* file = fopen("test.txt", "w");
    if (file == NULL) {
        printf("Failed to open file\n");
        return 1;
    }
    fprintf(file, "Hello, %s\n", "world");
    if (fclose(file) != 0) {
        printf("Failed to close file\n");
        return 1;
    }
    return 0;
}

在这个示例中,我们首先使用fopen函数打开一个名为test.txt的文件以写入数据。然后我们使用fprintf函数将一条消息写入文件。最后,我们使用fclose函数关闭文件。
以上就是我对C语言中的文件I/O操作,以及如何使用fopen(), fprintf(), 和 fclose()函数的解答。

问题10

C语言中的预处理器是什么?

参考答案

当面试官问到C语言中的预处理器时,可以这样回答:

预处理器是C语言编译过程中的一个重要组成部分,它负责在实际的编译之前对源代码进行一系列的预处理操作。预处理器指令以#开头,用于在编译之前对源代码进行宏替换、条件编译和文件包含等操作。

预处理器的主要作用有以下几个方面:

  1. 宏替换:
    预处理器可以使用#define指令定义宏,宏是一种简单的文本替换机制。预处理器会在编译之前将所有的宏进行替换,将宏名称替换为宏定义的文本。这样可以提高代码的复用性和可读性。

示例:

#define MAX(a, b) ((a) > (b) ? (a) : (b))
int maxNumber = MAX(10, 20); // maxNumber的值为20

在上面的示例中,MAX是一个宏,它接受两个参数并返回较大的那个数。在使用MAX宏时,预处理器会将MAX(10, 20)替换为((10) > (20) ? (10) : (20)),最终得到maxNumber的值为20。

  1. 条件编译:
    预处理器可以使用条件编译指令(如#if、#ifdef、#ifndef、#elif、#else和#endif)来根据条件选择性地编译代码块。条件编译可以根据宏的定义与否,或者特定条件的真假来控制代码的编译。
    示例:
#define DEBUG // 定义DEBUG宏
#ifdef DEBUG
  printf("Debug mode\n");
#else
  printf("Release mode\n");
#endif

在上面的示例中,根据DEBUG宏的定义与否,预处理器将选择性地编译不同的代码块。如果DEBUG宏被定义,将输出"Debug mode";否则,将输出"Release mode"。

  1. 文件包含:
    预处理器可以使用#include指令将其他文件的内容包含到当前文件中。这样可以将代码模块化,并且可以重复使用一些常用的代码。

示例:

#include <stdio.h> // 包含stdio.h头文件
int main() {
  printf("Hello, world!\n");
  return 0;
}

在上面的示例中,通过#include指令将stdio.h头文件包含到当前文件中,以便使用其中定义的printf函数。

预处理器在编译过程中会对源代码进行预处理操作,并生成一个经过宏替换、条件编译和文件包含等处理的中间代码,然后将该中间代码交给编译器进一步处理。

总结来说,预处理器是C语言编译过程中的一个重要组成部分,它负责对源代码进行宏替换、条件编译和文件包含等预处理操作

如果您觉得本篇文章对您有帮助,请点赞,转发给更多的人。

标签:语句,10,面试题,函数,int,C语言,数组,指针
From: https://blog.csdn.net/csdn_wangchong/article/details/136971781

相关文章

  • 中国电子学会(CEIT)2021年03月真题C语言软件编程等级考试三级(含详细解析答案)
    中国电子学会(CEIT)考评中心历届真题(含解析答案)C语言软件编程等级考试三级2021年03月编程题五道 总分:100分一、找和为K的两个元素(20分)在一个长度为n(n<1000)的整数序列中,判断是否存在某两个元素之和为k。时间限制:1000ms内存限制:65536kb输入第一行输入......
  • 水仙花数(C语言)
    文章目录水仙花数的起源思路运行代码水仙花数的起源水仙花数的名称来源于希腊神话中的美少年纳西索斯(Narcissus),其名字“Narcissus”与水仙花数的英文名称“Narcissisticnumber”的词根一致。水仙花数是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。......
  • C语言进阶——动态内存管理
    目录一、C语言底层内存知识补充二、动态内存函数1.1free1.2malloc1.3calloc1.4realloc三、使用常见错误3.1对非动态开辟内存使用free释放3.2空指针未判断造成的错误3.3使用free释放一块动态开辟内存的一部分3.4对同一块动态内存多次释放3.5动态开辟内存没有释放而......
  • C语言——函数练习程序
    1.从终端接收一个数,封装一个函数判断该数是否为素数#include<stdio.h>intpri(intnum){inti=0;for(i=2;i<num;i++){if(num%i==0){return0;break;}}if(i==num-1)......
  • 【C语言】整数和浮点数在内存中的存储
    点这里是个人主页~这次的内容是比较底层的奥,对于理解编程很重要~整数浮点数在内存中的存储一、整数在内存中的存储二、大小端字节序和字节序判断大小端的概念一道简单关于大小端排序的百度面试题三、简单理解数据类型存储范围例一例二例三例四例五例六四、浮点......
  • C语言的算符优先级
    C语言中提供许多算符,比如算术运算、逻辑运算、关系运算等,必须规定它们的优先级,否则将它们放到一起运算肯定要出乱子,正如算术中有先乘除后加减的规则,C语言同样要有确定的运算规则。C语言定义了15个算符优先级,其优先级规则如下:规则1:优先级高的先运算规则2:同一个优先级则需要按照结......
  • 力扣HOT100 - 49. 字母异位词分组
    解题思路:排序注意:返回时不能用List,因为List是抽象类,return的必须是List的具体实现,如ArrayListclassSolution{publicList<List<String>>groupAnagrams(String[]strs){Map<String,List<String>>map=newHashMap<>();for(Stringstr......
  • C语言 03 原码 反码 补码
    原码计算机中所有的数字都是使用0和1这样的二进制数来进行表示的。这时如果要存储一个数据,比如十进制的3,那么就需要使用2个二进制位来保存,二进制格式为11,占用两个位置,称为2bit位。一般占用8个bit位表示一个字节(B),2个字节等于1个字,所以一个字表示16个bit位......
  • C语言字符函数和字符串函数及内存函数详解(干货小知识:常用函数的模拟实现)
    文章目录1.字符函数1.1字符分类函数1.2字符转换函数2.字符串函数2.1strlen函数2.1.1strlen函数的使用:2.1.2strlen函数的模拟实现2.2strcpy函数2.2.1strcpy函数的使用2.2.2strcpy函数的模拟实现2.3strcat函数2.3.1strcat函数的使用2.3.2strcat函数的模拟实......
  • PAT乙级 1062 最简分数 C语言
    最简分数一个分数一般写成两个整数相除的形式:N/M,其中M不为0。最简分数是指分子和分母没有公约数的分数表示形式。现给定两个不相等的正分数N1​/M1​和N2​/M2​,要求你按从小到大的顺序列出它们之间分母为K的最简分数。输入格式:输入在一行中按N/M的格式给出两个......