C语言笔试面试大全


    1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问�
题)
    #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
    我在这想看到几件事情:
    1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
    2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一�
年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
    3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,�
告诉编译器这个常数是的长整型数。
    4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的�
起点。记住,第一印象很重要。
    2. 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
    #define MIN(A,B) ((A) <= (B) (A) : (B))
    这个测试是为下面的目的而设的:
    1). 标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inlin�
e)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,
    对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
    2). 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能�
产生比if-then-else更优化的代码,了解这个用法是很重要的。
    3). 懂得在宏中小心地把参数用括号括起来
    4). 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什�
么事?
    least = MIN(*p++, b);
    3. 预处理器标识#error的目的是什么?停止编辑并输出错误信息
    如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆�
子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如�
果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。
    死循环(Infinite loops)
    4. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
    这个问题用几个解决方案。我首选的方案是:
    while(1)
    {
    }
    一些程序员更喜欢如下方案:
    for(;;)
    {
    }
    这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应�
试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的
    基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么�
。”这会给我留下一个坏印象。
    第三个方案是用 goto
    Loop:
    ⋯⋯
    goto Loop;
    应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事�
)或者他是一个想进入新领域的BASIC/FORTRAN程序员。
    数据声明(Data declarations)
    5. 用变量a给出下面的定义
    a) 一个整型数(An integer)
    b) 一个指向整型数的指针(A pointer to an integer)
page 1    c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a�
 pointer to an integer)
    d) 一个有10个整型数的数组(An array of 10 integers)
    e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 poi�
nters to integers)
    f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 intege�
rs)int (*a)[10]
    g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointe�
r to a function that takes an integer as an argument and returns an intege�
r)
    h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返�
回一个整型数( An array of ten pointers to functions that 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 ta�
ke an integer argument and return an integer
    人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说�
法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。
    但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被�
面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道
    所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面�
试者没有为这次面试做准备,那么他又能为什么出准备呢?
    Static
    6. 关键字static的作用是什么?
    这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的�
作用:
    1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变�

    2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函�
数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
    3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那�
就是,这个函数被限制在声明它的模块的本地范围内使用。
    大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人�
能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代�
码范围的好处和重要性。
    Const
    7.关键字const是什么含意?
    我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余�
者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译�
者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不�
能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。�
尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更�
详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问�
他一个附加的问题:下面的声明都是什么意思?
page 2    const int a;
    int const a;
    const int *a;
    int * const a;
    int const * a const;
    前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的�
指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数�
的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最�
后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修�
改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我�
留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是�
能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下�
的几下理由:
    1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声�
明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理�
其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程�
序员很少会留下的垃圾让别人来清理的。)
    2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码�

    3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参�
数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
    Volatile
    8. 关键字volatile有什么含意 并给出三个不同的例子。
    一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器�
就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都�
小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile�
变量的几个例子:
    1). 并行设备的硬件寄存器(如:状态寄存器)
    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)�
    3). 多线程应用中被几个任务共享的变量
    回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统�
程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所�
用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
    假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究�
一下,看一下这家伙是不是直正懂得volatile完全的重要性。
    1). 一个参数既可以是const还可以是volatile吗?解释为什么。
    2). 一个指针可以是volatile 吗?解释为什么。
    3). 下面的函数有什么错误:
    int square(volatile int *ptr)
    {
    return *ptr * *ptr;
    }
    下面是答案:
    1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到�
地改变。它是const因为程序不应该试图去修改它。
    2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一�
个buffer的指针时。
    3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,�
但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
    int square(volatile int *ptr)
    {
page 3    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
    }
    由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码�
可能返不是你所期望的平方值!正确的代码如下:
    long square(volatile int *ptr)
    {
    int a;
    a = *ptr;
    return a * a;
    }
    位操作(Bit manipulation)
    9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写�
两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持�
其它位不变。
    对这个问题有三种基本的反应
    1). 不知道如何下手。该被面者从没做过任何嵌入式系统的工作。
    2). 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在�
