嵌入式软件工程师笔试题

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

2 . 写一个 "标准"宏 MIN ,这个宏输入两个参数并返回较小的一个。 
#define MIN(A,B)((A) <= (B) ? (A) : (B)) 

已知一个数组table,用一个宏定义,求出数据的元素个数。
参考答案:#define NTBL
#define NTBL (sizeof(table)/sizeof(table[0]))

3. 预处理器标识 #error的目的是什么?
不知道


4. 嵌入式系统中经常要用到无限循环,你怎么样用 C编写死循环呢? 这个问题用几个解决方案。我首选的方案是: 
while(1) { ?} 
一些程序员更喜欢如下方案: for(;;) { ?}


5. 用变量 a给出下面的定义 
a) 一个整型数( An integer) 
b)一个指向整型数的指针( A pointer to an integer) 
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r 
d)一个有 10个整型数的数组( An array of 10 integers) 
e)一个有 10个指针的数组,该指针是指向一个整型数的。( An array of 10 pointers to integers) 
f) 一个指向有 10个整型数数组的指针( A pointer to an array of 10 integers) 
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数( A pointer to a function that takes an integer as an argument and returns an integer) 
h)一个有 10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions t hat take an integer argument and return an integer ) 答案是: 
a) int a; // An integer 
b) int *a; // A pointer to an integer 
c) int **a; // A pointer to a pointer to an integer d) int a[10]; // An array of 10 integers 
e) int *a[10]; // An array of 10 pointers to integers 
f) int (*a)[10]; // A pointer to an array of 10 integers 
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer 
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer 


6. 关键字 static的作用是什么? 
这个简单的问题很少有人能回答完全。
在 C语言中,关键字 static有三个明显的作用:
在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变 量。 
在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

7.关键字 const有什么含意?
只读
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”

const int a; a是一个常整型数
int const a; a是一个常整型数
const int *a; a是一个指向常整型数的指针
int * const a; a是一个指向整型数的常指针
int const * a const;  a是一个指向常整型数的常指针

8. 关键字 volatile有什么含意 ?并给出三个不同的例子。
一个定义为 volatile的变量是说这变量可能会被意想不到地改变
并行设备的硬件寄存器(如:状态寄存器) 
一个中断服务子程序中会访问到的非自动变量 (Non-automatic variables)
多线程应用中被几个任务共享的变量


9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量 a,写两段代码,第一个设置 a的 bit 3,第二个清除 a 的 bit 3。
#define BIT3 (0x1 << 3) static int a; 
void set_bit3(void) { a |= BIT3; } 
void clear_bit3(void) { a &= ~BIT3; 
}


10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为 0x67a9的整型变量的值为 0xaa6
int *ptr; 
ptr = (int *)0x67a9;
*ptr = 0xaa55;

11. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展 ―让标准 C支持中断。具代表事实是,产生了一个新的关键 
字__interrupt。下面的代码就使用了 __interrupt关键字去定义了一个中断服务子程序 (ISR),请评论一下这段代码的。 
__interrupt double compute_area (double radius) { 
double area = PI * radius * radius; printf(" Area = %f", area); return area; } 
这个函数有太多的错误了,以至让人不知从何说起了: 
ISR不能返回一个值。如果你不懂这个,那么你不会被雇用的。 
ISR不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。 
在许多的处理器 /编译器中,浮点一般都是不可重入的。有些处理器 /编译器需要让额处的寄存器入栈,有些处理器 /编译器就是不允许在 IS 
R中做浮点运算。此外, ISR应该是短而有效率的,在 ISR中做浮点运算是不明智的。
与第三点一脉相承, printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点

12 . 下面的代码输出是什么,为什么? void foo(void) { 
unsigned int a = 6; int b = -20; 
(a+b > 6) ? puts("> 6") : puts("<= 6"); }

 C语言中的整数自动转换原则
当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。


15 Typedef 在 C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。
例如,思考一下下面的例子: 
#define dPS struct s * 
typedef struct s * tPS;


16 . C语言同意一些令人震惊的结构 ,下面的结构是合法的吗,如果是它做些什么? 
int a = 5, b = 7, c; 
c = a+++b; 
就近原则


