嵌入式軟件工程師筆試題

1 . 用預處理指令 #define 聲明一個常數,用以代表 1年中有多少秒(忽略閏年問題) 
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)ULc++

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類型,以使得其返回值不爲「左值」app

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("\nArea = %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\0在常量區,p3在棧上。
static int c =0;全局(靜態)初始化區
p1 = (char*)malloc(10);
p2 = (char*)malloc(20);分配得來得10和20字節的區域就在堆區。
strcpy(p1,"123456"); 123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。


18 什麼是野指針?產生的緣由?
「野指針」不是NULL指針,是指向「垃圾」內存(不可用內存)的指針。「野指針」是很危險的,if沒法判斷一個指針是正常指針仍是「野指針」。有個良好的編程習慣是避免「野指針」的惟一方法。
野指針的成因主要有三種:
1、指針變量沒有被初始化。指針變量在建立的同時應當被初始化,要麼將指針設置爲NULL,要麼讓它指向合法的內存。
2、指針p被free或者delete以後,沒有置爲NULL,讓人誤覺得p是個合法的指針。
3、指針操做超越了變量的做用範圍。好比不要返回指向棧內存的指針或引用,由於棧內存在函數結束時會被釋放。好比說某個地址的生命期,使用一個沒有生命期的指針是很是危險的。


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++) !=‘\0’ );
return address;
}

int strlen( const char *str ) //輸入參數const
{
assert(strt != NULL); //斷言字符串地址非0
intlen;
while( (*str++) !='\0' )
{
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==‘\0’||*str2==’\0’) return;

while(*str1!=’\0’&&*str2!=’\0’&&*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 函數會有什麼樣的結果?答:無效的指針,輸出不肯定

相關文章
相關標籤/搜索