嵌入式笔试面试题(10)----修饰符(define typedef static 等)

1、#include "stdafx.h"

#define SQR(X) X*X
int main(int argc, char* argv[])
{
  int a = 10;
  int k = 2;
  int m = 1;
  a /= SQR(k+m)/SQR(k+m); 
  printf("%d\n",a); 
  return 0;//1


2、const 符号常量;
(1)const char *p
(2)char const *p
(3)char * const p
说明上面三种描述的区别;

(1)P可变,p指向内容不可变;

(2)P可变,p指向内容不可变;

(3)P不可变,p指向内容可变;

3、static变量和static 函数各有什么特点?

Static变量在函数中修饰局部变量,该函数调用完成后,内存不被释放,延长变量生命周期;

Static修饰全局变量,该变量作用域只在本文本中有效,如果其他文本中有同名变量不会影响;

Static修饰函数,该函数作用域只在本文本中有效,其他文本中有同名函数互不影响;

4、请给出如下程序的结果

#define MAX_NUM 100+200

int nTemp = MAX_NUM*10;

Temp = 2100

5、宏的应用:

用宏声明一个常数,用来表示1年中有多少秒(忽略闰年的问题)

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

写一个宏:这个宏输入连个参数并返回较小的一个

用宏来选择不同的代码段

#define MIN(x,y)   (((x)<(y)) ?(x):(y))

 

6、关键字static const volatile 分别的作用是什么?

C语言中,关键字static有三个明显的作用:

1). 在函数体,一个被声明为静态的变量在这一函数被调用结束后不释放其存储空间。定义为static的局部变量的存储在全局区(静态区)而一般的局部变量存储在栈中。

2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

4). 类中定义的static数据成员属于所有该类对象共享,在内存中只占一份空间,而不是每个对象都分别为它保留一份空间。

5).类中定义为static的成员函数只能直接调用static数据成员,若要访问非静态数据成员,需要加上对象名。因为静态成员函数没有this指针。

 

关键字const是什么含意?

const意味着“只读”。

static和const关键字的作用可以从两个方面回答:一是和类的成员函数或者成员变量相关,二是不属于类的函数或者变量。

 

static关键字的作用:

1、函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此,其值在下次调用的时候仍然维持原始值, 作用域是声明该变量的代码段中

2、在模块内的static全局变量可以被模块内的所有函数访问,但是不能被模块外的其他函数访问。

3、在模块内的static函数只可以被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内。

4、在类中的static成员变量属于整个类所有,对类的所有对象只有一份拷贝。

5、在类中的static成员函数属于整个类所有,这个函数不接受this指针,因而只能访问类的static成员变量。

 

const关键字的作用:

1、想要阻止一个变量被改变,可以使用const关键字。在定义该const关键字是,通常要对它进行初始化,因为以后再也没有机会去改变它。

2、对于指针来说,可以指定指针本省为const,也可以指定指针所指向的数据为const,或者二者同时指定为const。

3、 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值。

4.对于类的成员函数,若指定为const,则表明其实一个常函数,不能修改类的成员变量。

5对于类的成员函数,有时候必须制定其返回值为const,以使得其返回值不能为左值。

 

关键字volatile有什么含意

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1). 并行设备的硬件寄存器(如:状态寄存器)

2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3). 多线程应用中被几个任务共享的变量

 

7、C语言中的变量根据其作用域来划分,分成几类?各自用在什么地方?

 

8、下面的大小分别是多少?//4

Short *p;  short (*p)();    int p;  int **p;   int (*P)(int,int)

 

9、在C语言中,只有在使用时才占用内存单元的变量,其存储类型是()

A.auto register          B.extern register

C.auto static            D.static register 

//register是指寄存器变量,寄存器是cpu的存储部件,即高速缓存,定义这个变量适用于频繁修改(使用)的全局变量,以加快运行速度,因为保存在寄存器中,省去了在内存中调用,定义这个变量后,不能取地址。

 

11、请写出BOOL,float ,指针变量与“零值”比较的if语句。