17 堆栈
int a = 0;全局初始化区
char *p1;全局未初始化区
main()
{
int b;栈
char s[] ="abc";栈
char *p2;栈
char *p3 ="123456"; 123456在常量区,p3在栈上。
static int c =0;全局(静态)初始化区
p1 = (char*)malloc(10);
p2 = (char*)malloc(20);分配得来得10和20字节的区域就在堆区。
strcpy(p1,"123456"); 123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。


18 什么是野指针?产生的原因?
“野指针”不是NULL指针,是指向“垃圾”内存(不可用内存)的指针。“野指针”是很危险的,if无法判断一个指针是正常指针还是“野指针”。有个良好的编程习惯是避免“野指针”的唯一方法。
野指针的成因主要有三种:
一、指针变量没有被初始化。指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
三、指针操作超越了变量的作用范围。比如不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。比如说某个地址的生命期,使用一个没有生命期的指针是非常危险的。


19 sizeof和strlen区别
sizeof
sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组、指针、类型、对象、函数等。它的功能是:获得保证能容纳实现所建立的最大对象的字节大小。
strlen
strlen(...)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,实际上数组就退化成指针了。
它的功能是:返回字符串的长度

某32位系统下, C++程序,请计算sizeof 的值(5分).
char str[] = “http://www.ibegroup.com/”
char *p = str ;
int n = 10;
请计算
sizeof (str ) = ?(1)
sizeof ( p ) = ?(2)
sizeof ( n ) = ?(3)
void Foo ( char str[100]){
请计算
sizeof( str ) = ?(4)
}
void *p = malloc( 100 );
请计算
sizeof ( p ) = ?(5)
答:(1)25 (2)4 (3) 4 (4)4 (5)4

20
char iArr[10]={0,1,2,3,4,5,6,7,8,9};
short int *pVal = NULL;
pVal = (short int *)(iArr+2);
short int tVal = *pVal;

请问:Intel CPU的计算机中:tVal = ?

char iArr[10]={0,1,2,3,4,5,6,7,8,9};
short int *pVal = NULL;
pVal = (short int *)(iArr+2); //pVal和(iArr+2)都指向数组iArr的的3个元素2的地址
short int tVal = *pVal; //pVal指向的地址的内容(按字节)是:0x02,0x03,0x04,0x05

由于tVal和pVal分别是short类型的变量和指针
而Intel CPU的对short双字节的存放是:高字节在后,低字节在前
所以,tVal=*pVal=0x02+(0x03<<8)=0x0302=77

21 写出strcpy,strcmp,strlen,memcpy函数源码的实现。
char * strcpy( char*strDest, const char *strSrc )
{
assert( (strDest !=NULL) && (strSrc != NULL) );
char *address =strDest;
while( (*strDest++= * strSrc++) !=‘’ );
return address;
}

int strlen( const char *str ) //输入参数const
{
assert(strt != NULL); //断言字符串地址非0
intlen;
while( (*str++) !='' )
{
len++;
}
return len;
}

内存区域相对位置和重叠关系 //不知道两个指针的类型,不可以这样自加
void* mymemcpy( void *dest, const void *src, size_t count )
{
char *ret;
char *dst_t;
char *src_t;

ret = (char *)dst;


if ((unsigned char*)dst <= (unsigned char*)src|| (unsigned char *)dst >= ((unsigned char *)src + count))
{ //Non-Overlapping Buffers,copy from lower addresses to higher addresse

dst_t = (char *)dst;
src_t = (char *)src;

while (count--)
{
*dst_t++ = *src_t++;
}

}else
{//Overlapping Buffers,copy from higher addresses to lower addresses

dst_t = (char *)dst + count - 1;
src_t = (char *)src + count - 1;

while (count--)
{
*dst_t-- = *src_t--;

}
}

return(ret);
}


int main( void )
{
char str[] = "0123456789";
mymemcpy( str+1, str+0, 9 );
cout << str << endl;

system( "Pause" );
return 0;
}

char * __cdecl strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}

int strcmp(char *str1,char *str2)

{

if(*str1==‘’||*str2==’’) return;

while(*str1!=’’&&*str2!=’’&&*str1==*str2)

{

str1++;

str2++;

}

if(*str1==*str2)

return 1;

else return 0;

}

}
22 请写一个C函数,判断大小端。
int checkCPU()
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return (c.b == 1); 小端
}
}

23 与“零值”比较
分别给出BOOL,int,float,指针变量与“零值”比较的 if语句(假设变量名为var)
解答:
BOOL 型变量:if(!var)
int型变量:if(var==0)
float 型变量:
const floatEPSINON = 0.00001;
if ((x >= -EPSINON) && (x <= EPSINON)
指针变量:if(var==NULL)

24 对齐方式
·使用伪指令#pragma pack (n),编译器将按照n 个字节对齐;
·使用伪指令#pragma pack (),取消自定义字节对齐方式。

25 不是使用变量,调换两个变量的值
a = a + b;
b = a - b;
a = a - b;
或者:
a = a ^ b;
b = a ^ b;
a = a ^ b;

26
(1).Void GetMemory(char **p, int num){
*p = (char *)malloc(num);
}
void Test(void){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
请问运行Test 函数会有什么样的结果?
答:输出“hello”
(2). void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL){
strcpy(str, “world”);
printf(str);
}
}
请问运行Test 函数会有什么样的结果?
答:输出“world”
(3). char *GetMemory(void){
char p[] = "hello world";
return p;
}
void Test(void){
char *str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test 函数会有什么样的结果?
答:无效的指针,输出不确定

原文地址:https://www.cnblogs.com/gjianw217/p/5272489.html