版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
高频c语言面试题及答案C语言中sizeof和strlen的区别是什么?sizeof是编译时运算符,用于计算数据类型或变量在内存中占用的字节数。对于数组,sizeof返回整个数组的字节大小;对于指针,返回指针本身的字节大小(与平台相关,32位4字节,64位8字节)。strlen是标准库函数(<string.h>),用于计算C字符串的实际长度(不包含结束符'\0')。其本质是遍历字符直到遇到'\0',因此要求参数必须是合法的以'\0'结尾的字符串,否则会导致越界访问。例如:chararr[]="test";sizeof(arr)结果为5(包含'\0'),strlen(arr)结果为4;若定义charptr=arr;sizeof(ptr)在64位系统为8,strlen(ptr)仍为4。常量指针和指针常量有何区别?常量指针的定义形式为constcharptr(或charconstptr),表示指针指向的内容不可修改,但指针本身可以重新指向其他地址。例如:constcharp="hello";p='H'(错误,内容不可改),p="world"(正确,指针可改)。指针常量的定义形式为charconstptr,表示指针本身的地址不可修改,但指向的内容可以修改。例如:charstr[]="test";charconstp=str;p=&str[1](错误,指针不可改),p='T'(正确,内容可改)。若两者结合(constcharconstptr),则指针地址和指向内容均不可修改。结构体成员对齐的规则是什么?结构体对齐遵循编译器默认的对齐系数(可通过pragmapack(n)修改)和成员自身大小的最小值作为对齐单位。具体规则:第一个成员偏移量为0;后续成员的偏移量必须是其自身大小与对齐系数中较小值的整数倍;结构体总大小需是所有成员对齐单位最大值的整数倍。例如:structA{chara;//1字节,偏移0intb;//4字节,需对齐到4的倍数,偏移4(填充3字节)shortc;//2字节,对齐到2,偏移8(4+4=8)};//总大小需是最大对齐单位(4)的倍数,8+2=10,填充到12字节若使用pragmapack(2),则对齐系数为2。此时int的对齐单位为min(4,2)=2,char偏移0,int偏移2(填充1字节),short偏移6(2+4=6),总大小8(6+2=8,是2的倍数)。对齐的目的是提高CPU访问效率,减少跨内存块读取的情况。static关键字在C语言中的作用有哪些?在函数内部,static修饰的局部变量会存储在静态存储区,仅初始化一次,生命周期持续到程序结束,下次调用函数时保留上次的值。例如:voidfunc(){staticintcount=0;count++;printf("%d",count);}//多次调用会输出123...在函数外部(全局作用域),static修饰的全局变量或函数仅在当前源文件可见,其他文件无法通过extern声明访问。这用于限制变量/函数的作用域,避免不同文件间的命名冲突。例如:staticintglobal=10;仅当前文件可访问。内存泄漏的常见场景及检测方法?内存泄漏指动态分配的内存未释放且无法再访问(指针丢失)。常见场景:malloc/calloc后未调用free释放;函数返回堆内存指针但未被正确释放;重复调用realloc时未保存旧指针导致丢失;异常分支(如提前return)未释放已分配内存。检测方法:1.工具检测:如Valgrind(Linux)的memcheck工具,可跟踪内存分配和释放,报告泄漏位置;2.手动排查:在关键位置打印内存分配/释放日志,统计分配次数与释放次数是否匹配;3.封装内存函数:自定义malloc和free,记录分配信息(文件名、行号),程序结束时检查未释放的内存。指针运算的规则有哪些?指针运算基于所指向的数据类型的大小。例如,intp指向地址0x1000,p+1的结果是0x1004(int占4字节);charq指向0x1000,q+1是0x1001(char占1字节)。指针相减仅当指向同一数组元素时才有意义,结果为元素个数差(如p2-p1得到两指针间的元素数量)。指针与整数相加/减时,结果需仍指向同一数组或数组尾后一个位置,否则为未定义行为。函数指针的作用及使用场景?函数指针是指向函数的指针变量,定义形式为:返回值类型(指针名)(参数类型列表)。例如:int(func_ptr)(int,int);可指向如intadd(inta,intb){returna+b;}的函数。使用场景包括:1.回调函数:将函数指针作为参数传递,由外部函数调用(如qsort的比较函数参数);2.函数跳转表:根据条件动态选择调用的函数(如状态机处理不同事件);3.实现多态:在不修改接口的情况下替换具体实现(类似面向对象的虚函数)。宏定义的常见陷阱及注意事项?宏定义在预处理阶段展开,需注意括号和副作用问题。陷阱1:未加括号导致运算优先级错误。例如:defineSQUARE(x)xx,当调用SQUARE(2+3)时展开为2+32+3=11,正确写法应为defineSQUARE(x)((x)(x))。陷阱2:参数包含自增/自减操作产生副作用。例如:defineMAX(a,b)((a)>(b)?(a):(b)),若调用MAX(i++,j++),会导致i和j被递增两次(条件判断和返回值各一次)。陷阱3:宏定义结尾加分号可能导致语句错误。例如:defineDEBUGprintf("debug\n");若在if语句中使用if(cond)DEBUGelse...,会展开为if(cond)printf("debug\n");;else...,导致语法错误。注意事项:尽量为参数和整体表达式加括号;避免使用包含副作用的参数;复杂逻辑优先使用内联函数而非宏。C程序的内存分区有哪些?各存储什么内容?C程序内存通常分为:1.代码区(TextSegment):存储编译后的机器指令,只读,多进程共享;2.数据区(DataSegment):已初始化全局变量和静态变量(.data);未初始化全局变量和静态变量(.bss),程序启动时自动初始化为0;3.堆(Heap):动态分配的内存(malloc/calloc/realloc),需手动管理,由低地址向高地址增长;4.栈(Stack):存储局部变量、函数参数、返回地址等,由编译器自动管理,由高地址向低地址增长。例如:全局变量intg1=10(.data);staticints1;(.bss);main函数中的inta=20(栈);charp=malloc(10)(堆,p本身在栈)。如何判断一个整数是大端序还是小端序?大端序(Big-Endian)指高位字节存储在低地址,低位字节在高地址;小端序(Little-Endian)相反。检测方法:1.利用联合体(Union)的特性(所有成员共享同一块内存):unionCheck{inti;charc;};unionChecku;u.i=1;if(u.c==1)//低地址存低位字节printf("Little-Endian");elseprintf("Big-Endian");2.指针强制转换:将int的地址转换为char,取第一个字节判断。例如:intnum=1;charptr=(char)#if(ptr==1)小端序,否则大端序。野指针的产生原因及避免方法?野指针指指向无效内存地址的指针,产生原因:1.指针未初始化:定义指针后未赋值(指向随机地址);2.指针指向的内存已释放:free后未将指针置NULL,成为“悬空指针”;3.指针越界访问:指向数组外的内存(如数组大小为5,访问索引5的元素)。避免方法:指针声明时初始化为NULL(charp=NULL;);free后立即将指针置NULL(free(p);p=NULL;);避免返回局部变量的指针(局部变量存储在栈中,函数返回后内存被回收);访问指针前检查是否为NULL(if(p!=NULL)p=10;)。static和const的区别是什么?static用于控制存储周期和作用域:局部变量变为静态存储(生命周期延长),全局变量/函数限制为文件内可见。const用于修饰变量,表示其值不可被直接修改(编译器层面的限制),但无法保证绝对不变(可通过指针强制转换修改)。例如:constinta=10;a=20(错误),但intp=(int)&a;p=20(可能成功,取决于编译器优化)。static变量存储在数据区,const变量若为全局/静态则存储在数据区(只读段),局部const变量存储在栈中。如何实现字符串的反转?要求原地反转,不使用额外空间。例如将"hello"变为"olleh"。实现思路:双指针法,用两个指针分别指向字符串首尾,交换字符后向中间移动,直到相遇。代码示例:voidreverse_string(charstr){if(str==NULL)return;charleft=str;charright=str+strlen(str)1;while(left<right){chartemp=left;left=right;right=temp;left++;right--;}}注意处理空指针和空字符串(strlen为0)的情况,避免越界访问。动态内存分配函数malloc、calloc、realloc的区别?malloc分配指定大小的内存块,不初始化内容(值为随机),原型:voidmalloc(size_tsize)。calloc分配n个元素、每个大小为size的内存块,并初始化为0,原型:voidcalloc(size_tn,size_tsize),相当于malloc(nsize)后memset为0。realloc调整已分配内存的大小,原型:voidrealloc(voidptr,size_tnew_size)。若当前内存块足够扩展,直接调整大小并返回原指针;若不足,重新分配新内存块,复制原内容,释放旧块,返回新指针(原指针失效)。若ptr为NULL,realloc等同于malloc;若new_size为0,等同于free(ptr)。预处理、编译、汇编、链接的作用分别是什么?1.预处理(Preprocessing):处理include、define、if等预处理指令,展开头文件、替换宏、删除注释,提供.i文件;2.编译(Compilation):将预处理后的代码转换为汇编语言,进行词法分析、语法分析、语义检查,提供.s文件;3.汇编(Assembly):将汇编语言转换为机器指令(二进制目标代码),提供.o(或.obj)文件;4.链接(Linking):将多个目标文件和库文件(静态/动态)链接成可执行文件,解决符号引用(如函数调用、全局变量),提供.exe(Windows)或ELF(Linux)文件。如何判断单链表是否有环?使用快慢指针法(Floyd判圈算法)。定义两个指针,slow每次移动1步,fast每次移动2步。若链表有环,fast最终会追上slow(相遇);若fast到达NULL(链表尾),则无环。代码示例:structListNode{intval;structListNodenext;};boolhas_cycle(structListNodehead){if(head==NULL||head->next==NULL)returnfalse;structListNodeslow=head;structListNodefast=head->next;while(slow!=fast){if(fast==NULL||fast->next==NULL)returnfalse;slow=slow->next;fast=fast->next->next;}returntrue;}若需要找到环的入口点,相遇后将slow重新指向头节点,slow和fast均每次移动1步,再次相遇的节点即为入口点。数组和指针的区别是什么?数组是连续存储相同类型元素的集合,数组名是常量指针(指向首元素地址,不可修改);指针是变量,存储内存地址。sizeof数组名返回整个数组的字节大小,sizeof指针返回指针本身的大小。数组作为函数参数传递时会退化为指针(丢失数组大小信息),因此无法在函数内部用sizeof计算数组长度。例如:voidfunc(intarr[]){printf("%d",sizeof(arr));//输出4或8(指针大小)}intmain(){intarr[5]={1,2,3,4,5};printf("%d",sizeof(arr));//输出20(54)func(arr);return0;}如何实现一个高效的冒泡排序?传统冒泡排序时间复杂度为O(n²),可通过以下优化:1.记录每轮是否发生交换,若未交换说明已有序,提前终止;2.记录最后一次交换的位置,作为下一轮的边界(后续元素已有序)。优化后代码:voidbubble_sort(intarr[],intn){if(n<=1)return;intlast_swap=n1;//初始边界为最后一个元素for(inti=0;i<n1;i++){intswapped=0;intcurrent_swap=0;for(intj=0;j<last_swap;j++){if(arr[j]>arr[j+1]){inttemp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;swapped=1;current_swap=j;//记录最后一次交换的位置}}if(!swapped)break;//无交换,提前结束last_swap=current_swap;//更新下一轮边界}}const修饰函数参数和返回值的意义?修饰参数:防止函数内部修改输入参数的值(如constcharstr防止修改字符串内容)。修饰返回值:若返回指针或引用,防止调用者修改指向的内容(如constcharget_str(),避免get_str()='a'这样的操作)。例如:constcharget_message(){return"hello";}//调用者不能通过返回的指针修改字符串常量(可能导致崩溃)。如何计算二进制中1的个数?方法1:位运算,每次判断最低位是否为1,然后右移。intcount_ones(intn){intcount=0;while(n){count+=n&1;n>>=1;}returncount;}方法2:利用n&(n-1)消除最低位的1。例如n=5(101),n-1=4(100),n&(n-1)=4(100);再次操作n=4&3=0,共2次循环。intcount_ones(intn){intcount=0;while(n){n&=n1;count++;}returncount;}后者时间复杂度为O(k),k为1的个数,更高效。结构体和联合体的区别是什么?结构体(struct)的每个成员占用独立内存空间,总大小是各成员大小之和(考虑对齐);联合体(union)的所有成员共享同一块内存空间,总大小是最大成员的大小(考虑对齐)。例如:structS{chara;//1字节intb;//4字节(偏移4,总大小8)};unionU{chara;//1字节intb;//4字节(共享前4字节)};//总大小4字节(最大成员大小)。联合体用于节省内存,或在不同数据类型间转换(如同时存储int和float)。如何避免头文件重复包含?使用预编译指令:1.ifndef/define/endif:ifndef_HEADER_H_define_HEADER_H_//头文件内容endif2.pragmaonce(部分编译器支持,如MSVC、GCC):pragmaonce//头文件内容前者是标准方法,跨平台兼容性好;后者更简洁,但依赖编译器实现。两种方法均通过在第一次包含时定义宏(或标记),后续包含时跳过内容,避免重复定义(如结构体、函数声明)。如何实现两个变量的交换?不使用临时变量。方法1:算术运算(适用于整数):a=a+b;b=ab;//此时b=(a+b)b=aa=ab;//此时a=(a+b)a=b方法2:位运算(适用于整数,无溢出风险):a=a^b;b=a^b;//等价于(a^b)^b=aa=a^b;//等价于(a^b)^a=b注意:若a和b指向同一块内存(如交换数组中同一元素),算术运算会导致a和b变为0,位运算会导致a和b变为0(因a^a=0),需先判断是否为同一地址。内存分配失败时malloc的返回值是什么?如何处理?malloc分配失败时返回NULL指针(在标准C中)。因此,动态分配后必须检查返回值是否为NULL,避免对NULL指针解引用导致崩溃。例如:charp=(char)malloc(1024);if(p==NULL){perror("mallocfailed");//打印错误信息(如“Notenoughmemory”)exit(EXIT_FAILURE);//或进行其他错误处理}//使用p...free(p);p=NULL;//防止悬空指针在嵌入式系统中,可能禁用exit函数,需根据具体场景处理(如返回错误码、重新分配较小内存)。函数参数的压栈顺序是怎样的?C语言中函数参数的压栈顺序是从右到左(Right-to-Left)。例如调用func(a,b,c),压栈顺序为c→b→a。这是因为C允许可变参数函数(如printf),从右到左压栈可保证最左边的参数(格式字符串)在栈顶,便于通过栈指针偏移访问后续参数。例如:voidfunc(inta,intb,intc){//栈中顺序:c(高地址)→b→a(低地址)}intmain(){func(1,2,3);return0;}压栈顺序由调用约定决定(如__cdecl、__stdcall),但C默认的__cdecl是从右到左。如何判断一个数是否为2的幂?2的幂的二进制表示中只有1个1(如2=10,4=100,8=1000)。利用n&(n-1)的特性:若n是2的幂,则n&(n-1)=0(例如8&7=0)。注意n=0时需特殊处理(0不是2的幂)。boolis_power_of_two(intn){returnn>0&&(n&(n1))==0;}如何实现strcpy函数?需考虑源字符串和目标字符串的重叠情况(如目标字符串在源字符串之后),并确保目标空间足够。标准strcpy不处理重叠,需使用memmove。手动实现:charmy_strcpy(chardest,constcharsrc){if(dest==NULL||src==NULL)returnNULL;charret=dest;while((dest++=src++)!='\0');//复制直到'\0'returnret;}若源和目标重叠(如dest=src+1),会导致源字符串被覆盖,需先判断是否重叠,或使用memmove(内部处理了重叠情况)。volatile关键字的作用是什么?volatile告知编译器变量可能被意外修改(如硬件寄存器、多线程共享变量),禁止编译器对其进行优化(如缓存到寄存器、省略重复读取)。例如:volatileintreg=0x1234;//硬件寄存器,值可能被外部电路修改while(reg==0);//若不加volatile,编译器可能优化为读取一次reg,陷入死循环常见使用场景:中断服务程序中的共享变量、内存映射的硬件寄存器、多线程中的共享变量。如何实现一个简单的内存池?内存池通过预先分配大块内存,减少频繁malloc/free的开销,避免内存碎片。基本步骤:1.定义内存块结构(包含起始地址、大小、是否空闲);2.初始化时分配一大块内存,分割为固定大小的块;3.分配时查找空闲块,标记为已使用;4.释放时标记块为空闲,可选合并相邻空闲块(减少碎片)。示例结构:structMemBlock{size_tsize;//块大小intis_free;//是否空闲structMemBlocknext;//下一个块指针};structMemPool{structMemBlockhead;//内存块链表头voidstart_addr;//内存池起始地址size_ttotal_size;//总大小};初始化内存池时,分配total_size的内存,创建初始MemBlock(size为total_sizesizeof(MemBlock),is_free=1)。分配时遍历链表,找到足够大的空闲块,若块大小大于需求,分割为使用块和剩余空闲块。释放时标记is_free=1,遍历前后块合并。如何处理C语言中的可变参数?使用<stdarg.h>中的宏:va_list(保存参数列表)、va_start(初始化参数列表,指向第一个可选参数)、va_arg(获取当前参数并移动到下一个)、va_end(结束参数列表访问)。例如实现求和函数:intsum(intnum,...){va_listargs;va_start(args,num);//num是最后一个固定参数inttotal=0;for(inti=0;i<num;i++){total+=va_arg(args,int);//获取int类型参数}va_end(args);returntotal;}调用:sum(3,1,2,3)返回6。注意:va_arg需指定正确的类型(与实际参数匹配),否则导致未定义行为。大端序和小端序在网络传输中的处理?网络字节序(NetworkByteOrder)采用大端序,主机字节序(HostByteOrder)可能是大端或小端。发送数据时需将主机字节序转换为网络字节序(htons/htonl),接收时转换为主机字节序(ntohs/ntohl)。例如:uint16_thost_port=8080;uint16_tnet_port=htons(host_port);//转换为网络字节序(大端)//网络传输net_port...uint16_trecv_port=ntohs(net_port);//转换回主机字节序htons(hosttonetworkshort)处理16位,htonl处理32位,ntohs/ntohl是逆操作。如何检测内存越界访问?常见方法:1.工具检测:Valgrind的memcheck可检测越界;2.编译器选项:GCC的-fsanitize=address(ASan)在运行时检测越界;3.手动保护:在分配的内存前后添加哨兵值(如0xDEADBEEF),释放时检查哨兵是否被修改;4.调试版本处理:malloc在调
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年政府公务员考试指南公共管理与政策分析类岗位笔试题目集
- 2026年Python编程基础与进阶试题集及答案
- 2026年旅游景区突发事件应急处理模拟测试
- 2026年新星职业技术学院单招职业适应性考试题库附答案
- 2026年市场营销经理岗位面试专业知识测试题
- 2026年高级财务成本控制与管理题库解析
- 2026年食品营养与健康管理专业毕业论文答辩题目
- 2026年建筑项目防水安全措施三同时知识题
- 2026年数学思维训练逻辑思维与问题解决能力
- 2026年农业技术推广与种植知识考试模拟题
- 医学教材 常见心律失常诊治(基层医院培训)
- 体温单模板完整版本
- 武汉市2024届高中毕业生二月调研考试(二调)英语试卷(含答案)
- 天然美肌无添加的护肤品
- 《正常人体形态学》考试复习题库大全(含答案)
- 湖南省长沙市外国语学校 2021-2022学年高一数学文模拟试卷含解析
- 3D车载盖板玻璃项目商业计划书
- 阿米巴经营管理培训课件
- 我国的宗教政策-(共38张)专题培训课件
- 铝材厂煲模作业指导书
- 【行测题库】图形推理题库
评论
0/150
提交评论