C语言面试题总结(含参考答案)------持续更新

1、关键字static的作用是什么?

  1. 在函数内部使用static修饰局部变量时表示该变量在程序的整个生命周期内只会被初始化一次,并且在函数调用结束后不会被销毁,其值会一直保持。这种特性使得静态局部变量成为一种很有用的工具,可以在多次函数调用之间保持其值。

  2. 在全局变量前使用static关键字修饰,表示该全局变量的作用域被限制在当前文件内,其他文件无法访问该变量。通过这种方式可以实现全局变量的封装,避免被其他文件不小心修改。

  3. 函数前使用static修饰时表示该函数的作用域也被限制在当前文件内,其他文件无法调用该函数。这种方式可以实现函数的封装和隐藏,只允许当前文件内部调用。

2、.h头文件中的ifndef/define/endif 的作用?

  用于防止头文件被重复包含,如果已经定义了该标识符,就不会再次包含头文件,从而避免重复   定义和编译错误。这样可以确保头文件只被包含一次,提高编译效率并避免潜在的错误。

3、全局变量和局部变量在内存中是否有区别?如果有,是什么区别?

全局变量存储在静态数据区,而局部变量存储在栈区。

全局变量在程序运行期间始终存在,其内存空间在程序启动时分配,在程序结束时释放。局部变量则在函数被调用时创建,在函数执行结束时销毁,其内存空间随着函数的执行而动态分配与释放。

4、堆栈溢出一般是由什么原因导致的?

堆栈溢出通常是由递归调用或者过多的嵌套函数调用导致的。当一个函数被调用时,其参数和局部变量会被压入堆栈中,当函数执行完毕后,这些数据会被弹出堆栈。如果递归调用或者函数调用过多导致堆栈空间不足,就会发生堆栈溢出。另外,如果函数内部使用了大量的局部变量或者数组,也有可能导致堆栈溢出。

5、不能做switch()的参数类型?

switch()的参数类型不能是浮点型、双精度型、字符串型或者对象型。只能是整型或字符型。

6、局部变量能否和全局变量重名?

局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。

7、语句for( ;1 ;)有什么问题?它是什么意思?

和while(1)相同,无限循环。

8、do……while和while……do有什么区别?

前一个循环一遍再判断,后一个判断以后再循环。

9、程序的内存分配?

一个 C、C++程序编译时内存分为 5 大存储区:堆区、栈区、全局区、文字常量区、程序代码区。

1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。
5、程序代码区—存放函数体的二进制代码

10、堆和栈的区别?

1、分配内存的方式:

堆是由程序员分配和释放的,通过内存管理函数(如malloc、free)来操作堆内存。堆内存的生命周期由程序员控制,需要手动释放,否则可能导致内存泄漏。

栈是由编译器自动分配和释放的,编译器根据变量的作用域来管理栈内存。当一个函数被调用时,其局部变量存储在栈上,函数执行完成后,这些变量会自动释放。

2、存储方式:

堆是用于存储动态分配的内存,通常用来存储程序中需要长时间保存的大型数据结构,如数组、对象等。堆内存的访问速度较慢,因为需要通过指针来访问。

栈是用于存储局部变量和函数调用时的参数,栈内存的访问速度较快,因为数据的存取都在固定的位置进行。

3、内存管理:

堆内存需要手动分配和释放,程序员需要注意内存泄漏和内存溢出等问题。

栈内存由编译器自动管理,不需要程序员手动介入,因此更安全和方便。

11、C语言关键字

12、关键字const的作用?

Const作用:定义常量、修饰函数参数、修饰函数返回值三个作用。被Const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。

const int *p:  const修饰指向常量整数,指针指向的值不能被修改,但是指针可以指向其它的整数

int const *p: 修饰指针指向的内容,指向的值不能改变,指针可以指向其他的整数。

int * const p: 修饰指针p,p不能改变,指向的整数的值可以改变。

13、const与#define 相比,有何优点?

1、 const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
2、有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。

14、typedef和define有什么区别?
1、用法不同:typedef 用来定义一种数据类型的别名,增强程序的可读性。define 主要用来定义常量,以及书写复杂使用频繁的宏。
2、执行时间不同:typedef 是编译过程的一部分,有类型检查的功能。define 是宏定义,是预编译的部分,其发生在编译之前,只是简单的进行字符串的替换,不进行类型的检查。
3、作用域不同:typedef 有作用域限定。define 不受作用域约束,只要是在 define 声明后的引用都是正确的。

14、extern有什么作用?

extern 标识的变量或者函数声明其定义在别的文件中,提示编译器遇到此变量和函数时在其它模块中寻找其定义。