不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸�
看到 Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对�
我无用,因为我的编译器用其它的方式来实现bit fields的。从道德讲:永远不要让�
一个非嵌入式的家伙粘实际硬件的边。
    3). 用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应�
该被用到的方法。最佳的解决方案如下:
    #define BIT3 (0x1<<3)
    static int a;
    void set_bit3(void)
    {
    a |= BIT3;
    }
    void clear_bit3(void)
    {
    a &= ~BIT3;
    }
    一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以�
接受的。我希望看到几个要点:说明常数、|=和&=~操作。
    访问固定的内存位置(Accessing fixed memory locations)
    10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程�
中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的AN�
SI编译器。写代码去完成这一任务。
    这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecas�
t)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代�
码如下:
    int *ptr;
    ptr = (int *)0x67a9;
    *ptr = 0xaa55;
    一个较晦涩的方法是:
    *(int * const)(0x67a9) = 0xaa55;
    即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。
    中断(Interrupts)
page 4    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()经常有重入和性能上的问题。如果你丢掉了第�
三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前�
景越来越光明了。
    代码例子(Code examples)
    12 . 下面的代码输出是什么,为什么?
    void foo(void)
    {
    unsigned int a = 6;
    int b = -20;
    (a+b > 6) puts("> 6") : puts("<= 6");
    }
    这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得�
极少这些东西。不管如何,这无符号整型问题的答案是输出是“>6”。原因是当表达�
式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-2�
0变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频�
繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你�
也就到了得不到这份工作的边缘。
    13. 评价下面的代码片断:
    unsigned int zero = 0;
    unsigned int compzero = 0xFFFF;
    /*1's complement of zero */
    对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:�
    unsigned int compzero = ~0;
    这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好�
的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作�
为一个无法避免的烦恼。
    到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应�
试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我�
就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不�
错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何�
,你就当是这个娱乐吧⋯
    动态内存分配(Dynamic memory allocation)
    14. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态�
分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?
page 5    这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。�
这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远�
超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种�
虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么�

    char *ptr;
    if ((ptr = (char *)malloc(0)) == NULL)
    puts("Got a null pointer");
    else
    puts("Got a valid pointer");
    这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得�
到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是�
“Got a valid pointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想�
到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的�
基本原理更重要些。
    Typedef
    15. Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可�
以用预处理器做类似的事。例如,思考一下下面的例子:
    #define dPS struct s *
    typedef struct s * tPS;
    以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法�
更好呢?(如果有的话)为什么?
    这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的�
。答案是:typedef更好。思考下面的例子:
    dPS p1,p2;
    tPS p3,p4;
    第一个扩展为
    struct s * p1, p2;
    上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想�
要的。第二个例子正确地定义了p3 和p4 两个指针。
    晦涩的语法
    16. C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么�

    int a = 5, b = 7, c;
    c = a+++b;
    这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完�
全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问�
题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码�
被处理成:
    c = a++ + b;
    因此, 这段代码持行后a = 6, b = 7, c = 12。
    如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个�
当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性�
,代码的可修改性的好的话题
    今天早上的面试题9道,比较难,
    1、线形表a、b为两个有序升序的线形表,编写一程序,使两个有序线形表合并�
成一个有序升序线形表h;
    答案在 请化大学 严锐敏《数据结构第二版》第二章例题,数据结构当中,这个�
叫做:两路归并排序
    Linklist *unio(Linklist *p,Linklist *q){
    linklist *R,*pa,*qa,*ra;
    pa=p;
page 6    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)
    ra->next=pa;
    if(qa->next!=NULL)
    ra->next==qa;
    return R;
    }
    2、运用四色定理,为N个局域举行配色,颜色为1、2、3、4四种,另有数组adj�
[][N],如adj[i][j]=1则表示i区域与j区域相邻,数组color[N],如color[i]=1,表示�
i区域的颜色为1号颜色。
    四色填充
    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] );
    }
    4、编写算法,从10亿个浮点数当中,选出其中最大的10000个。
    用外部排序,在《数据结构》书上有
    《计算方法导论》在找到第n大的数的算法上加工
    5、编写一unix程序,防止僵尸进程的出现.
    同学的4道面试题,应聘的职位是搜索引擎工程师,后两道超级难,(希望大家�
多给一些算发)
    1.给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态�
