C语言面试题

1、考点宏定义和运算符优先级

#include <stdio.h>

#define SUM(a,b,c) ++a+(b+c++)

int main()
{
	int a=2,b=3,c=4;
	int d = SUM(a,b,c)/SUM(a,b,c);

    printf("d:%d \n",d);
    return 0;
}

注意:宏定义是否有括号,运算符优先级() > ++变量名 > /;经典
C运算符优先级:http://www.slyar.com/blog/c-operator-priority.html

2、解释黑盒测试、白盒测试、单元测试、集成测试、系统测试、验收测试的联系与区别,做好测试计划工作的关键是什么?

3、sizeof()与strlen()计算

https://blog.csdn.net/M_joy666/article/details/80471230

示例一:

#include <stdio.h>

int main()
{
	char *ss = "0123456789";
	int i = sizeof(ss); 	/*i = 4*/
	int j = sizeof(*ss); 	/*j = 1*/
	int k = strlen(ss); 	/*k = 10*/
   	printf("i:%d,j:%d,k:%d! \n",i,j,k);
	
	int *num = {1,2,3};
	int m = sizeof(*num);
	printf("m:%d \n",m);	/*m = 4*/
    return 0;
}

注意:sizeof(*ss) == sizeof(ss[0]);

示例二:

#include <stdio.h>
void main()
{
   char str[]="yanguoqi";
   char *p = str;
   printf("sizeof(str) = %d\n", sizeof(str));	//字符数+1
   printf("strlen(str) = %d\n", strlen(str));
   printf("sizeof(p) = %d\n", sizeof(p));		//看系统
   printf("strlen(p) = %d\n", strlen(p));
}

4、结构体(内存对齐、sizeof计算)

https://blog.csdn.net/dai_wen/article/details/78304568

1.什么是结构体?
结构体是一系列数据的集合
2.一般在什么情况下用到结构体?
a、一般当内置内存无法满足用户需要,没有合适类型对应对象时,需要封装特定的类型
b、当函数有多个参数时,返回值过多,需要封装特定类型,将参数打包返回
3.什么是结构体内存对齐?为什么要对齐?怎样对齐?
结构体内存对齐:元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每个元素放置到内存中时,它都会认为内存是按照自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始。

struct   A
{
	int a;
   	char b;
	double c;		//min(默认对齐参数,类型最大字节数)=8
   	char d;
};

sizeof计算嵌套的结构体大小

truct stu5  
{  
      short i;  
      struct   
      {  
           char c;  
           int j;  
      } ss;   
      int k;  
}  

结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。

对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:
1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

https://www.cnblogs.com/0201zcr/p/4789332.html

5、二叉树及其三种遍历
https://blog.csdn.net/qq_33243189/article/details/80222629
https://www.cnblogs.com/shunyu/p/4986288.html
https://blog.csdn.net/qq_40772692/article/details/79343914

二叉树遍历分为三种:前序、中序、后序,其中序遍历最为重要。

前序顺序(根节点排最先,然后同级先左后右);中序顺序(先左后根最后右);后序顺序(先左后右最后根)。

6、C链表、链表排序、链表增删改查

插入指定位置、插入指定值到单向有序列表;
删除指定值、删除指定位置;
链表有:单向链表,双向链表、环形链表、十字链表

https://blog.csdn.net/mathew_leung/article/details/79795909
https://blog.csdn.net/mathew_leung/article/details/83868991

7、数组排序示例

冒泡排序法:
https://blog.csdn.net/mathew_leung/article/details/80400188

冒泡排序-1:

#include <stdio.h>

int main()
{
	int nums[10] = {4, 5, 2, 10, 7, 1, 8, 3, 6, 9};
	int i, j, temp;
	int count = sizeof(nums)/sizeof(int);

	for(i=0; i<count-1; i++){
		for(j=0; j<count-1-i; j++){
			if(nums[j] > nums[j+1]){
				temp = nums[j];
				nums[j] = nums[j+1];
				nums[j+1] = temp;
			}
		}
	}
	for(i=0; i<10; i++){
		printf("%d ", nums[i]);
	}
	printf("\n");
	return 0;
}

冒泡排序-2:

#include <stdio.h>

int main()
{
	int nums[10] = {4, 5, 2, 10, 7, 1, 8, 3, 6, 9};
	int i, j, temp, isSorted;

	//优化算法:最多进行 n-1 轮比较
	for(i=0; i<10-1; i++){
		isSorted = 1; //假设剩下的元素已经排序好了
		for(j=0; j<10-1-i; j++){
			if(nums[j] > nums[j+1]){
				temp = nums[j];
				nums[j] = nums[j+1];
				nums[j+1] = temp;
				isSorted = 0; //一旦需要交换数组元素,就说明剩下的元素没有排序好
			}
		}
		if(isSorted) break; //如果没有发生交换,说明剩下的元素已经排序好了
	}

	for(i=0; i<10; i++){
		printf("%d ", nums[i]);
	}
	printf("\n");
	return 0;
}

选择排序和冒泡排序:
https://www.cnblogs.com/zhouquan-1992-04-06/p/6207664.html

#include <stdio.h>