布尔变量与零值比较 
l 【规则4-3-1】不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。 
根据布尔类型的语义,零值为(记为FALSE),任何非零值都是(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如Visual   C++   将TRUE定义为1,而Visual   Basic则将TRUE定义为-1。 
假设布尔变量名字为flag,它与零值比较的标准if语句如下: 
if   (flag) //   表示flag为真 
if   (!flag) //   表示flag为假 
其它的用法都属于不良风格,例如: 
if   (flag   ==   TRUE) 
if   (flag   ==   1   ) 
if   (flag   ==   FALSE)       
if   (flag   ==   0) 

4.3.2   整型变量与零值比较 
l 【规则4-3-2】应当将整型变量用==!=直接与0比较。 
假设整型变量的名字为value,它与零值比较的标准if语句如下: 
if   (value   ==   0)       
if   (value   !=   0) 
不可模仿布尔变量的风格而写成 
if   (value) //   会让人误解   value是布尔变量 
if   (!value)    

4.3.3   浮点变量与零值比较 
l 【规则4-3-3】不可将浮点变量用==!=与任何数字比较。 
千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用==!=与数字比较,应该设法转化成> =<=形式。 
假设浮点变量的名字为x,应当将 
if   (x   ==   0.0)   //   隐含错误的比较 
转化为    
if   ((x> =-EPSINON)   &&   (x <=EPSINON)) 
其中EPSINON是允许的误差(即精度)。 

4.3.4   指针变量与零值比较 
l 【规则4-3-4】应当将指针变量用==!=与NULL比较。 
指针变量的零值是(记为NULL)。尽管NULL的值与0相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if语句如下: 
if   (p   ==   NULL) //   p与NULL显式比较,强调p是指针变量 
if   (p   !=   NULL) 
不要写成 
if   (p   ==   0)   //   容易让人误解p是整型变量 
if   (p   !=   0)             
或者 
if   (p) //   容易让人误解p是布尔变量 
if   (!p) 

4.3.5   对if语句的补充说明 
有时候我们可能会看到   if   (NULL   ==   p)   这样古怪的格式。不是程序写错了,是程序员为了防止将   if   (p   ==   NULL)   误写成   if   (p   =   NULL),而有意把p和NULL颠倒。编译器认为   if   (p   =   NULL)   是合法的,但是会指出   if   (NULL   =   p)是错误的,因为NULL不能被赋值。 
程序中有时会遇到if/else/return的组合,应该将如下不良风格的程序 
if   (condition) 
return   x; 
return   y; 
改写为 
if   (condition) 
{ 
return   x; 
} 
else 
{ 
return   y; 
} 
或者改写成更加简练的    
return   (condition   ?   x   :   y);

 

/*****************************************************************************************************************************************************************************************************/

分别给出BOOL,int,float,指针变量 与零值比较的 if 语句(假设变量名为var)

    解答:

    BOOL型变量:if(!var)

    int型变量: if(var==0)

    float型变量:

    const float EPSINON = 0.00001;

    if ((x >= - EPSINON) && (x <= EPSINON)

    指针变量:  if(var==NULL)

    剖析:

    考查对0值判断的内功,BOOL型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思。一般的,如果想让if判断一个变量的,应直接使用if(var)、if(!var),表明其为逻辑判断;如果用if判断一个数值型变量(short、int、long等),应该用if(var==0),表明是与0进行数值上的比较;而判断指针则适宜用if(var==NULL),这是一种很好的编程习惯。

    浮点型变量并不精确,所以不可将float变量用==!=与数字比较,应该设法转化成>=<=形式。如果写成if (x == 0.0),则判为错

12、实现将一个整形数据进行反序,如123变成321,如果int a=0xAD 78 怎么实现a的高地位反转?

#include <string.h>

#include <stdio.h>

Void main()

{

   char buf[1024]={0};

   int a=0,i=0;

  printf(please enter a string:);

gets(buf);

a=strlen(buf);

for(i=a-1;a>=0;a--)

{

  Printf(%c\n,buf[i]);

}

Putchar(‘\n’);

}

13、define和typedef的区别:

(1) 执行时间不同:

Define在编译之前,预处理阶段原样替换,简单机械的字符串替换;

Typedef在编译阶段有效,在编译阶段,有类型检查功能;

(2)功能差异:

           Typedef用来给类型的别名,常与struct结合使用;

           Define不只可以为类型取别名,还可以定义常量,变量,编译宏开关;

       3)作用域不同:

          Define没有作用域限制,只要之前预定过的宏,后面都可以使用;

          Typedef有作用域的限制;

14、以下程序的输出结果是________.

#include     <stdio.h>

int fun(int   x,int  y)

{

  static  int   m = 0;

  static  int   i = 2;

  i += m + 1;

  m = i + x + y;

  return  m;

}

void main()

{

  int   j = 4;

  int   m = 1;

  int   k;

  k = fun(j, m);

  printf("%d,", k);//8

  k=fun(j, m);

  printf("%d\n", k);//17

  return;

}

 

15、定义函数时,缺省函数的类型声明,则函数类型取缺省类型
A.void
B.char
C.float
D.int


16、若有宏定义:#define MOD(x,y) x%y  
则执行以下语句后的输出结果是
int a=13,b=94;
printf(″%d\n″,MOD(b,a+4));
A.5
B.7
C.9
D.11


17、设
#define N 3
#define Y(n) ((N+1)*n)
则表达式2*(N+Y(5+1))的值是
A.42
B.48
C.54
D.出错

 

19、如何判别一个数是unsigned。

 Int a;

Return (a>=0&&(~a>=0))    返回为0,为有符号数;

Unsigned  a;

Return (a>=0&&(~a>=0))    返回为1,为无符号数;

20、#Define replace_bit(a, v, m, n)实现bit的替换,如:

a = 0b0101010101101100,若v = 1101,m = 2, n = 4, 则从第m个bit起将n个bit替换为v,若v的bit个数大于n, 则取前n个。

 

21、将无符号int的后n位bit返回,用#Define_bit(value)实现,用宏定义实现。

 

22、unsigned int u;

for(u = 255;u >= 0; u - -)

{

Printf(u);

}

 

23、

unsigned a = 6;

int a = -20;

(a + b) > 6 ? puts(“>6”) : putts(“< 6”);

24、写两段代码,完成:

a的bit3设为1

a的bit3清零

Int a;

a | 1<<3;

a & ~(1<<3);

25、全局变量、局部变量、静态全局变量、静态局部变量的区别和引用方式。

初始化的全局变量在.data段,可以外部文本加extern引用;

未初始化的全局变量在.bss段,可以外部文本加extern引用;

静态全局变量区别是不能在外部文件引用;

 

局部变量在运行时,栈区分配空间;

静态局部变量在静态区分配空间,函数调用后内存不释放;

26、#define test struct

typedef struct test哪个更好

 

27、以下代码的输出结果是

#include <stdio.h>

#define SQR(x) (x*x)

void main

{

int a, b = 3;

a = SQR(b + 2);

printf(“/n%d”,a);

}//11

 

char *a 与char a[] 的区别

char *a = "hello" 中的a是指向第一个字符‘a'的一个指针

char a[20] = "hello" 中数组名a也是执行数组第一个字符‘h’的指针

但二者并不相同

看实例:把两个字符串相加:

 

结果:

 

对比:

 

结果:

 

把字符串加到指针所指的字串上去,出现段错误,本质原因:*d="0123456789"存放在常量区,是无法修的。而数组是存放在中,是可以修改的。两者区别如下:

. ”读“ ”写“ 能力

· char *a = "abcd";  此时"abcd"存放在常量区。通过指针只可以访问字符串常量,而不可以改变它。

· char a[20] = "abcd"; 此时 "abcd"存放在栈。可以通过指针去访问和修改数组内容。

. 赋值时刻

· char *a = "abcd"; 是在编译时就确定了(因为为常量)。

· char a[20] = "abcd"; 在运行时确定

. 存取效率

· char *a = "abcd"; 存于静态存储区。在上的数组比指针所指向字符串快。因此慢

· char a[20] = "abcd"; 存于栈上。快

另外注意:

char a[] = "01234",虽然没有指明字符串的长度,但是此时系统已经开好了,就是大小为6-----'0' '1' '2' '3' '4' '5' '\0',(注意strlen(a)是不计‘\0’)

看一结构中出现的同样的问题:

这样红色部分在调用Init函数时会出现“Segment Default", 因为此时 指针n是静态的,只有“读”的本事,不可以改变。

 

内存分配方式
内存分配有三种:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。

1. 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

2. 栈区:在执行函数时,函数(包括main函数)内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(任何变量都处于站区,例如int a[] = {1, 2},变量a处于栈区。数组的内容也存在于栈区。)

3. 堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,并立即将指针置位NULL,防止产生野指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屁小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值