面试问题小结

面试问题小结

1.使用宏定义判断两个数的大小

答:

#define Max(a,b) (a>b)?a:b

2.函数指针和指针函数的区别

答:
函数指针顾名思义就是指向函数的指针,
也就是就是指向代码段中函数入口地址的指针

函数指针的定义可以类比变量的指针来看,例如:

int *count;

即定义了一个指向int类型数据的指针。
函数指针定义方式例如:

int (*p)(int, int);

即定义了一个指向返回值为int类型数据,传递参数为两个int类型数据的函数的指针。

函数指针的初始化方式为:

函数指针变量 =  函数名;
int max(int a, int b)
{
    return a > b ? a : b;
}
p = max;    //函数指针初始化

函数指针的调用方式为:

int ret = p(10, 15);

指针函数顾名思义本质上是一个函数,只是它的返回值是一个指针。
其定义方式为:

int * func_sum(int n)

即定义了一个返回值为指向int类型数据的指针,传递参数为int类型数据的函数。

在使用指针函数的时候,一定要避免出现返回局部变量指针的情况。
原因在于,一般的局部变量是存放于栈区的,当函数结束,栈区的变量就会释放掉,如果我们在函数内部定义一个变量,在使用一个指针去指向这个变量,当函数调用结束时,这个变量的空间就已经被释放,这时就算返回了该地址的指针,也不一定会得到正确的值。

可以使用了static去修饰变量,那么该变量就变成了静态变量。而静态变量是存放在数据段的,它的生命周期存在于整个程序运行期间,只要程序没有结束,该变量就会一直存在,所以该指针就能一直访问到该变量。

3.static关键词的作用

答:
刚好承接上一个问题,就重新复习一下变量的作用域和生命周期和存储区域的相关知识吧。

首先从变量的定义位置出发,变量的类型可以分为:局部变量和全局变量
局部变量就是在函数内部定义的变量,全局变量就是在函数外部定义的变量。

可以列一个表格来看:

特征局部变量全局变量
作用域只在本函数内有效在整个文件有效
生命周期本函数运行期间程序运行期间
存储区域动态存储区静态存储区

这里要先说明,数据的存储空间,可以分为代码区和数据区,而数据区又分为静态存储区和动态存储区。
以上都为不加任何关键词修饰的变量。

其中局部变量,如果加上static关键词修饰后就做静态局部变量,此时该变量的作用域不变,生命周期变为程序运行期间,存储区域由动态存储区变为静态存储区。

其中全局变量,如果加上static关键词修饰后就做静态全局变量,此时该变量的它的特征和上表中一致。

如果全局变量被extern关键词修饰,就做外部全局变量,该关键词直接扩大了该变量的作用域,由文件内有效变为外部文件可用。

除了变量,也可以对函数进行static和extern声明,又分别叫做静态函数(内部函数)和外部函数,也是作用域的差别,静态函数只能在定义该函数的文件内使用,外部函数可以通过包含声明了该函数的头文件在其他文件内调用。

4.用户空间和系统空间的区别

答:
这是Linux系统的相关知识,网上搜的哈
用户空间就是用户进程所在的内存区域,相对的,系统空间就是操作系统占据的内存区域。
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。

5.volatile关键词的作用

答:
简单地说就是防止编译器对代码进行优化。
一般说来,volatile用在如下的几个地方:
a.中断服务程序中修改的供其它程序检测的变量需要加volatile;
b.多任务环境下各任务间共享的标志应该加volatile;
c.存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义

6.堆和栈的区别

答:
堆和栈都是动态存储区的组成部分,温习一下,静态存储区存储的数据都包括:全局变量和static变量(包括静态局部变量和静态全局变量)。

栈:保存局部变量。栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁。其特点是效率高,但空间大小有限。

堆:由malloc系列函数或new操作符分配的内存。其生命周期由free或delete决定。

7.数组和链表

答:
数组:在内存中,是一块连续的内存区域;
链表:是由不连续的内存空间组成;

项目数组链表
随机访问性
查找速度
插入和删除效率
内存要求宽松度
大小扩展难度

8.位段和联合体

答:
贴一段网上代码吧

typedef struct{  
    uchar bit0:1;  
    uchar bit1:1;  
    uchar bit2:1;  
    uchar bit3:1;  
    uchar bit4:1;  
    uchar bit5:1;  
    uchar bit6:1;  
    uchar bit7:1;  
}bits;  
typedef union{  
    uchar data_char;  
    bits  data_bits;   
}utype;  
  
uchar *addr = (uchar*)0x10;  
utype value;  
value.data_char = *addr;  
  
如果要查看某个位比如第3位  
直接看 value.data_bits.bit3就可以了。  
  
  
如果要设置某个位,比如设置第0位为1,第7位为0  
value.data_bits.bit0 = 1;  
value.data_bits.bit7 = 0;  
*addr = value.data_char;  

9.进程和线程的区别

答:
每一个程序相当于一个进程,而一个进程之中可以有多个线程 。
以下是网上找的
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值