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

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

时间: 2024-10-06 16:23:40

嵌入式linux面试题解析(二)——C语言部分三的相关文章

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

嵌入式linux面试题解析(二)--C语言部分二 1..h头文件中的ifndef/define/endif 的作用?    答:防止该头文件被重复引用. 2.#include 与 #include "file.h"的区别?    答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h. 3.描述实时系统的基本特性    答 :在特定时间内完成特定的任务,实时性与可靠性. 4.全局变量和局部变量在内存中是否有区别?如果有,是

嵌入式linux面试题解析(一)——ARM部分二

嵌入式linux面试题解析(一)--ARM部分二 1.描述一下嵌入式基于ROM的运行方式基于RAM的运行方式有什么区别. 基于RAM的运行方式:需要把硬盘和其他介质的代码先加载到ram中,加载过程中一般有重定位的操作: 基于ROM:没有上面的操作. 基于ROM:速度较基于RAM的慢,因为会有一个把变量,部分代码等从存储器(硬盘,flash)搬移到RAM的过程:可用RAM资源比基于RAM的多: 基于RAM:速度较基于ROM的快,可用RAM比基于ROM的少,因为所有的代码,数据都必须存放在RAM中.

嵌入式linux面试题解析(三)——Linux应用编程部分一

嵌入式linux面试题解析(三)--Linux应用编程部分一 1.TCP与UDP的区别 TCP:是面向连接的流传输控制协议,具有高可靠性,确保传输数据的正确性,有验证重发机制,不会出现丢失或乱序. UDP:是无连接的数据报服务,不对数据报进行检查与修改,无须等待对方的应答,会出现分组丢失.重复.乱序,但具有较好的实时性,UDP段结构比TCP的段结构简单,因此网络开销也小. 2.流量控制和拥塞控制 拥塞控制    网络拥塞现象是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致

嵌入式linux面试题

基础试题(C语言) 一.ANSI C/C++方面的知识 一.1.简答题.下面的题目必须全部答对才给分(20分): 1. 如何在C中初始化一个字符数组. char s[100]={' '}; 2. 如何在C中为一个数组分配空间. char s[10]; s=malloc(10*sizeof(char)); 3. 如何初始化一个指针数组. int *pt[10]={NULL}; 4. 如何定义一个有10个元素的整数型指针数组. int *pt[10]={NULL}; 5. s[10]的另外一种表达方

嵌入式 Linux进程间通信(十二)——多线程同步

嵌入式 Linux进程间通信(十二)--多线程同步 多线程编程中有三种线程同步机制:互斥锁.信号量.条件量.本文将使用生产者消费者问题编程实践三种线程同步方式. 生产者.消费者问题:生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费.消费者线程从缓冲区中获得物品,然后释放缓冲区.当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区.当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来. 一.互斥锁

嵌入式 Linux网络编程(二)——TCP编程模型

嵌入式 Linux网络编程(二)--TCP编程模型 一.TCP编程模型 TCP编程的一般模型如下图: TCP编程模型分为客户端和服务器端编程,两者编程流程如下: TCP服务器端编程流程: A.创建套接字: B.绑定套接字: C.设置套接字为监听模式,进入被动接受连接状态: D.接受请求,建立连接: E.读写数据: F.终止连接. TCP客户端编程流程: A.创建套接字: B.与远程服务器建立连接: C.读写数据: D.终止连接. 二.TCP迭代服务器编程模型 TCP循环服务器接受一个客户端的连接

嵌入式linux QT开发(二)——QT开发环境搭建

嵌入式linux QT开发(二)--QT开发环境搭建 一.Windows系统QT开发环境搭建 操作系统:Windows 7 QT Creator:qt-creator-win-opensource-2.4.1 QT SDK:qt-win-opensource-4.7.4-mingw 1.安装QT Creator 点击qt-creator-win-opensource-2.4.1源程序安装. 2.安装QT SDK 点击qt-win-opensource-4.7.4-mingw源程序安装. 选择mi

嵌入式 Linux系统编程(二)——文件描述符控制函数fcntl

嵌入式 Linux系统编程(二)--文件描述符控制函数fcntl 由于fcntl函数实在过于灵活和复杂,本文将fcntl函数从文件IO中单独列出来,便于详细解读.函数原型如下: #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ ); fcntl函数用于控制操作文件描述符fd,对文件描述符的控制操作由cmd控制命令来控制,arg参数为可选参数,是否需要arg参数取决于控制命令

.NET面试题解析(07)-SQL语言基础及数据库基本原理

  系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 本文内容涉及到基本SQL语法,数据的基本存储原理,数据库一些概念.数据优化等.抱砖引玉,权当一个综合复习! 常见面试题目: 0. 基本SQL语法题目,在 正文“基础SQL语法”中有13道题,这里就略过了. 1. 索引的作用?她的优点缺点是什么? 2. 介绍存储过程基本概念和 她的优缺点? 3. 使用索引有哪些需要注意的地方? 4. 索引碎片是如何产生的?有什么危害?又该如何处理? 5. 锁的目的是什么? 6.