1. 關鍵字volatile有什麼含意 并給出三個不同的例子。
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精确地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用儲存在寄存器裡的備份。下面是volatile變量的幾個例子:
1). 并行裝置的硬體寄存器(如:狀态寄存器)
2). 一個中斷服務子程式中會通路到的非自動變量(Non-automatic variables)
3). 多線程應用中被幾個任務共享的變量
2, 一個指針可以是volatile 嗎?解釋為什麼。
2). 是的。盡管這并不很常見。一個例子是當一個中服務子程式修該一個指向一個buffer的指針時。
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;
一些人喜歡為設定和清除值而定義一個掩碼同時定義一些說明常數,這也是可以接受的。我希望看到幾個要點:說明常數、|=和&=~操作。
11. 中斷是嵌入式系統中重要的組成部分,這導緻了很多編譯開發商提供一種擴充—讓标準C支援中斷。具代表事實是,産生了一個新的關鍵字 __interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一個中斷服務子程式(ISR),請評論一下這段代碼的。
__interrupt double compute_area (double radius)
double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
這個函數有太多的錯誤了,以至讓人不知從何說起了:
1). ISR 不能傳回一個值。如果你不懂這個,那麼你不會被雇用的。
2). ISR 不能傳遞參數。如果你沒有看到這一點,你被雇用的機會等同第一項。
3). 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點運算。此外,ISR應該是短而有效率的,在ISR中做浮點運算是不明智的。
4). 與第三點一脈相承,printf()經常有重入和性能上的問題。如果你丢掉了第三和第四點,我不會太為難你的。不用說,如果你能得到後兩點,那麼你的被雇用前景越來越光明了。
13. 評價下面的代碼片斷:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
對于一個int型不是16位的處理器為說,上面的代碼是不正确的。應編寫如下:
unsigned int compzero = ~0;
這一問題真正能揭露出應試者是否懂得處理器字長的重要性。在我的經驗裡,好的嵌入式程式員非常準确地明白硬體的細節和它的局限,然而PC機程式往往把硬體作為一個無法避免的煩惱。
到了這個階段,應試者或者完全垂頭喪氣了或者信心滿滿志在必得。如果顯然應試者不是很好,那麼這個測試就在這裡結束了。但如果顯然應試者做得不錯,那麼我就扔出下面的追加問題,這些問題是比較難的,我想僅僅非常優秀的應試者能做得不錯。提出這些問題,我希望更多看到應試者應付問題的方法,而不是答案。不管如何,你就當是這個娛樂吧…
1、線形表a、b為兩個有序升序的線形表,編寫一程式,使兩個有序線形表合并成一個有序升序線形表h;
答案在 請化大學 嚴銳敏《資料結構第二版》第二章例題,資料結構當中,這個叫做:兩路歸并排序
Linklist *unio(Linklist *p,Linklist *q){
linklist *R,*pa,*qa,*ra;
pa=p;
qa=q;
R=ra=p;
while(pa->next!=NULL&&qa->next!=NULL){
if(pa->data>qa->data){
ra->next=qa;
qa=qa->next;
else{
ra->next=pa;
pa=pa->next;
if(pa->next!=NULL)
if(qa->next!=NULL)
ra->next==qa;
return R;
3、用遞歸算法判斷數組a[N]是否為一個遞增數組。
遞歸的方法,記錄目前最大的,并且判斷目前的是否比這個還大,大則繼續,否則傳回false結束:
bool fun( int a[], int n )
if( n= =1 )
return true;
if( n= =2 )
return a[n-1] >= a[n-2];
return fun( a,n-1) && ( a[n-1] >= a[n-2] );
2.單連表的建立,把'a'--'z'26個字母插入到連表中,并且倒叙,還要列印!
方法1:
typedef struct val
{ int date_1;
struct val *next;
}*p;
void main(void)
{ char c;
for(c=122;c>=97;c--)
{ p.date=c;
p=p->next;
}
p.next=NULL;
方法2:
node *p = NULL;
node *q = NULL;
node *head = (node*)malloc(sizeof(node));
head->data = ' ';head->next=NULL;
node *first = (node*)malloc(sizeof(node));
first->data = 'a';first->next=NULL;head->next = first;
p = first;
int longth = 'z' - 'b';
int i=0;
while ( i<=longth )
node *temp = (node*)malloc(sizeof(node));
temp->data = 'b'+i;temp->next=NULL;q=temp;
head->next = temp; temp->next=p;p=q;
i++;
print(head);
一個遞規反向輸出字元串的例子,可謂是反序的經典例程.
void inverse(char *p)
if( *p = = '\0' )
return;
inverse( p+1 );
printf( "%c", *p );
int main(int argc, char *argv[])
inverse("abc\0");
return 0;
2。運作的結果為什麼等于15
#include "stdio.h"
#include "string.h"
void main()
char aa[10];
printf("%d",strlen(aa));
答案:sizeof()和初不初始化,沒有關系;strlen()和初始化有關。
6。int a,b,c 請寫函數實作C=a+b ,不可以改變資料類型,如将c改為long int,關鍵是如何處理溢出問題
答案:bool add (int a, int b,int *c)
*c=a+b;
return (a>0 && b>0 &&(*c<a || *c<b) || (a<0 && b<0 &&(*c>a || *c>b)));
7。分析:
struct bit
{ int a:3;
int b:2;
int c:3;
};
int main()
bit s;
char *c=(char*)&s;
cout<<sizeof(bit)<<endl;
*c=0x99;
cout << s.a <<endl <<s.b<<endl<<s.c<<endl;
int a=-1;
printf("%x",a);
return 0;
輸出為什麼是?
答案:4
1
-1
-4
ffffffff
因為0x99在記憶體中表示為 100 11 001 , a = 001, b = 11, c = 100(在vc環境中,一般是由右到左進行配置設定的)
當c為有符合數時, c = 100, 最高1為表示c為負數,負數在計算機用補碼表示,是以c = -4;同理
b = -1;
當c為有符合數時, c = 100,即 c = 4,同理 b = 3
9。下面這個程式執行後會有什麼錯誤或者效果:
#define MAX 255
unsigned char A[MAX],i; //i被定義為unsigned char
for (i=0;i<=MAX;i++)
A[i]=i;
答案:死循環加數組越界通路(C/C++不進行數組越界檢查)
MAX=255
數組A的下标範圍為:0..MAX-1,這是其一..
其二.當i循環到255時,循環内執行:
A[255]=255;
這句本身沒有問題..但是傳回for (i=0;i<=MAX;i++)語句時,
由于unsigned char的取值範圍在(0..255),i++以後i又為0了..無限循環下去.
2.對于一個頻繁使用的短小函數,在C語言中應用什麼實作,在C++中應用什麼實作?
c用宏定義,c++用inline
6.軟體測試都有那些種類?
黑盒:針對系統功能的測試 白合:測試函數功能,各函數接口
- 程序和線程的差别。
線程是指程序内的一個執行單元,也是程序内的可排程實體.
與程序的差別:
(1)排程:線程作為排程和配置設定的基本機關,程序作為擁有資源的基本機關
(2)并發性:不僅程序之間可以并發執行,同一個程序的多個線程之間也可并發執行
(3)擁有資源:程序是擁有資源的一個獨-立機關,線程不擁有系統資源,但可以通路隸屬于程序的資源.
(4)系統開銷:在建立或撤消程序時,由于系統都要為之配置設定和回收資源,導緻系統的開銷明顯大于建立或撤消線程時的開銷。
11.程序死鎖的原因
資源競争及程序推進順序非法
12.死鎖的4個必要條件
互斥、請求保持、不可剝奪、環路
13.死鎖的處理
鴕鳥政策、預防政策、避免政策、檢測與解除死鎖
9.純虛函數如何定義?使用時應注意什麼?
virtual void f()=0;
是接口,子類必須要實作
2:int main()
{
int x=3;
printf("%d",x);
return 1;
}
問函數既然不會被其它函數調用,為什麼要傳回1?
mian中,c标準認為0表示成功,非0表示錯誤。具體的值是某中具體出錯資訊
- 要對絕對位址0x100000指派,我們可以用
(unsigned int*)0x100000 = 1234;
那麼要是想讓程式跳轉到絕對位址是0x100000去執行,應該怎麼做?
*((void (*)( ))0x100000 ) ( );
首先要将0x100000強制轉換成函數指針,即:
(void (*)())0x100000
然後再調用它:
*((void (*)())0x100000)();
用typedef可以看得更直覺些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
位域:
有些資訊在存儲時,并不需要占用一個完整的位元組,而隻需占幾個或一個二進制位。例如在存放一個開關量時,隻有0和1 兩種狀态,用一位二進位即可。為了節省存儲空間,并使處理簡便,C語言又提供了一種資料結構,稱為“位域”或“位段”。所謂“位域”是把一個位元組中的二進位劃分為幾個不同的區域,并說明每個區域的位數。每個域有一個域名,允許在程式中按域名進行操作。這樣就可以把幾個不同的對象用一個位元組的二進制位域來表示。一、位域的定義和位域變量的說明位域定義與結構定義相仿,其形式為:
struct 位域結構名
{ 位域清單 };
其中位域清單的形式為:類型說明符位域名:位域長度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
位域變量的說明與結構變量說明的方式相同。可采用先定義後說明,同時定義說明或者直接說明這三種方式。例如:
}data;
說明data為bs變量,共占兩個位元組。其中位域a占8位,位域b占2位,位域c占6位。對于位域的定義尚有以下幾點說明:
1. 一個位域必須存儲在同一個位元組中,不能跨兩個位元組。如一個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*從下一單元開始存放*/
unsigned c:4
}
在這個位域定義中,a占第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,占用4位,c占用4位。
2. 由于位域不允許跨兩個位元組,是以位域的長度不能大于一個位元組的長度,也就是說不能超過8位二進位。
3. 位域可以無位域名,這時它隻用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k
int a:1
int :2 /*該2位不能使用*/
int b:3
int c:2
從以上分析可以看出,位域在本質上就是一種結構類型,不過其成員是按二進位配置設定的。
二、位域的使用位域的使用和結構成員的使用相同,其一般形式為:位域變量名•位域名位域允許用各種格式輸出。
main(){
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
bit.a=1;
bit.b=7;
bit.c=15;
pri
1、頭檔案中的 ifndef/define/endif 幹什麼用?(5分)
答:防止該頭檔案被重複引用。
(2)strcpy能把strSrc的内容複制到strDest,為什麼還要char * 類型的傳回值?
答:為了實作鍊式表達式。
六、編寫類String的構造函數、析構函數和指派函數(25分)
已知類String的原型為:
class String
{
public:
String(const char *str = NULL); // 普通構造函數
String(const String &other); // 拷貝構造函數
~ String(void); // 析構函數
String & operate =(const String &other); // 指派函數
private:
char *m_data; // 用于儲存字元串
};
請編寫String的上述4個函數。
标準答案:
// String的析構函數
String::~String(void) // 3分
delete [] m_data;
// 由于m_data是内部資料類型,也可以寫成 delete m_data;
// String的普通構造函數
String::String(const char *str) // 6分
if(str==NULL)
{
m_data = new char[1]; // 若能加 NULL 判斷則更好
*m_data = ‘\0’;
}
else
int length = strlen(str);
m_data = new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, str);
}
// 拷貝構造函數
String::String(const String &other) // 3分
{
int length = strlen(other.m_data);
m_data = new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, other.m_data);
// 指派函數
String & String::operate =(const String &other) // 13分
// (1) 檢查自指派 // 4分
if(this == &other)
return *this;
// (2) 釋放原有的記憶體資源 // 3分
delete [] m_data;
// (3)配置設定新的記憶體資源,并複制内容 // 3分
m_data = new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, other.m_data);
// (4)傳回本對象的引用 // 3分
return *this;
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
來自為知筆記(Wiz)