c语言面试题总结

一、必须完成的函数封装

① 判断一个数是不是素数
② 斐波那契数列打印
③ 杨辉三角
④ 两个数的最大公约数和最小公倍数
⑤ 冒泡排序
⑥ 二分查找
⑦ 选择排序
⑧ 插入排序
⑨ strlen、strcpy、strcmp、strcat、strstr、atoi、itoa、strncpy、strncat、strncmp、memset、memcpy

注:前4个为常见使用,出现频率高,所以也要求完成
要求以上所有函数必须能够手写完成封装,要求做到,手写结果以没有标点符号错误并且能做到8分钟内完成为标准,不限具体实现过程,可参考相关资料。
详细代码见:

二、必须能够回答的简答题

① static的用法?

a、static修饰变量,多次调用使用上一次调用结果
b、static修饰变量,若未初始化,则由系统赋予确定值
c、static修饰全局变量,限制全局变量不能被外部调用
d、static修饰函数,限制函数不能被外部调用

② 栈区与堆区的区别?
管理方式:堆区由程序员管理,栈区由系统自己管理
空间大小:栈空间小,空间大。
能否产生碎片不同:栈区不会产生碎片,但是堆区会产生,会有内 存泄露
生长方向不同:栈向下压栈,堆是向上存放数据
分配方式不同:栈是由程序员申请之后,由系统分配的没有经过初试化的变量,只有动态的分配方式。而堆是由程序员自己实例化,创建已经初始化的变量,分配方式类似于链表动态分配,静态分配都可以
分配效率不同:栈由内存分配,系统专门为其准备寄存器,同时有专门的进栈和出栈的命令,因此效率较高,而堆由c库分配,可能会存在碎片的原因导致内存不连续,因而效率比较低

③ break、continue、return的区别
break退出本层循环
continue跳过本次循环,进入下一次循环
return 函数结束
④ typedef与define的区别
a、typedef属于语句,define属于预处理命令
b、typedef只作用于数据里类型的重命名,define常在宏中替换常量,变量、表达式,数据类型。
c、define编译时不会被检测错误,typedef会有类型检查功能
⑤ sizeof与strlen的区别
a、本质不同;sizeof是运算符号,strlen是函数
b、计算对象不同:sizeof 可以计算变量、指针、数组等,strlen只能计算字符串
c、计算本质不同:strlen计算字符串中有效的字符个数,不包括‘\0’,sizeof计算传入对象所占空间大小,跟是否存值无关
⑥ volatile的用法
⑦ 指针?
⑧全局变量与局部变量
比较维度

a、 全局变量的生命周期为整个程序执行时间,局部变量的生命周期为局部变量调用时间
b、全局变量的作用范围为整个程序,局部变量的作用范围为局部空间
c、 全局变量的若未初始化则有系统赋予确定值,局部变量若未初始化则有系统赋予随机值
d、在局部范围内修改全局变量,则其他使用全局变量的区域都会被修改
e、若局部范围内存在与全局变量同名的局部变量,则优先调用局部变量
注:① 类似于这种单独的知识点,回答时需要了解是什么?有什么特点?怎么用?
② – ⑥ 类似于这种比较类的知识点,回答时需要先各自解释自己是什么,有什么特点?
区别主要体现在用法上,不一定只有不同点,也有相同点,需要注意不能只答一部分

⑦ 类似于这种综合类的知识点,回答时需要详细,有步骤,将其涉及到的方方面面都要答出来,按照自己的知识体系进行组织,避免漏讲、讲错、混乱出现,这种问题属于多答多得,不一定仅限于当前语言、当前科目、当前领域。主要体现的是知识的熟悉程度、理解程度、应用程度以及扩展程度,考察性很强,最好提前总结。

三、必须会做的笔试题

注:笔试原题,几乎没有变化,但不意味着直接记答案,需要完全了解原理,不然出现变化,直接结束。

① 写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
答案:#define MIN(A,B) ((A) <= (B) ? (A) : (B))
重点:使用宏函数,参数使用加()

② 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
答案:#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
重点:UL是什么,为什么要用UL

③ 已知一个数组table,用一个宏定义,求出数据的元素个数。
答案:#define NTBL(table) (sizeof(table)/sizeof(table[0]))
重点:使用宏函数,数组大小计算

④ 下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
答案: > 6 这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 “>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。

重点:隐式类型转换中有符号数和无符号数的计算以及超值域计算

⑤ 请填写bool,int,float, 指针变量 与“零值”比较的if语句。
答案:
bool:
bool flag;
if(flag)
int:
int a;
if(a == 0)
float:
float f;
if(-0.000001 <= f && f <= 0.000001)
指针变量:
int *p;
if(p == NULL)

重点:对于"零值"在不同情况下的理解

⑥ 交换两数,实现方式
答案:
(1)使用第三变量
int a=3,b=4;
int c;
c=a;
a=b;
b=c;
printf(“a=%d,b=%d”,&a,&b);

(2)不需要使用第三变量,使用加减实现
int a=3,b=4;
a=a+b;
b=a-b
a=a-b;
printf(“a=%d,b=%d”,&a,&b);

(3)不需要使用第三变量,使用乘除实现
int a=3,b=4;
a=a*b
b=a/b
a=a/b;
printf(“a=%d,b=%d”,&a,&b);

(4)不需要使用第三变量,使用位运算实现
int a=3,b=4;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf(“a=%d,b=%d”,&a,&b);

重点:常用第一种,其他也必须掌握

