• Linux C 面试题汇总(总有你不知道的知识点)


    摘自:https://blog.csdn.net/chen1415886044/article/details/98891245

    linux C


    1.用变量a给出下面的定义.

    a) 一个整型数
    b) 一个指向整型数的指针
    c) 一个指向指针的的指针,它指向的指针是指向一个整型数
    d) 一个有10个整型数的数组
    e) 一个有10个指针的数组,该指针是指向一个整型数的
    f) 一个指向有10个整型数数组的指针
    g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数
    h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

    答案是:
    a) int a;
    b) int *a;
    c) int **a;
    d) int a[10];
    e) int *a[10];
    f) int (*a)[10];
    g) int (*a)(int);
    h) int (*a[10])(int);

    2.写一个“标准”宏MIN,这个输入两个参数并返回较小的一个。
    #define Min(a,b) ( ((a)>=(b))?(b):(a))

    3.嵌入式经常用到死循环,你怎么样用C来编写死循环呢?
    我的首选就是:
    while(1){},一些有经验的程序员喜欢用for( ; ; ){} ,还有一种是写汇编语言的程序员常用的写法:
    Loop:

    goto Loop;

    4.引用和指针的区别?

    答:1.引用必须要初始化,指针可以不用初始化;2.不存在指向空值的引用,但是存在指向空值的指针;3.引用初始化后不能改变,但存在指向空值的指针;4.引用是变量的别名,本身不单独分配自己的内存空间,而指针有自己的内存空间;

    5.关键字static的作用是什么?

    在c语言中static有三个明显的作用:
    1)static在修饰局部变量的时候,其使得局部变量的生命周期发生改变,使得其放在data段,直到程序运行结束才结束。
    2)static在修饰全局变量的时候,作用是改变其作用域,使得全局变量只能在定义的文件中使用。
    3)static在修饰函数的时候,同样也是只能时函数只能在当前的文件中使用。

    6.请填写bool , float, 指针变量 与“零值”比较的if语句。

    1)if ( flag ) if ( !flag )
    2)const float EPSINON = 0.00001;
    if ((x >= - EPSINON) && (x <= EPSINON)
    3)if (p == NULL) if (p != NULL)

    7.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

    #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

    8.extern c 作用

    告诉编译器该段代码以C语言进行编译。

    9.头文件中的 ifndef/define/endif 干什么用?

    预处理,防止头文件被重复使用。

    10.do……while和while……do有什么区别?

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

    11.C语言链表与数组的区别?

    链表跟数组都属于一种数据结构。可以分为两个点来看:
    从逻辑结构来看
    1)数组必须事先定义固定的长度,不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
    2) 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。链表必须根据next指针找到下一个元素。
    从内存存储来看
    1)(静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小
    2)链表从堆中分配空间, 自由度大但是申请管理比较麻烦

    12.队列和栈有什么区别?

    队列先进先出,栈后进先出。

    13.const 有什么用途?

    1)可以定义const常量。
    2)修饰函数的返回值和形参。

    14 . #include <…h> 和#include “…h” 有什么区别?

    对于#include <…h> ,编译器从标准库路径开始搜索.h
    对于#include “…h” ,编译器从用户的工作路径开始搜索.h

    15.请写出下列代码的输出内容

    #include <stdio.h>
    int main()
    {
    	int a,b,c,d;
    	a=10;
    	b=a++;
    	c=++a;
    	d=10*a++;
    	printf("b,c ,d:%d,%d,%d",b,c,d );
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    10,12,120

    16.关键字volatile有什么含意?

    提示编译对象的值可能在编译器未检测到的情况改变。

    18.不用标准库函数,写一个字符串拷贝函数strcpy。

    1)不考虑重叠问题:

    	char* strcpy(char* dst, const char* src)
    	{
    			assert((dst != NULL )&&(src != NULL));
    			char * ret = dst;
    			while ((*dst ++ = *src ++) != '');
    			return ret;
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2)strcpy考虑重叠与不重叠问题:

    	char *strcpy(char *dst, const char *src)
    	{
    			assert((dst != NULL) && (src != NULL));
    			char *ret = dst;
    			int size = strlen(src) + 1;
    			if (dst > src  || dst < src + szie)
    			{
    					dst = dst + size -1;
    					  src = src + size -1;
    					while (size -- )
    					{
    						*dst ++ = *src ++;
    					}
    			}
    			else
    			{
    					while (size --)
    					{
    						*dst ++ = *src ++;
    					}
    				}
    			
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    19.在下面语句中,fd的具体含义?

    void ((*fp)(int))[10];
    1).()的优先级最高所以先看(*fp),fp是个指针;
    2). 假设 func=(*fp); func(void ) 是个指针函数返回值是个指针,参数是(void),所以fp是指向指针函数的函数指针;

    20.有一个16位整数,每4位为一个数,写函数求他们的和。

    解析:
    整数1101010110110111
    和 1101+0101+1011+0111

    char SumOfQuaters(unsigned short n)
    {
    		char c = 0;
    		int i = 4;
    		do
    		{
    				c += n & 15;
    				n = n >>4;
    		}while(--i);
    return c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    21.用c语言写一个冒泡排序函数。

    /*
    冒泡排序: 比较相邻的元素,如果第一个比第二个大,交换他们两个;
    */
    
    void BubbleSort(int *arr,int size)
    {
    	int i,j,temp;
    	for (i = 0; i < size - 1; i++)
    	{
    		for (j = 0; j <size -i -1; j++)
    		{
    			if (arr[j] > arr[j+1])
    			{
    				temp = arr[j];
    				arr[j] = arr[j+1];
    				arr[j+1] =temp;
    			}
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

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

    1).内存泄露,比如某一数组原先已定义好大小,但是在后续操作中存放的个数超出这一既定长度,会导致堆栈溢出。
    2).由于程序员动态申请的内存块使用后未立即释放,导致内存区不够用,也会导致堆栈溢出 。

    23.请用指针实现一个函数,函数的功能是交换2个整数,并要求写出如何调用这个函数。

    #include "stdio.h"
    void fun(int  *x,int  *y)
    {
    	int t;
    	t=*x;
    	*x=*y;
    	*y=t;		
    
    }
    int main(int argc, char **argv)
    {
    	int a,b;
    	printf("请输入a和b:");
    	scanf("%d%d",&a,&b);
    	fun(&a,&b);
    	printf("
     = %d ,b = %d
    ",a,b);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    24.c语言程序运行的时候内存分布?

    1).堆区:在动态申请内存的时候,在堆里开辟内存。
    2).栈区: 主要存放局部变量(在函数内部,或复合语句内部定义的变量)。
    3).静态/全局区
    3.1):未初始化的静态全局区 (bss区):
    静态变量(定义的时候,前面加 static 修饰),或全局变量 ,没有初始化的。
    3.2):初始化的静态全局区 全局变量、静态变量,赋过初值的,存放在此区 。

    4.代码区:存放咱们的程序代码
    5.文字常量区 :存放常量的。

    25.写一个链表逆序?

    struct link
    {
    int data;
    link* next;

    };

    link* reverse(link *head)
    {
    link *p,*q,*r;
    if (head ==NULL ||head ->next ==NULL)
    return head;
    p = head;
    q = head->next;
    while(q != NULL)
    {
    r = q ->next;
    q->next = p;
    p = q;
    q = r;
    }
    head ->next =NULL;
    head = p;
    return head;
    }

    26.怎么判断链表中是否有环?

    /*
    分析:用两个指针来遍历这个单向链表,第
    一个指针p1,每次走一步;第二个指针p2,每次走两
    步;当p2 指针追上p1的时候,就表明链表当中有环
    路了。
     */
    struct link
    {
    	int data;
    	link* next;
    
    };
    
    bool Isloop(link* head)
    {
    	link *p1;
    	link *p2;
    	p1 = head;
    	p2 = head;
    	if (head == NULL   ||  head -> next == NULL)
    		return false;
    	do
    	{
    		p1 = p1 ->next;
    		p2 = p2 ->next->next;
    	}while(p2&&p2->next&&p1!=p2);
    	if (p1 == p2)
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    27.什么是守护进程?

    守护进程:是指在UNIX或其他多任务操作系统中在后台执行的电脑程序,并不会接受电脑用户的直接操控。此类程序会被以进程的形式初始化。守护进程程序的名称通常以字母“d”结尾:例如,syslogd就是指管理系统日志的守护进程。通常,守护进程没有任何存在的父进程(即PPID=1),且在UNIX系统进程层级中直接位于init之下。守护进程程序通常通过如下方法使自己成为守护进程:对一个子进程调用fork,然后使其父进程立即终止,使得这个子进程能在init下运行。这种方法通常被称为“脱壳”

    28.描述一下进程与线程的区别?

    1)调度:线程作为调度和分配的基本单元,进程作为拥有资源的基本单位;
    2)并发性:不仅进程可以并发执行,同一进程内的线程也可以并发执行。
    3)拥有资源:进程是拥有资源的基本独立单元,线程不拥有资源,但可以访问进程内的资源;
    4)在创建或撤销线程时,由于系统都要为之分配和回收内存资源,导致系统的开销明显大于创建或撤销线程时的开销。

    29.进程之间通信有哪些?

    1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。
    2)有名管道(named pipe):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间通信。
    3)信号量(semophore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
    4)消息队列(message queue):消息队列是由消息组成的链表,存放在内核中 并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
    5)信号处理机制(signal):信号是一种比较复杂的通信方式,用于通知接收进程某一事件已经发生。
    6)共享内存(shared memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,共享内存是最快的IPC方式,它是针对其他进程间的通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。
    7)套接字(socket):套接字也是一种进程间的通信机制,与其他通信机制不同的是它可以用于不同及其间的进程通信。

    30.exit()、_exit()和return()的区别?

    exit():结束当前的进程,并且会刷新缓存区,关闭没有关闭的文件等。
    _exit():结束当前的进程,不对缓存区刷新。
    return:
    1)在main函数中会结束当前进程。
    2)在子函数中,会返回调用当前函数的调用位置,进程从下个C语句开始执行。

    31.fork与vfork区别?

    fork和vfork都用于创建子进程。但是vfork创建子进程后,父进程阻塞,直到子进程调用exit()或者excle()。
    对于内核中过程fork通过调用clone函数,然后clone函数调用do_fork()。do_fork()中调用copy_process()函数先复制task_struct结构体,然后复制其他关于内存,文件,寄存器等信息。fork采用写时拷贝技术,因此子进程和父进程的页表指向相同的页框。但是vfork不需要拷贝页表,因为父进程会一直阻塞,直接使用父进程页表。

    32.路由器工作在哪一层(B)

    A:链路层 B:网络层 C:传输层 D:应用层

    33.网络192.168.220.0/24 定向广播地址是(192.168.220.255),受限的广播地址为(255.255.255.255);

    34.简述TCP/IP协议中三次握手的过程及涵义?

    第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手

    35.简述一下TCP 、UDP 的区别?

    TCP:TCP 则提供面向连接的服务。在传输数据前必须先建立连接,数据传输完毕后要释放连接。
    UDP:UDP协议是面向无连接的用户数据报协议,在传输数据之前不需要先建立连接。远地主机的运输层收到UDP报文后,不需要给出任何确认。

    区别:
    是否面向连接:Tcp面向连接 ,udp是面向无连接
    是否可靠: Tcp可靠 ,udp不可靠
    应用场合: Tcp应用于传输大量数据 ,udp用于传输少量数据
    速度: Tcp的速度慢 ,udp的速度快
    是否能够广播:tcp不能 ,udp能广播
    tcp是基于连接的,速度慢,有校验等,所以传送相同的数据,要比UDP发送的包多很多。

    36.请说明信号量与互斥量的区别?

    答:互斥量用于线程的互斥,信号量用于线程的同步。其根本区别在于互斥和同步之间的区别。
    互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
    同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

    37.socket什么情况下可读?

    1)socket接收缓冲区中已经接收的数据的字节数大于等于socket接收缓冲区低潮限度的当前值;对这样的socket的读操作不会阻塞,并返回一个大于0的值(准备好读入的数据的字节数)。
    2)连接的读一半关闭(即:接收到对方发过来的FIN的TCP连接),并且返回0;
    3)socket收到了对方的connect请求已经完成的连接数为非0.这样的soocket处于可读状态。
    4)异常的情况下socket的读操作将不会阻塞,并且返回一个错误(-1)。

    38.socket编程,如果client断电了,服务器如何快速知道?

    使用定时器(适合有数据流动的情况);使用socket选项SO_KEEPALIVE(适合没有数据流动的情况);

    1)、自己编写心跳包程序,简单的说就是自己的程序加入一条线程,定时向对端发送数据包,查看是否有ACK,根据ACK的返回情况来管理连接。此方法比较通用,一般使用业务层心跳处理,灵活可控,但改变了现有的协议;
    2)、使用TCP的keepalive机制,UNIX网络编程不推荐使用SO_KEEPALIVE来做心)跳检测。

    39.https与http的区别?如何实现加密传输?

    1)https就是在http与传输层之间加上了一个SSL。
    2)对称加密与非对称加密。

  • 相关阅读:
    SpringKafka——消息监听
    RabbitMQ(八)线程池消费
    RabbitMQ(七)延迟队列
    window计划任务 0x1
    获取网页URL地址及参数等的两种方法(js和C#)
    HttpWebRequest的偶尔请求超时问题
    用HTML、CSS、JS制作圆形进度条(无动画效果)
    批量关联update
    仅仅 IE8 有效的 CSS hack 写法
    SqlServer关闭与启用标识(自增长)列
  • 原文地址:https://www.cnblogs.com/LiuYanYGZ/p/14296317.html
Copyright © 2020-2023  润新知