15、数组与指针的区别?

  1. 内存分配:数组在内存中是一块连续的空间,其大小在编译时确定,因此数组的大小是固定的。而指针只是一个地址,它指向的数据可以是连续的,也可以是不连续的。

  2. 数据类型:数组的元素类型是固定的,而指针可以指向不同类型的数据

  3. 表示形式:数组是一个特殊的数据类型,可以直接使用下标来访问元素。而指针是一个变量,存储的是地址,需要通过解引用操作*才能访问指向的数据

  4. 传递方式:当数组作为函数参数传递时,实际上传递的是数组的首地址,即指针。因此在函数内部对数组的操作将改变原始数组的值。

16、c语言库函数中将一个字符转换成整型的函数?

用 法: int atoi(const char *str);

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    char str[] = "1234";
    int num = atoi(str);

    printf("str:%s nun: %d\n", str,num);

    return 0;
}

17、结构体和共用体的区别?

  1. 内存分配

    • 结构体中的数据成员占用独立的内存空间结构体的大小等于所有成员占用内存空间之和。
    • 共用体中的所有成员共享同一块内存空间共用体的大小等于所有成员中占用内存空间最大的那个。
  2. 成员的访问:

    • 对结构体成员的修改不会影响其他成员的值,每个成员都有独立的内存空间。
    • 对共用体的赋值会影响其他成员的值,由于共用体的所有成员共享同一块内存,修改一个成员会影响其他成员的值。
  3. 用途:

    • 结构体通常用于将多个不同类型的数据聚合在一起,以便组织相关的数据信息
    • 共用体一般用于节省内存空间,当几个成员中只有一个会被使用时,可以使用共用体来节省内存。

18、变量的声明和定义有什么区别?

变量的声明是指在程序中告诉编译器有一个变量存在,并且指定该变量的类型,但并没有为该变量分配内存空间。而变量的定义是指在程序中为变量分配了内存空间,同时也进行了初始化。

19、sizeof和strlen的区别?

  1. sizeof:sizeof 是一个操作符,而不是一个函数。它用来获取一个数据类型或变量的大小,单位是字节。在使用时,sizeof 后面可以跟数据类型或变量名,用于获取它们所占用的内存空间大小。例如,sizeof(int) 会返回一个 int 类型的变量占用的内存空间大小,通常是 4 个字节。

  2. strlen:strlen 是一个函数用来获取字符串的长度,即字符串中字符的个数,不包括末尾的空字符 '\0'。在使用时,需要传入一个以空字符结尾的字符串作为参数,函数会返回这个字符串中字符的实际个数。例如,strlen("hello") 会返回 5,因为字符串 "hello" 中包含了五个字符。

20、strcpy、sprintf与memcpy的区别?

strcpy:是C语言中的字符串复制函数,用于将一个字符串复制到另一个字符串中。

使用strcpy时,必须确保目标字符串有足够的空间来存放源字符串的内容。如果源字符串超出目标字符串的长度,会导致内存溢出。

strcpy是以'\0'字符作为终止符,因此复制的内容会自动添加'\0'。

#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, World!";
    char dest[20]; // 目标字符串需要足够大

    // 使用 strcpy 函数复制字符串
    strcpy(dest, src);

    // 输出复制后的字符串
    printf("源字符串: %s\n", src);
    printf("目标字符串: %s\n", dest);

    return 0;
}

运行结果: 

 

sprintf:也是C语言中的字符串复制函数,功能类似于strcpy,但是可以将不同类型的数据格式化为字符串。

sprintf通常用于将整数、浮点数等转换为字符串,并将结果存储到目标字符串中。

和strcpy一样,使用sprintf时也要确保目标字符串有足够的空间。否则可能会导致内存溢出。

#include <stdio.h>

int main() {
    char str[100];
    int num = 10;
    float fnum = 3.14;

    // 使用 sprintf 将格式化的数据写入字符串
    sprintf(str, "The number is %d and the float number is %.2f", num, fnum);

    // 输出写入的字符串
    printf("%s\n", str);

    return 0;
}

运行结果:  

 

memcpy:是C语言中的内存复制函数,用于将一个内存块的内容复制到另一个内存块中。

memcpy可以复制任意数据类型的内存块,而不仅仅是字符串。

使用memcpy时,需要指定要复制的源内存地址、目标内存地址以及要复制的字节数。

memcpy不会自动添加'\0'字符,因此在复制字符串时,需要手动添加终止符。

#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, World!";
    char dest[20]; // 目标字符串需要足够大

    // 使用 memcpy 函数复制字符串
    memcpy(dest, src, strlen(src) + 1); // 需要复制的字节数为字符串长度加上结尾的空字符

    // 输出复制后的字符串
    printf("源字符串: %s\n", src);
    printf("目标字符串: %s\n", dest);

    return 0;
}

运行结果:

  • 36
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值