内存dongtai,并且返回交集个数
    long jiaoji(long* a[],long b[],long* alength,long blength,long* dongt�
ai[])
    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--)
page 7    { 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);
    6.可怕的题目终于来了
    象搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前十条,我�
们每次输入的一个字符串为不超过255byte,内存使用只有1G,
    请描述思想,写出算发(c语言),空间和时间复杂度,
    7.国内的一些帖吧,如baidu,有几十万个主题,假设每一个主题都有上亿的跟帖�
子,怎么样设计这个系统速度最好,请描述思想,写出算发(c语言),空间和时间复�
杂度,
    #include string.h
    main(void)
    { char *src="hello,world";
    char *dest=NULL;
    dest=(char *)malloc(strlen(src));
    int len=strlen(str);
    char *d=dest;
    char *s=src[len];
    while(len--!=0)
    d++=s--;
    printf("%s",dest);
    }
    找出错误!!
    #include "string.h"
    #include "stdio.h"
    #include "malloc.h"
    main(void)
    { 
    char *src="hello,world";
    char *dest=NULL;
    dest=(char *)malloc(sizeof(char)*(strlen(src)+1));
page 8    int len=strlen(src);
    char *d=dest;
    char *s=src+len-1;
    while(len--!=0)
    *d++=*s--;
    *d='\0';
    printf("%s",dest);
    }
    intel c语言
    1。struct s1
    {
    int i: 8;
    int j: 4;
    int a: 3;
    double b;
    };
    struct s2
    {
    int i: 8;
    int j: 4;
    double b;
    int a:3;
    };
    printf("sizeof(s1)= %d\n", sizeof(s1));
    printf("sizeof(s2)= %d\n", sizeof(s2));
    答案:16, 24
    第一个struct s1
    {
    int i: 8;
    int j: 4;
    int a: 3;
    double b;
    };
    理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一�
个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,�
然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前�
总共是18位,折算过来是2字节2位的样子,由于double是8字节的,因此要在相对0要�
是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字�
节的位置了,因此,总共是16字节。
    第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数�
据的倍数
    编程题
    2。读文件file1.txt的内容(例如):
    12
    34
    56
    输出到file2.txt:
    56
    34
    12
    (逆序)
    答案:注意可增长数组的应用.