⑦ 要对绝对地址0x100000赋值,我们可以用*(unsigned int*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
答案:((void ()( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即:
(void (*)())0x100000
然后再调用它:
((void ()())0x100000)();

重点:对于地址的理解

⑧ 现有一个绝对地址0xbf988c5c,要求给这个确定的地址赋值为整型数50,请在横线处填写正确的C语言语句
答案:*((int *)0xbf988c5c)=50;
重点:对于地址的理解

⑨ 下面代码有什么问题
1)void GetMemory(char *p)
{
p = (char *) malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str,”hello world”);
printf(“%s”,str);
}
答: 乱码,str不能带出局部范围开辟的空间
2)

void GetMemory(void)
{
char p[] = “hello world”;
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(“%s”,str);
}
答: 乱码,局部地址不能返回
3) void GetMemory(char **p,int num)
{
*p = (char *) malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str,100);
strcpy(str,”hello world”);
printf(“%s”,str);
}
答案: hello world,二级地址可以带出局部范围内开辟的空间的地址,因为该局部空间本身的起始地址就是一级地址

重点:对于函数形参和实参的理解,传入指针不代表地址传参,比较另类

⑩ 下面程序的输出是_____,为什么?
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
{
puts(“Got a null pointer”);
}
else
{
puts(“Got a valid pointer”);
}
注:malloc申请0字节大小空间,返回值为一个有效的指针,但是不可用,不是NULL

答案:输出Got a valid pointer,申请空间为0字节,不表示申请失败

⑪ 请说出以下三种定义的区别(详情见附录)
const char *p;
char * const p;
const char * const p;

答案:第一种const修饰p,所以指针指向空间内容不能修改,即p的值不能修改
第二种const修饰p,所以指针指向不能修改,即p的值不能修改
第三种const修饰p也修饰p,所以指针指向空间内容和指针指向都不能修改,即p和p的值都不能修改

重点:认真观察const修饰的对象,与数据类型无关
char const *p; 同第一种

⑫ 用变量a给出下面的定义
1) 一个整型数(An integer)
2) 一个指向整型数的指针(A pointer to an integer)
3) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
4) 一个有10个整型数的数组(An array of 10 integers)
5) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
6) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
7) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
8) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )

答案:① int a;
② int *a;
③ int **a;
④ int a[10];
⑤ int *a[10];
⑥ int (*a)[10];
⑦ int (*a)(int);
⑧ int (*a[10])(int);

重点:需要对各种指针熟悉

⑬ 描述内存分配方式以及它们的区别?
答案:1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

重点:内存上分配空间,千万不要和栈区与堆区区别混淆

⑭ #include <filename.h>和 #include “filename.h” 有什么区别?
答案: 1>,#include<xxx.h>:系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。
2>,#include “xxx.h”:用户自定义的文件用双引号括起来,编译器首先会在用户目录下查找,然后在到C++安装目录(比如VC中可以指定和修改库文件查找路径,Unix和Linux中可以通过环境变量来设定)中查找,最后在系统文件中查找。

重点:系统头文件和自定义头文件不太相同,使用起来不一样

⑮ #ifndef的作用
答案:是"if not defined"的简写,是宏定义的一种,它是可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等等。 
例: 
#ifndef x //先测试x是否被定义过
  #define x //如果没有定义下面就定义x并执行下面的语句
  …
#endif //如果已经定义了则执行#endif后面的语句
一般常用于头文件中,防止头文件的重复包含和编译

重点:常用于工程中防止头文件的多次包含

⑯ 以下代码的作用是什么?
#if MAX

#endif
答案:若MAX值为0,则会跳过#if MAX与#endif之间的代码;
若MAX值为1,则会将#if MAX与#endif之间的代码一起编译

重点:条件编译的一种,根据宏值(真假)进行相关编译

⑰ struct node
{
int data;
struct node *next;
} *p;
以下语句调用malloc函数,使指针p指向一个具有struct node类型的动态存储空间。请填空p = (struct node *)malloc(________);
答案:sizeof(struct node)或 8
重点:理解malloc参数以及结构体这种构造数据类型,注意是数据类型struct node

⑱ 设有以下说明和定义:
  typedef union {long i; int k[5]; char c;} DATE;
  struct data { int cat; DATE cow; double dog;} too;
  DATE max;
 则语句 printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:( )

答案:52
重点:共用体的特殊性和共用体、结构体等构造数据类型的嵌套计算以及字节对齐

⑲ (9)某32位系统下, C程序,请计算sizeof 的值.
char str[] = “http://www.stkj.com/”;
char *p = str ;
char array[10] = {‘h’,’e’,’l’,’l’,’\0’,’o’};
请计算
sizeof (str ) = ?(1)
sizeof ( p ) = ? (2)
sizeof ( array ) = ?(3)
strlen(array) = ?(4)
void Foo ( char str[100]){
请计算
sizeof( str ) = ? (5)
}
void *p = malloc( 100 );
请计算
sizeof ( p ) = ?(6)

答案:(1) 21  
      (2) 4  
	  (3) 10  
	  (4) 4  
	  (5) 4  
	  (6) 4

重点:如何理解sizeof的计算对象是指针,还是正常计算对象
      需要注意下面这个例子:
	  void fun(char *p)
	  {
	      printf("%d\n",sizeof(p));
		  printf("%d\n",strlen(p));
	  }
	  
	  woid main()
	  {
	    char *str1 = "hello";
	    fun(str1);
	  }
	  
	  以上程序输出结果是什么?说出原因。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值