嵌入式linux面试题解析(二)——C语言部分三

1、下面的程序会出现什么结果
#include
#include

#include
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
    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

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

low="mid+1;

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、对于共用体的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的