版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
高频c语言常见面试题及答案C语言中,`sizeof`和`strlen`的区别是什么?`sizeof`是运算符,用于计算数据类型或变量在内存中占用的字节数,编译时确定结果;`strlen`是标准库函数,用于计算字符串的实际长度(不包含末尾的空字符'\0'),运行时逐个字符遍历直到遇到'\0'。例如,`chararr[]="test";`中,`sizeof(arr)`结果为5(包含'\0'),`strlen(arr)`结果为4。若`charp="test";`,`sizeof(p)`在32位系统是4字节(指针大小),`strlen(p)`仍为4。`const`关键字有哪些常见用法?`const`用于修饰变量时,表示变量值不可修改(本质是只读,非真正常量),如`constinta=10;`。修饰指针时,`constintp`表示指针指向的内容不可变(常量指针),`intconstp`表示指针本身地址不可变(指针常量),`constintconstp`表示指针地址和指向内容均不可变。修饰函数参数时,如`voidfunc(constintp)`,防止函数内部修改指针指向的数据,提高代码安全性。修饰类成员函数时(C++特性),表示该函数不修改类的成员变量,但C语言无类概念,此场景仅适用于C++扩展。`static`关键字在C语言中的作用有哪些?在函数内部修饰变量时,变量存储在静态存储区,仅初始化一次,生命周期持续到程序结束,函数多次调用时变量值保留上次结果。例如:```cvoidfunc(){staticintcount=0;count++;printf("%d",count);}```每次调用`func()`都会输出递增的数值。在文件作用域修饰变量或函数时,变量/函数的作用域限制在当前文件内,其他文件无法通过`extern`声明访问,避免全局命名冲突。例如,`staticintglobal=10;`只能在当前文件使用,而普通全局变量可被其他文件访问。指针和数组的区别是什么?数组名是指向首元素的常量指针(地址不可修改),而指针是变量(可重新赋值)。例如,`intarr[5];arr++`会编译错误(数组名是常量),而`intp=arr;p++`合法。数组的大小在编译时确定(`sizeof(arr)`得到整个数组的大小),指针的大小是系统指针长度(32位4字节,64位8字节)。数组作为参数传递时会退化为指针,丢失大小信息,因此函数内部无法通过`sizeof`获取数组实际长度。野指针是如何产生的?如何避免?野指针指指向无效内存地址的指针,常见原因:指针未初始化(直接使用未赋值的指针)、指针指向的内存被释放后未置空(悬空指针)、指针越界访问(指向数组外的内存)。避免方法:指针声明时初始化为`NULL`;内存释放后将指针置为`NULL`;动态分配内存后检查是否分配成功(`malloc`可能返回`NULL`);使用指针前判断是否为`NULL`;避免返回局部变量的地址(局部变量生命周期结束后内存被回收)。`malloc`/`free`和`new`/`delete`的区别是什么?(注:`new`/`delete`是C++关键字,C语言不支持,但面试中常对比)`malloc`/`free`是C标准库函数,`new`/`delete`是C++运算符。`malloc`分配的是未初始化的内存(返回`void`需强制转换),`new`会调用构造函数初始化对象;`free`仅释放内存,`delete`会调用析构函数。`malloc`分配失败返回`NULL`,`new`默认抛出异常(可通过`nothrow`参数返回`NULL`)。C语言中只能使用`malloc`/`free`管理动态内存。结构体和联合体的区别是什么?结构体(`struct`)中各成员拥有独立的内存空间,总大小是各成员大小之和(需考虑内存对齐);联合体(`union`)所有成员共享同一块内存空间,总大小是最大成员的大小(同样需内存对齐)。例如:```cstructS{inta;charb;};//大小通常为8(int4+char1+3填充)unionU{inta;charb;};//大小为4(与int对齐)```结构体用于存储不同时使用的多个数据,联合体用于节省内存,同一时间只有一个成员有效。内存对齐的作用是什么?如何计算结构体大小?内存对齐是为了提高CPU访问效率(CPU通常按字长访问内存,非对齐数据需多次访问),同时满足某些硬件平台的限制(如ARM不允许访问未对齐的内存)。计算结构体大小需遵循:每个成员的起始地址是其类型大小的整数倍;结构体总大小是所有成员中最大对齐数的整数倍。例如:```cstructA{charc;//1字节,起始地址0inti;//4字节,需对齐到4的倍数,起始地址4(填充3字节)shorts;//2字节,起始地址8};//最大对齐数是4,总大小需是4的倍数,8+2=10→填充到12字节```可用`pragmapack(n)`设置最大对齐数(`n`为1、2、4等),此时成员对齐数取`min(自身大小,n)`。`define`和`const`的区别是什么?`define`是预处理器指令,在编译前替换,无类型检查;`const`是关键字,定义只读变量,有类型检查更安全。`define`宏可能产生多次求值(如`defineMAX(a,b)((a)>(b)?(a):(b))`,若参数含自增操作会导致副作用),`const`变量仅计算一次。`define`不分配内存(除非用于定义常量字符串),`const`变量存储在数据段(全局/静态)或栈(局部)。`define`可定义宏函数,`const`不能。函数指针的作用是什么?如何定义?函数指针指向函数的入口地址,可用于实现回调函数、函数表(如状态机)等。定义格式:`返回类型(指针名)(参数类型列表)`。例如,定义指向`intadd(inta,intb)`的函数指针:```cint(p)(int,int);p=add;//或p=&add(取地址符可选)intres=p(2,3);//调用方式与原函数一致```标准库函数`qsort`的第四个参数即为函数指针,用于指定排序规则。栈和堆的区别是什么?栈由编译器自动管理,存储局部变量、函数参数、返回地址等,空间较小(通常几MB),遵循先进后出(LIFO)原则,内存分配/释放由系统自动完成,效率高。堆由程序员手动管理(`malloc`/`free`),空间较大(受限于物理内存),分配方式灵活但需手动释放,易出现内存泄漏。栈的内存地址向下增长(向低地址扩展),堆向上增长(向高地址扩展)。`volatile`关键字的作用是什么?`volatile`表示变量可能被编译器未知的因素修改(如硬件寄存器、多线程共享变量),禁止编译器对该变量进行优化(如缓存到寄存器、重排指令)。例如,读取硬件状态寄存器时:```cvolatileintstatus=(volatileint)0x1234;intval=status;//编译器不会优化为读取一次,确保每次读取实际内存值```多线程中共享变量若被`volatile`修饰,可保证每次读取的是最新值(但不保证原子性,需结合互斥锁)。`voidmain()`和`intmain(intargc,charargv[])`的区别是什么?C语言标准规定`main`函数返回类型为`int`,`voidmain()`是非标准写法(仅部分编译器支持)。`intmain()`表示无命令行参数,`intmain(intargc,charargv[])`用于接收命令行参数:`argc`是参数个数(至少1,`argv[0]`是程序名),`argv`是指向参数的指针数组。程序结束时返回`int`值(0表示成功,非0表示错误),供操作系统或父进程获取执行结果。数组名和指针的联系与区别?数组名是指向首元素的常量指针(地址不可变),`&arr`表示数组的地址(类型为`int()[5]`,指向5元素数组的指针),`arr`和`&arr[0]`等价(类型为`int`)。指针可指向数组任意位置,且可修改指向(如`p=arr+2`指向第三个元素)。数组作为参数传递时退化为指针(`voidfunc(intarr[])`等价于`voidfunc(intarr)`),因此函数内部无法通过`sizeof(arr)`获取数组大小,需额外传递长度参数。内存泄漏的危害及检测方法?内存泄漏指动态分配的内存未释放,导致可用内存逐渐减少,最终可能引发程序崩溃或系统变慢。长期运行的程序(如服务器)泄漏积累会导致严重问题。检测方法:手动检查(代码中`malloc`后是否有对应的`free`,尤其在分支语句中);使用工具(如Linux的`valgrind`、Windows的`DebugCRT库`),`valgrind`可检测未释放的内存并定位分配位置;编写内存管理封装函数(记录分配/释放信息,程序结束时检查是否有未释放的内存)。`switch`语句中`case`后为何需要`break`?`switch`根据表达式值跳转到对应`case`标签,若没有`break`会继续执行后续`case`的代码(穿透现象)。例如:```cintx=2;switch(x){case1:printf("1");case2:printf("2");//x=2时执行此casecase3:printf("3");//无break会继续执行}```输出结果为`23`。`break`用于终止当前`case`的执行,跳出`switch`结构。`default`标签处理所有未匹配的情况,可选但建议保留以处理异常。`typedef`和`define`在类型重命名上的区别?`typedef`是编译器关键字,用于为类型定义新名称(有类型检查),`define`是预处理器指令,简单文本替换。例如:```ctypedefintpint;definePINTint````pinta,b;`定义两个`int`指针;`PINTa,b;`等价于`inta,b;`,其中`b`是`int`类型。`typedef`可用于结构体、指针等复杂类型,`define`可能因替换位置导致错误。`typedef`更安全,推荐用于类型别名。如何判断一段内存是栈分配还是堆分配?栈内存由系统自动管理,存储局部变量、函数参数等,生命周期随函数调用结束而结束;堆内存由`malloc`等函数分配,需手动释放,生命周期由程序员控制。可通过地址范围判断(通常堆地址高于栈地址,但不同系统可能不同);或检查指针是否由`malloc`返回(需记录分配信息)。例如,局部变量地址通常在函数调用时压栈,地址较低;堆地址在`malloc`时从堆区分配,地址较高。`memcpy`和`memmove`的区别是什么?`memcpy`和`memmove`均用于内存拷贝,原型为`voidmemcpy(voiddest,constvoidsrc,size_tn);`和`voidmemmove(voiddest,constvoidsrc,size_tn);`。`memcpy`假设源和目标内存无重叠,直接拷贝;`memmove`处理重叠情况(如`dest`在`src`之后且区间重叠),会先将源数据复制到临时缓冲区,再拷贝到目标,保证正确性。例如,`chararr[10]="abcdefgh";memmove(arr+2,arr,5);`会正确将`"abcde"`复制到`arr+2`(结果为`"ababcdeh"`),而`memcpy`可能因重叠导致数据覆盖错误。位域的作用是什么?如何定义?位域用于在结构体中按位分配内存,节省空间(尤其在嵌入式系统中处理寄存器位操作)。定义格式:`类型成员名:位数;`。例如:```cstructReg{unsignedintflag1:1;//1位unsignedintflag2:2;//2位unsignedintdata:29;//29位(总32位,与unsignedint对齐)};```位域成员类型需是`unsignedint`、`signedint`或`_Bool`(C99),位数不能超过类型的最大位数(如`unsignedint`通常32位)。位域不可取地址(`®.flag1`非法),跨平台时需注意位顺序(大端/小端)。逗号表达式的运算规则是什么?逗号表达式按从左到右顺序计算各表达式,结果为最后一个表达式的值。例如,`inta=(2+3,54,100);`中,先计算`2+3=5`(无赋值),再`54=20`(无赋值),最后`100`赋值给`a`,最终`a=100`。逗号表达式常用于for循环初始化/更新部分,如`for(i=0,j=10;i<j;i++,j--)`。如何实现一个函数交换两个整数的值?错误方式:```cvoidswap(inta,intb){//值传递,交换的是副本inttemp=a;a=b;b=temp;}```正确方式需传递指针(地址传递):```cvoidswap(inta,intb){inttemp=a;a=b;b=temp;}```调用时`swap(&x,&y)`,通过指针修改原变量的值。若使用C++引用,可`voidswap(int&a,int&b)`,但C语言不支持引用,必须用指针。`gets`函数的危害及替代方案?`gets`从标准输入读取字符串,不限制输入长度,可能导致缓冲区溢出(输入超过数组大小时覆盖后续内存),是不安全的函数(C11已移除)。替代方案:`fgets`(指定最大读取长度,`fgets(str,sizeof(str),stdin)`),会保留换行符(需手动处理);或`scanf("%[^\n]",str)`(读取到换行符停止,但仍需限制长度防止溢出)。如何判断机器是大端序还是小端序?大端序(网络字节序)高位字节存放在低地址,小端序低位字节存放在低地址。可通过联合体检测:```cintcheck_endian(){union{inti;charc;}u;u.i=1;return(u.c==1);//小端返回1,大端返回0}````int`类型4字节,若`u.c`(取低地址字节)为1,说明低位在低地址,是小端序。`strcpy`和`strncpy`的区别是什么?`strcpy`将源字符串(含'\0')复制到目标,不检查目标缓冲区大小,可能溢出;`strncpy`指定复制的最大字符数(`n`),若源长度小于`n`,目标后填充'\0'直到`n`个字符;若源长度大于等于`n`,目标字符串无'\0'(导致非合法C字符串)。例如:```cchardest[5];strcpy(dest,"hello");//溢出,未定义行为strncpy(dest,"hello",5);//dest内容为"hello"(无'\0'),strlen(dest)会越界```安全使用`strncpy`需手动添加'\0':`strncpy(dest,src,n-1);dest[n-1]='\0';`。函数参数压栈顺序是怎样的?C语言函数参数压栈顺序是从右到左(不同编译器可能不同,但常见为右到左)。例如,`func(a,b,c)`先压`c`,再`b`,最后`a`。这样设计是为了支持可变参数函数(如`printf`),通过最左边的参数(已知类型)可计算后续参数的位置。压栈顺序由调用约定决定(如`__cdecl`、`__stdcall`),默认通常为`__cdecl`(调用者清理栈)。如何防止头文件重复包含?使用头文件保护符(`ifndef`/`define`/`endif`):```cifndef_HEADER_H_define_HEADER_H_//头文件内容endif```或C99支持的`pragmaonce`(部分编译器支持),作用相同但更简洁。重复包含会导致结构体/函数重复声明(编译错误),保护符确保头文件只编译一次。`void`指针的特性是什么?`void`是通用指针类型,可指向任意类型的数据(无需强制转换),但不能直接解引用(需转换为具体类型)。例如:```cinta=10;voidp=&a;intq=(int)p;//需强制转换printf("%d",q);//正确````void`常用于内存分配函数(`malloc`返回`void`),可赋值给任意类型的指针变量。如何实现一个简单的内存池?内存池预先分配大块内存,按需分配小块,减少`malloc`/`free`调用次数(提高效率,减少内存碎片)。基本步骤:1.初始化时分配一块大内存(如`charpool=malloc(POOL_SIZE);`);2.维护当前可用位置指针(`charcurrent=pool;`);3.分配时检查剩余空间,若足够则从`current`处分配,`current+=size;`;4.释放时不立即回收(或标记为可用),程序结束时统一释放`pool`。适用于需要频繁分配/释放相同大小内存的场景(如链表节点)。`static`局部变量和全局变量的区别?`static`局部变量存储在静态存储区(与全局变量相同),但作用域仅限所在函数,其他函数不可访问;全局变量作用域是整个程序(其他文件可通过`extern`访问)。`static`局部变量仅初始化一次(编译时初始化),全局变量同理。两者生命周期均为程序运行期间。如何判断两个指针是否指向同一块内存?直接比较指针值(`p==q`)即可。若指针指向数组元素,`p`和`q`需指向同一数组且在数组范围内;若指向动态分配内存,需确保未被释放(否则比较无意义)。注意,不同内存块可能有相同地址(如不同函数的局部变量地址可能重叠),但运行时同一时刻两个有效指针指向同地址即表示同一块内存。`printf`如何实现可变参数?`printf`使用`<stdarg.h>`头文件中的宏(`va_list`、`va_start`、`va_arg`、`va_end`)处理可变参数。函数原型为`intprintf(constcharformat,...);`,`...`表示可变参数列表。实现步骤:1.用`va_list`声明参数指针;2.`va_start(ap,format)`初始化指针(指向第一个可变参数);3.`va_arg(ap,type)`按类型获取参数;4.`va_end(ap)`结束参数处理。例如,简化版`my_printf`:```cinclude<stdarg.h>voidmy_printf(constcharformat,...){va_listap;va_start(ap,format);//解析format,根据格式符调用va_arg获取参数va_end(ap);}```需注意参数类型与格式符匹配(如`%d`对应`int`,`%f`对应`double`),否则未定义行为。结构体指针访问成员的两种方式?结构体指针`p`访问成员`member`可用`(p).member`或`p->member`(箭头运算符更简洁)。例如:```cstructNode{intdata;structNodenext;};structNodep=malloc(sizeof(structNode));p->data=10;//等价于(p).data=10;p->next=NULL;```箭头运算符自动解引用指针并访问成员,避免括号冗余。`const`修饰的变量一定不能被修改吗?`const`修饰的变量是只读的,直接修改会编译错误(如`constinta=10;a=20;`),但可通过指针间接修改(未定义行为,依赖编译器实现)。例如:```cconstinta=10;intp=(int)&a;p=20;//可能成功(如GCC),但修改只读内存可能导致段错误```不建议此操作,`const`的目的是保证变量不被意外修改,间接修改违反设计意图。`sizeof`对函数名的处理?`sizeof(函数名)`在C语言中是未定义行为(C标准未规定),不同编译器处理不同。例如,`intfunc(){return0;}`,`sizeof(func)`在GCC中返回1(无实际意义),但应避免此类用法。`sizeof`用于变量或类型,函数名不是变量,不应计算其大小。如何实现一个不使用临时变量交换两个整数?算术法:`a=a+b;b=ab;a=ab;`(可能溢出);异或法:`a=a^b;b=a^b;a=a^b;`(利用异或自反性,`x^x=0`,`x^0=x`)。异或法更安全(无溢出问题),但两种方法均需注意:若`a`和`b`指向同一块内存(如`swap(&x,&x)`),异或法会导致结果为0(`a^a=0`),需额外判断指针是否相同。`main`函数执行前/后会执行哪些代码?C语言中,`main`函数执行前会初始化全局变量、静态变量(调用构造函数,C++特性)、执行`__attribute__((constructor))`(GCC扩展)修饰的函数;执行后会执行`atexit`注册的函数(`atexit(func)`)、析构全局对象(C++)、`__attribute__((destructor))`修饰的函数。例如:```cinclude<stdio.h>include<stdlib.h>voidpre_main()__attribute__((constructor));voidpre_main(){printf("Beforemain\n");}voidpost_main(){printf("Aftermain\n");}intmain(){atexit(post_main);printf("Inmain\n");return0;}```输出顺序:`Beforemain→Inmain→Aftermain`。如何检测程序中未初始化的变量?未初始化的局部变量存储在栈中,其值是随机的(垃圾值),使用会导致未定义行为。检测方法:开启编译器警告(如GCC的`-Wall`选项,会提示“variable‘x’isuseduninitialized”);使用静态代码分析工具(如`cppcheck`);调试时观察变量值(调试器中未初始化变量通常显示为特殊值)。全局变量和静态变量默认初始化为0(或空指针),无需担心未初始化。`charstr="hello";`和`charstr[]="hello";`的区别?前者`str`是指向字符串字面量的指针(存储在只读内存区,修改
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026江西南昌市劳动保障事务代理中心招聘劳务派遣人员备考题库及答案详解参考
- 2025北京国专知识产权有限责任公司招聘备考题库三及一套完整答案详解
- 2026江苏南京大学招聘备考题库XZ2025-428医学院专业、技术人员备考题库及参考答案详解1套
- 医院药品采购管理及库存控制方案
- 2026四川德阳市第六人民医院(东汽医院)面向社会招聘编外人员10人备考题库及一套完整答案详解
- 打造高效名师团队的管理与激励方案
- 电力系统安全运行与风险防范方案
- 劳动经济学高起专期末复习提纲
- 高校实验大体老师致敬方案
- 桥梁承台混凝土施工工艺方案
- 云南省2026年普通高中学业水平选择性考试调研测试历史试题(含答案详解)
- 广东省花都亚热带型岩溶地区地基处理与桩基础施工技术:难题破解与方案优化
- GB 4053.3-2025固定式金属梯及平台安全要求第3部分:工业防护栏杆及平台
- 2026中央广播电视总台招聘124人参考笔试题库及答案解析
- JG/T 3030-1995建筑装饰用不锈钢焊接管材
- 羽毛球二级裁判员试卷
- 通风与空调监理实施细则abc
- JJF 1614-2017抗生素效价测定仪校准规范
- GB/T 5237.3-2017铝合金建筑型材第3部分:电泳涂漆型材
- GB/T 3625-2007换热器及冷凝器用钛及钛合金管
- GA 1016-2012枪支(弹药)库室风险等级划分与安全防范要求
评论
0/150
提交评论