嵌入式linux面試題解析(二)——C語言部分三

1、下面的程序會出現什么結果
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
void getmemory(char *p)
{
????p=(char *) malloc(100);
????strcpy(p,”hello world”);
}
int main( )
{
????char *str=NULL;
????getmemory(str);
????printf(“%s/n”,str);
????free(str);
????return 0;
}
程序崩潰,getmemory中的malloc 不能返回動態內存, free()對str操作很危險

?

2、(void *)ptr 和 (*(void**))ptr的結果是否相同?
答:ptr為同一個指針
(void *)ptr 和 (*(void**))ptr值是相同的

?

3、對絕對地址0×100000賦值且想讓程序跳轉到絕對地址是0×100000去執行
(unsigned int*)0×100000 = 1234;
首先要將0×100000強制轉換成函數指針,即:
(void (*)())0×100000
然后再調用它:
*((void (*)())0×100000)();
用typedef可以看得更直觀些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0×100000)();

?

4、下面的函數實現在一個數上加一個數,有什么錯誤?請改正。
int add_n ( int n )
{
????static int i = 100;
????i += n;
????return i;
}
????當你第二次調用時得不到正確的結果,難道你寫個函數就是為了調用一次?問題就出在 static上


5、下面這個程序執行后會有什么錯誤或者效果:
#define MAX 255
int main()
{
????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了..無限循環下去.

?

6、請問一下程序將輸出什么結果?
char *RetMenory(void)
{
????char p[] = “hellow world”;
????return p;
}
void Test(void)
{
????char *str = NULL;
????str = RetMemory();
????printf(str);
}
????RetMenory執行完畢,p資源被回收,指向未知地址。返回地址,str的內容應是不可預測的, 打印的應該是str的地址

?

7、對下面程序進行分析
void test2()
{
????char string[10], str1[10];
????int i;
????for(i=0; i<10; i++)
????{
????????str1[i] = 'a';
????}
????strcpy( string, str1 );
}
解答:

字符數組str1不能在數組內結束

strcpy(string, str1)調用使得從str1內存起復制到string內存起所復制的字節數具有不確定性

指出庫函數strcpy工作方式

str1不能在數組內結束:因為str1的存儲為:{a,a,a,a,a,a,a,a,a,a},沒有'\0'(字符串結束符),所以不能結束
strcpy( char *s1,char *s2)他的工作原理是,掃描s2指向的內存,逐個字符付到s1所指向的內存,直到碰到'\0',因為str1結尾沒有'\0',所以具有不確定性,不知道他后面還會付什么東東。
正確應如下
void test2()
{
????char string[10], str1[10];
????int i;
????for(i=0; i<9; i++)
????{
????????str1[i] = 'a'+i; //把abcdefghi賦值給字符數組
????}
????str[i]='\0';//加上結束符
????strcpy( string, str1 );
}

?

8、分析下列代碼輸出的值
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++)+=123;
printf(“ %d %d ”, *ptr, *(++ptr));
輸出:8 8
過程:對于*(ptr++)+=123;先做加法6+123,然后++,指針指向7;對于printf(“ %d %d ”, *ptr, *(++ptr));從后往前執行,指針先++,指向8,然后輸出8,緊接著再輸出8

?

9、分析下面的代碼:
char *a = "hello";
char *b = "hello";
if(a= =b)
????printf("YES");
else
????printf("NO");
輸出YES

"hello"是一個常量字符串位于靜態存儲區,在程序生命期內恒定不變a和b同時指向同一個hello的。

?

10、已知strcpy函數的原型是:
char * strcpy(char * strDest,const char * strSrc);
不調用庫函數,實現strcpy函數。
解釋為什么要返回char *。
解答
strcpy實現代碼

