常见Linux嵌入式面试题--单片机C语言杂项知识点

1.中断与异常区别:

异常:在产生时必须考虑与处理器的时钟同步,实际上异常也称为同步中断。在处理器执行到由于编程失误而导致的错误指令时,或者在执行期间出现特殊情况(如缺页),必须靠内核处理的时候,处理器就会产生一个异常。

所谓中断就是外部硬件产生的一个电信号,从CPU的中断引脚进入,打断当前CPU的运行。

所谓异常就是软件运行中发生了一些必须作出处理的事件,CPU自动产生一个陷入来打断当前运行,转入异常处理流程。

2.进程与线程的区别:

a:调度:线程作为调度与分配的基本单位,进程作为拥有资源的基本单位

b:并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

c:拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源

d:系统开销:在创建或撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销

3.volatile关键字有什么含义

volatile说明这个变量可能会被意想不到的改变,这样在使用之前都要去内存里重新读取它的值,并告诉编译器不要随意对变量做优化

用到场合:并行设备的硬件寄存器(如状态寄存器),一个中断服务子程序会访问到的非自动变量,多线程应用中被几个任务共享的变量 

4.static作用

a:在函数体中,一个被声明为静态的变量在这一函数被调用过程中维持其值不变

b:在模块内(但在函数体外),一个被声明为静态变量的变量,可以被这个模块内的所有函数使用,但不能被模块外的函数使用,它是一个本地的全局变量,

c:在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用,那就是这个函数被限制在声明它模块的本地范围内使用后注问题:static全局变量与普通的全局变量有何不同?static局部变量和普通局部变量有何区别?static函数与普通函数有什么区别?

答:static全局变量只初始化一次,防止在其它文件单元中被引用;static局部变量只被初始化一次,下一次依据上一次结果值;static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

5.关键字const是什么含义?

答案一:

a:它可以定义const常量

b:const可以修饰函数的参数,返回值,甚至是函数的定义体,被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。

答案二:

const意味着只读

如:int const *p  指向常整型的指针;

int *const p 指向整型的常指针

int *const *p 指向常整型的常指针  或者等同于const int * const p

a:关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多于的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的)

b:通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码

c:合理地使用关键字const可以使编译器很自然的保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

6.对变量或寄存器进行位操作

给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其他位不变。

代码如下:

#define BIT3 (0x1<<3)

static int a;

void set_bit3(void)

{

a|=BIT3;

}

void clear_bit3(void)