page 9    #include 
    #include  
    3。输出和为一个给定整数的所有组合
    例如n=5
    5=1+4;5=2+3(相加的数不能重复)
    则输出
    1,4;2,3。
    答案:
    #include 4。在对齐为4的情况下
    struct BBB
    {
    long num;
    char *name;
    short int data;
    char ha;
    short ba[5];
    }*p;
    p=0x1000000;
    p+0x200=;
    (Ulong)p+0x200=;
    (char*)p+0x200=;
    答案:假设在32位CPU上,
    sizeof(long) = 4 bytes
    sizeof(char *) = 4 bytes
    sizeof(short int) = sizeof(short) = 2 bytes
    sizeof(char) = 1 bytes
    int main(void)
    {
    unsigned long int i,j,k;
    printf("please input the number\n");
    scanf("%d",&i);
    if( i % 2 == 0)
    j = i / 2;
    else
    j = i / 2 + 1;
    printf("The result is \n");
    for(k = 0; k < j; k++)
    printf("%d = %d + %d\n",i,k,i - k);
    return 0;
    }
    #include 
    void main()
    {
    unsigned long int a,i=1;
    scanf("%d",&a);
    if(a%2==0)
    {
    for(i=1;i
    usingnamespacestd;
    intPartition (int*L,intlow,int high)
    {
    inttemp = L[low];
page 10    intpt = L[low];
    while (low < high)
    {
    while (low < high && L[high] >= pt)
    --high;
    L[low] = L[high];
    while (low < high && L[low] <= pt)
    ++low;
    L[low] = temp;
    }
    L[low] = temp;
    returnlow;
    }
    voidQSort (int*L,intlow,int high)
    {
    if (low < high)
    {
    intpl = Partition (L,low,high);
    QSort (L,low,pl - 1);
    QSort (L,pl + 1,high);
    }
    }
    intmain ()
    {
    intnarry[100],addr[100];
    intsum = 1,t;
    cout << "Input number:" << endl;
    cin >> t;
    while (t != -1)
    {
    narry[sum] = t;
    addr[sum - 1] = t;
    sum++;
    cin >> t;
    }
    sum -= 1;
    QSort (narry,1,sum);
    for (int i = 1; i <= sum;i++)
    cout << narry[i] << '\t';
    cout << endl;
    intk;
    cout << "Please input place you want:" << endl;
    cin >> k;
    intaa = 1;
    intkk = 0;
    for (;;)
    {
    if (aa == k)
    break;
    if (narry[kk] != narry[kk + 1])
    {
    aa += 1;
page 11    kk++;
    }
    }
    cout << "The NO." << k << "number is:" << narry[sum - kk] << endl;
    cout << "And it's place is:" ;
    for (i = 0;i < sum;i++)
    {
    if (addr[i] == narry[sum - kk])
    cout << i << '\t';
    }
    return0;
    }
    int main(void)
    {
    int MAX = 10;
    int *a = (int *)malloc(MAX * sizeof(int));
    int *b;
    FILE *fp1;
    FILE *fp2;
    fp1 = fopen("a.txt","r");
    if(fp1 == NULL)
    {printf("error1");
    exit(-1);
    }
    fp2 = fopen("b.txt","w");
    if(fp2 == NULL)
    {printf("error2");
    exit(-1);
    }
    inti = 0;
    int j = 0;
    while(fscanf(fp1,"%d",&a[i]) != EOF)
    {
    i++;
    j++;
    if(i >= MAX)
    {
    MAX = 2 * MAX;
    b = (int*)realloc(a,MAX * sizeof(int));
    if(b == NULL)
    {
    printf("error3");
    exit(-1);
    }
    a = b;
    }
    }
    for(;--j >= 0;)
    fprintf(fp2,"%d\n",a[j]);
    fclose(fp1);
    fclose(fp2);
    return 0;
page 12    }
    6。void g(int**);
    int main()
    {
    int line[10],i;
    int *p=line; 
    for (i=0;i<10;i++)
    {
    *p=i;
    g(&p);
    }
    for(i=0;i<10;i++)
    printf("%d\n",line[i]);
    return 0;
    }
    void g(int**p)
    {
    (**p)++;
    (*p)++;
    }
    输出?
    答案:1
    2 
    3 
    4 
    5 
    6 
    7 
    8 
    9 
    10这道题目不是很好理解,我们可以把题目g函数改为
    void g(int**s)
    {
    (**s)++;
    (*s)++;
    }
    这样不容易看混淆s就是一个形式参数,g(&p)输入的就是p的地址,这样有如下�
指向:*p-》p-》line调用函数时候,**s对应*p即数组中的数,*s对应p即数组数字�
的地址,这样就可以知道了(**s)++是line中的内容增加;(*s)++是地址增加。
    7。写出程序运行结果
    int sum(int a)
    {
    auto int c=0;
    static int b=3;
    c+=1;
    b+=2;
    return(a+b+c);
    }
    void main()
    {
    int I;
    int a=2;
page 13    for(I=0;I<5;I++)
    {
    printf("%d,", sum(a));
    }
    }
    答案:static会保存上次结果,记住这一点,剩下的自己写
    输出:8,10,12,14,16,
    8。int a[3];
    a[0]=0; a[1]=1; a[2]=2;
    int *p, *q;
    p=a;
    q=&a[2];
    则a[q-p]=a[2]
    答案:指针一次移动一个int但计数为1,p=a;q=a+2。
    1。分析下面的程序:
    void GetMemory(char **p,int num)
    {
    *p=(char *)malloc(num);
    } 
    int main()
    {
    char *str=NULL;
    GetMemory(&str,100);
    strcpy(str,"hello");
    free(str);
    if(str!=NULL)
    {
    strcpy(str,"world");
    } 
    printf("\n str is %s",str);
    getchar();
    } 
    问输出结果是什么?
    答案:输出str is world。
    free 只是释放的str指向的内存空间,它本身的值还是存在的.
    所以free之后,有一个好的习惯就是将str=NULL.
    此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话�
,这段存储空间是可能被重新分配给其他变量的,
    尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常�
会打印出world来。
    这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完�
成的。
    当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请�
的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点�
),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给�
操作系统,因此你是可以继续访问这块地址的,只不过⋯⋯楼上都说过了,最好别这�
么干。
    2。运行的结果为什么等于15
    #include "stdio.h"
    #include "string.h"
    void main()
    {
page 14    char aa[10];
    printf("%d",strlen(aa));
    }
    答案:sizeof()和初不初始化,没有关系;strlen()和初始化有关。
    3。给定结构struct A 
    {
    char t:4;
    char k:4;
    unsigned short i:8;
    unsigned long m;
    };问sizeof(A) = ?
    答案:给定结构
    struct A 
    {
    char t:4; //4位
    char k:4; //4位
    unsigned short i:8; //8位 这里要偏移2字节保证4字节对齐 
    unsigned long m; //4个字节
    }; // 共8字节
    4。分析一下
    #include
    #include 
    #include <malloc.h>
    #include 
    #include 
    #include <memory.h>
    typedef struct AA
    {
    int b1:5;
    int b2:2;
    }AA;
    void main()
    {
    AA aa;
    char cc[100];
    strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
    memcpy(&aa,cc,sizeof(AA));
    cout << aa.b1 <<endl;
    cout << aa.b2 <<endl;
    }
    答案: -16和1
    首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.
    经过strcpy和memcpy后,aa的4个字节所存放的值是:
    0,1,2,3的ASC码,即00110000,00110001,00110010,00110011
    所以,最后一步:显示的是这4个字节的前5位,和之后的2位
    分别为:10000,和01
    因为int是有正负之分  所以是-16和1
    5。求函数返回值,输入x=9999; 
    int func ( x )
    { 
    int countx = 0; 
    while ( x ) 
page 15    { 
    countx ++; 
    x = x&(x-1); 
    } 
    return countx; 
    } 
    结果呢?
    答案:知道了这是统计9999的二进制数值中有多少个1的函数,且有
    9999=9×1024+512+256+15
    9×1024中含有1的个数为2;
    512中含有1的个数为1;
    256中含有1的个数为1;
    15中含有1的个数为4;
    故共有1的个数为8,结果为8。
    1000 - 1 = 0111,正好是原数取反。这就是原理。
    用这种方法来求1的个数是很效率很高的。
    不必去一个一个地移位。循环次数最少。
    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 &&(*ca || *c>b)));
    }
    7。分析:
    struct bit 
    { int a:3; 
    int b:2; 
    int c:3; 
    }; 
    int main() 
    { 
    bit s; 
    char *c=(char*)&s; 
    cout<
    int main(void) {
    int **p;
    int arr[100];
    p = &arr;
    return 0;
    }
    答案:搞错了,是指针类型不同,
    int **p; //二级指针
    &arr; //得到的是指向第一维为100的数组的指针
    应该这样写#include 
    int main(void) {
    int **p, *q;
    int arr[100];
    q = arr;
    p = &q;
    return 0;
    9。下面这个程序执行后会有什么错误或者效果:
page 16    #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了..无限循环下去.
    11。struct name1{
    char str;
    short x;
    int num;
    }
    struct name2{
    char str;
    int num;
    short x;
    }
    sizeof(struct name1)=??,sizeof(struct name2)=??
    答案:sizeof(struct name1)=8,sizeof(struct name2)=12
    在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同�
时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就�
是12字节
1
page 17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值