char * strcpy( char *strDest, const char *strSrc )
{
 assert( (strDest != NULL) && (strSrc != NULL) );
 char *address = strDest;
 while( (*strDest++ = * strSrc++) != '’ );
  return address;
}

?

11、判斷一個字符串是不是回文
int IsReverseStr(char *aStr)
{
????int i,j;
????int found=1;
????if(aStr==NULL)
????????return -1;
????j=strlen(aStr);
????for(i=0;i<j; i++)
????if(*(aStr+i)!=*(aStr+j-i-1))
????{
????????found=0;
????????break;
????}
????return found;
}

?

12、寫一個函數比較兩個字符串str1和str2的大小,若相等返回0,若str1大于
str2返回1,若str1小于str2返回-1
int strcmp ( const char * src,const char * dst)
{
????int ret = 0 ;
????while( ! (ret = *(unsigned char *)src – *(unsigned char *)dst) && *dst)
????{
????????++src;
????????++dst;
????}
????if ( ret < 0 )
????????ret = -1 ;
????else if ( ret > 0 )
????????ret = 1 ;
????return( ret );

}


13、給定字符串A和B,輸出A和B中的最大公共子串。
比如A="aocdfe" B="pmcdfa" 則輸出"cdf"
*/
//Author: azhen
#include
#include
#include

char *commanstring(char shortstring[], char longstring[])
{
????int i, j;

?char *substring=malloc(256);

?if(strstr(longstring, shortstring)!=NULL)

return shortstring;

????for(i=strlen(shortstring)-1;i>0; i–) //否則,開始循環計算
????{
????????for(j=0; j<=strlen(shortstring)-i; j++)

?{
????????????memcpy(substring, &shortstring[j], i);
????????????substring[i]='\0';
????????????if(strstr(longstring, substring)!=NULL)
????????????return substring;
????????}
????}
????return NULL;
}

int main()
{
????char *str1=malloc(256);
????char *str2=malloc(256);
????char *comman=NULL;

?gets(str1);
????gets(str2);

?if(strlen(str1)>strlen(str2)) //將短的字符串放前面
????????comman=commanstring(str2, str1);
????else
????????comman=commanstring(str1, str2);

????printf(“the longest comman string is: %s\n”, comman);
}


14、編寫一個 C 函數,該函數在一個字符串中找到可能的最長的子字符串,且該字符串是由同一字符組成的。
char * search(char *cpSource, char ch)
{
????char *cpTemp=NULL, *cpDest=NULL;
????int iTemp, iCount=0;
????while(*cpSource)
????{
????????if(*cpSource == ch)
????????{
????????????iTemp = 0;
????????????cpTemp = cpSource;
????????????while(*cpSource == ch)
????????????????++iTemp, ++cpSource;
????????????if(iTemp > iCount)
????????????????iCount = iTemp, cpDest = cpTemp;
????????????if(!*cpSource)
????????????????break;
????????}
????++cpSource;
????}
????return cpDest;
}

?

15、不用庫函數,用C語言實現將一整型數字轉化為字符串
int getlen(char *s)

{
????int n;
????for(n = 0; *s != '\0'; s++)
????????n++;
????return n;
}
void reverse(char s[])
{
????int c,i,j;
????for(i = 0,j = getlen(s) - 1; i < j; i++,j--)

{
????????c = s[i];
????????s[i] = s[j];
????????s[j] = c;
????}
}
void itoa(int n,char s[])
{
????int i,sign;
????if((sign = n) < 0)
????n = -n;
????i = 0;
????do{/*以反序生成數字*/
????????s[i++] = n%10 + '0';/*get next number*/
????}while((n /= 10) > 0);/*delete the number*/

?if(sign < 0)
????????s[i++] = '-';

??? s[i] = '\0';
????reverse(s);
}


16、請說出const與#define 相比,有何優點?
答:const作用:定義常量、修飾函數參數、修飾函數返回值三個作用。被Const修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。
A、const常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查。而對后者只進行字符替換,沒有類型安全檢查,并且在字符替換可能會產生意料不到的錯誤。
B、有些集成化的調試工具可以對const 常量進行調試,但是不能對宏常量進行調試。

?

17、編寫用C語言實現的求n階階乘問題的遞歸算法:

答:

long int fact(int n)
{

????if(n==0||n==1)

?? ????return 1;

????else

?????? return n*fact(n-1);

}

?

18、二分查找算法:

A遞歸方法實現:

int BSearch(elemtype a[],elemtype x,int low,int high)

/*在下為low,上界為high的數組a中折半查找數據元素x*/

{

int mid;

if(low>high)

return -1;

mid=(low+high)/2;

if(x?==?a[mid])

return mid;

?????? if(x<a[mid])

return(bsearch(a,x,low,mid-1));

else

return(BSearch(a,x,mid+1,high));

}

B、非遞歸方法實現:

int BSearch(elemtype a[],keytype key,int n)

{

int low,high,mid;

low=0;high=n-1;

while(low<=high)

{

mid=(low+high)/2;

if(a[mid].key==key)

return mid;

else if(a[mid].key<key)

low="mid+1;</font">

else

high=mid-1;

}

return -1;

}

?

19、遞歸計算如下遞歸函數的值(斐波拉契)

f(1)=1

f(2)=1

f(n)=f(n-1)+f(n-2) n>2

解:

A、非遞歸算法

int f(int n)

{

int i,s,s1,s2;

s1=1;/*s1用于保存f(n-1)的值*/

s2=1;/*s2用于保存f(n-2)的值*/

s=1;

for(i=3;i<=n;i++)

{

s=s1+s2;

s2=s1;

?? s1=s;

}

return(s);

}

B、遞歸算法

int f(int n)

{

if(n==1||n==2)

?? ????????rerurn 1;

?????? else

?? ????????return f(n-1)+f(n-2);

}


20、如何判斷一段程序是由C 編譯程序還是由C++編譯程序編譯的?
答:

#ifdef __cplusplus
cout<<"c++";
#else
cout<<"c";
#endif

?

21、結構與共用體有和區別?
答:

?A、結構和共用體都是由多個不同的數據類型成員組成, 但在任何同一時刻, 共用體中只存放了一個被選中的成員(所有成員共用一塊地址空間), 而結構的所有成員都存在(不同成員的存放地址不同)。
????B、對于共用體的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了, 而對于結構的不同成員賦值是互不影響的