{

a&=~BIT3;

7.用C语言实现大小端的测试

void checkcpu()

{

  union{

    int a;

    char b;

  }c;

c.a=1;

if(c.b==1)

printf("xiaoduan");

else

printf("daduan");

}

8.引用与指针有什么区别?

a:引用必须初始化,指针不必

b:引用初始化不能改变,指针可以被改变

c:不存在指向空值的引用,但存在指向空值的指针

注:用const限定引用的目的是:用这种形式的引用不能通过引用对目标变量的值进行修改

形式为const 类型标识符 &引用名=目标变量名

eg:Example(const Example &x)

引用的主要目的:当参数传递的数据量较大时,用引用比用一般变量传递参数的效率和空间占有率较好

9.写出float,int ,bool类型与零的比较,假设变量为x

float:if(x>0.000001&&x<-0.000001)

int :if(x==0)

bool: if(x==false)

10.OSI七层网络协议,TCP/IP协议

OSI:物理层-数据链路层-网络层-传输层-会话层-表示层-应用层

TCP/IP:网络接口层-互连网络层-传输层-应用层

11.对于一个频繁使用的短小函数,在C语言与C++中分别用什么实现?

C中用宏定义,C++用inline

注:inline作用:当在程序中调用一个内联函数时,是将该函数的代码直接插入到调用点,然后执行该段代码,所以在调用过程中不存在程序的跳转与返回问题,而对于普通函数的调用,程序是从主调函数点转去执行被调函数,待被调函数执行完毕后,再返回到主调函数的调用点的下一语句继续执行。从调用机理看,内联函数可以加快程序代码的执行速度和效率,减少调用开销。但这是以增加程序代码为代价来求得速度的。

12.堆与栈的区别

Heap是堆,Stack是栈;

Stack的空间由操作系统自动分配/释放,Heap上的空间是手动分配/释放;

C中的malloc函数分配的内存空间在堆上,C++对应的是new操作符;

程序在编译期间对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行;

13.用宏定义写出swap(x,y);

#define swap(x,y)/

x=x+y;/

y=x-y;/

x=x-y;

14.用define声明一个常数,用以表明1年中有多少秒 

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

15.写出宏MIN,这个宏输入两个参数并返回较小的一个 

#define MIN(A,B) (A<B)?A:B

16.const的作用

const 限定一个数据为只读属性。

(1)const char p; 限定变量 p 为只读。

(2)const char *p; p 为一个指向 char 类型的指针,const 限定 p 指向的数据为只读。所以 *p 的值不能被修改,而指针变量 p 本身的值可以被修改。

(3)char * const p; 限定此指针变量为只读,所以p的值不能被修改,而 *p 的值可以被修改。

(4)const char *const p; 者皆限定为只读,不能修改。

一个指向指针的指针,它指向的指针是指向一个整型数 int **a;

一个有10个指针的数组,该指针是指向一个整型数的 int *a[10];

一个指向有10个整型数数组的指针 int (*a)[10];

17.文件操作函数

ftell() 函数用于得到文件位置指针当前位置相对于文件首的偏移字节数;

fseek() 函数用于设置文件指针的位置;

rewind() 函数用于将文件内部的位置指针重新指向一个流(数据流/文件)的开头;

ferror() 函数可以用于检查调用输入输出函数时出现的错误。

18.结构体的内存分配

结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐。

原则1 数据成员对齐规则: 结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。

原则2 结构体作为成员: 如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)

原则3 收尾工作: 结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

不同系统下数据类型的字节大小

int (*(*p)[10])(int *)

先看未定义标识符p,p的左边是*,*p表示一个指针,跳出括号,由于[ ]的结合性大于*,所以*p指向一个大小为10的数组,即(*p)[10]。左边又有一个*号,修释数组的元素,*(*p)[10]表示*p指向一个大小为10的数组,且每个数组的元素为一个指针。跳出括号,根据右边(int *)可以判断(*(*p)[10])是一个函数指针,该函数的参数是int*,返回值是int。

19.结构体和联合的区别

(1) 联合和结构体都是由多个不同的数据类型成员组成,但在任何同一时刻,联合只存放了一个被选中的成员,而结构体的所有成员都存在。   

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

结构体中各成员都有自己的内存空间,是同时共存的,长度是所有成员的和。考虑内存对齐。

联合体中所有的成员只有一个内存空间,不同时刻储存不同类型的值,长度是它最长成员的长度。

20.fopen(fname,"w") 函数的打开方式

"r" 以“只读”方式打开文件。只允许读取,不允许写入。文件必须存在,否则打开失败。

"w" 以“写入”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。

"a" 以“追加”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。

"r+" 以“读写”方式打开文件。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败。

"w+" 以“写入/更新”方式打开文件,相当于w和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。

"a+" 以“追加/更新”方式打开文件,相当于a和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。

21.BBS 数据段 代码段 堆栈

BSS段:存放程序中未初始化的全局变量的一块内存区域,BSS段属于静态内存分配。

数据段:存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

代码段:存放程序执行代码的一块内存区域。

堆(heap):存放进程运行中被动态分配的内存段,内存手动申请手动释放

栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。内存自动申请自动释放

22.请问一下代码是否有问题,如果有问题请指出,没问题运行结果是什么?

Char *pt=”AAA”;

Printf(“%s”,pt); //输出为 AAA

*pt=’B’;

Printf(“%s”,pt); //出错 (段错,核心已转存)

pt=”BBB”;

Printf(“%s”,pt); //输出为 BBB

答”AAA”为字符串常量,编译后放置在内存区的只读区域,只读区域不允许修改,指针指向地址的内容不允许修改,但指针的指向可以修改。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值