int main()
{
	int arr[6] = {3,5,2,1,9,6};
	int i,j,temp;
	#if 0	//冒泡排序法
	for(i=0;i<6;i++)
	{
		for(j=0;j<6-i;j++)
		{
			if(arr[j] > arr[j+1])
			{
				temp = arr[j+1];
				arr[j+1] = arr[j];
				arr[j] = temp;
			}
		}
	}
	#else	//选择排序法
	int length = sizeof(arr)/sizeof(int);
	for(i=0;i<length;i++)
	{
		for(j=i+1;j<length;j++)
		{
			if(arr[j]<arr[i])//如果后一个元素小于前一个元素则交换
			{
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}
	#endif
	
	for(i=0;i<6;i++)
		printf("%d \t",arr[i]);
}

8、解释大小端模式、使用上的区分、及如何确认系统是哪种模式?

https://www.cnblogs.com/Alandre/p/4878841.html
https://www.cnblogs.com/dylancao/p/8472879.html

【大端模式】 CPU对操作数的存放方式是高地址存放低位,低地址存放高位。

【小端模式】CPU对操作数的存放方式是高地址存放高位,低地址存放低位。

大多数ARM处理器都是采用的小端模式,PowerPC是采用的大端模式,网络字节序是采用的大端模式。

大小端针对多字节数据类型,如int、short、long等;

常用的有两种方式来判断大小端,一种是使用C语言中的联合体,具体代码如下:

#include <stdio.h>

int checkSystem()
{
	union check
	{
		int i;
		char ch;
	} c;
	c.i = 1;
	return (c.ch == 1);//大端返回0,小端返回1
}
int main()
{
	int ret = checkSystem();
	printf("%s\n",(ret==1)?"小端":"大端");
}

9、static在C中的用法

https://blog.csdn.net/guotianqing/article/details/79828100

static核心是两个功能:1.改变作用域;2.改变生命周期;

static修饰局部变量:作用域是本函数内,生命周期是程序运行期间一直都存在,存放在static静态缓冲区;
static修饰全局变量:作用域是本文件内,生命周期是程序运行期间一直都存在,存放在static静态缓冲区;
static修饰函数:作用域是本文件内;

编译器自动对其初始化 static修饰的变量,如static int num会被编译器自动初始化为0.

10、引用与指针的概念和区别

https://blog.csdn.net/u013130743/article/details/80806179

c语言中没有引用,“.c”文件是不可以使用引用;引用类型是C++提供的;引用相当于变量的另外一个名字;

指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;
引用:引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已;

引用和指针的区别:

1)引用必须被初始化,指针不必。
2)引用初始化以后不能被改变,指针可以改变所指的对象。
3)不存在指向空值的引用,但是存在指向空值的指针。

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。

流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用

11、C语言内存分布图
https://blog.csdn.net/yanbober/article/details/8713250

12、内存管理
https://www.cnblogs.com/ralap7/p/9184773.html

13、解释堆和栈的区别

(1)申请方式
(2)申请后系统的响应
(3)申请大小的限制
(4)申请效率的比较
(5)堆和栈中的存储内容
(6)存取效率的比较

14、三种基本的数据模型

答:按照数据结构类型的不同,将数据模型划分为层次模型、网状模型和关系模型。

https://www.cnblogs.com/daniumeng/p/8717438.html

15、结构与联合有和区别?

答:(1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。

(2). 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的

16、描述内存分配方式以及它们的区别?

答:1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。

2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。

3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多

C语言面试宝典:
https://blog.csdn.net/chengxuyuan997/article/details/82048231
https://blog.csdn.net/themagickeyjianan/article/details/79047242

问题测试:
关键字static的作用是什么?
“引用”与指针的区别是什么?
.h头文件中的ifndef/define/endif 的作用?
#include 与 #include "file.h"的区别?
描述实时系统的基本特性
局变量和局部变量在内存中是否有区别?如果有,是什么区别?
什么是平衡二叉树?
堆栈溢出一般是由什么原因导致的?
冒泡排序算法的时间复杂度是什么?
什么函数不能声明为虚函数?
队列和栈有什么区别?
不能做switch()的参数类型
如何引用一个已经定义过的全局变量?
全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
语句for( ;1 ;)有什么问题?它是什么意思?
do……while和while……do有什么区别?
statac 全局变量、局部变量、函数与普通全局变量、局部变量、函数
程序的内存分配
解释堆和栈的区别
什么是预编译,何时需要预编译?
关键字const是什么含意?
三种基本的数据模型
结构与联合有和区别?
描述内存分配方式以及它们的区别?
请说出const与#define 相比,有何优点?
简述数组与指针的区别?
分别写出BOOL,int,float,指针类型的变量a 与“零”的比较语句。
如何判断一段程序是由C 编译程序还是由C++编译程序编译的?
论述含参数的宏与函数的优缺点
用两个栈实现一个队列的功能?要求给出算法和思路!
嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
位操作(Bit manipulation)
访问固定的内存位置(Accessing fixed memory locations)
中断(Interrupts)
动态内存分配(Dynamic memory allocation)
Typedef
39、用变量a给出下面的定义
解释局部变量、全局变量和静态变量的含义。
写一个“标准”宏
A.c 和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题?这两个static变量会保存到哪里(栈还是堆或者其他的)?
一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值