几道基础的面试题

1.各种<include>之间的顺序是否可交换?
2.<>和''加之在include上有什么区别呢?
3.if...else和switch语句在汇编中是怎样执行的以及它们都属于比较吗?
4.三重指针在什么情况下才会用到?
5.当将<include>包去掉时,系统会有错吗?如果有错,那么什么时候系统会报错?

答案:
1.各种<include>之间的顺序是否可交换?

不可以, include 就是将内容copy 进去而已。 设计的原因,很多include 不能交互

试试winsock2.h  windows.h  的顺序

2.<>和''加之在include上有什么区别呢?
就是搜索的路径不同


3.if...else和switch语句在汇编中是怎样执行的以及它们都属于比较吗?
前者比较后者查表


4.三重指针在什么情况下才会用到?

在要更改二维指针的地址的时候会用到


5.当将<include>包去掉时,系统会有错吗?如果有错,那么什么时候系统会报错?

不一定报错,如果用到了对应的包里面的函数或者名字才会报错

关于include的顺序:
1、 尽可能的在源文件中include 头文件,尽量不要在 头文件引用头文件;

2、如果你的头文件的类型中含有自动变量:
           a.h:
                      typedef struct    A {
                                B_t     b;
                                int   c;
                      } A_t;

          那么你的a.h非引用 b.h不可;


3、如果你的头文件的类型只含 指针变量:
              a.h:
                      typedef struct   A {
                                 B_t   *b;
                                 int  c;
                       };
         那么在a.h中就不要include b.h了,在前面加一句:
                      typedef struct B_t   B;  
          就可以了;

       但是这样的话你在 a.c 里面#include "b.h", 因为b.h里面也有一句:                       typedef struct B_t   B;  
        会报错,同一文件同一类型不允许 typedef 两次,所以你的  a.h必须这么写:
              
              a.h:
                      struct  B;
                      typedef struct   A {
                                 struct B   *b;
                                 int  c;
                       };
          就OK了。

3,
if...else... 和 switch 的效率再研究

昨天发现了一本叫做CSAPP的书,终于找到了关于switch问题的解答。
这是一段C代码:
/* $begin switch-c */
int switch_eg(int x)
{
    int result = x;

    switch (x) {

    case 100:
    result *= 13;
    break;

    case 102:
    result += 10;
    /* Fall through */

    case 103:
    result += 11;
    break;

    case 104:
    case 106:
    result *= result;
    break;

    default:
    result = 0;      
    }

    return result;
}
/* $end switch-c */

用GCC汇编出来的代码如下:
    .file    "switch.c"
    .version    "01.01"
gcc2_compiled.:
.text
    .align 4
.globl switch_eg
    .type     switch_eg,@function
switch_eg:
    pushl %ebp
    movl %esp,%ebp
    movl 8(%ebp),%edx
    leal -100(%edx),%eax
    cmpl ,%eax
    ja .L9
    jmp *.L10(,%eax,4)
    .p2align 4,,7
.section    .rodata
    .align 4
    .align 4
.L10:
    .long .L4
    .long .L9
    .long .L5
    .long .L6
    .long .L8
    .long .L9
    .long .L8
.text
    .p2align 4,,7
.L4:
    leal (%edx,%edx,2),%eax
    leal (%edx,%eax,4),%edx
    jmp .L3
    .p2align 4,,7
.L5:
    addl ,%edx
.L6:
    addl ,%edx
    jmp .L3
    .p2align 4,,7
.L8:
    imull %edx,%edx
    jmp .L3
    .p2align 4,,7
.L9:
    xorl %edx,%edx
.L3:
    movl %edx,%eax
    movl %ebp,%esp
    popl %ebp
    ret
.Lfe1:
    .size     switch_eg,.Lfe1-switch_eg
    .ident    "GCC: (GNU) 2.95.3 20010315 (release)"

在上面的汇编代码中我们可以很清楚的看到switch部分被分配了一个连续的查找表,switch case中不连续的部分也被添加上了相应的条目,switch表的大小不是根据case语句的多少,而是case的最大值的最小值之间的间距。在选择相应 的分支时,会先有一个cmp子句,如果大于查找表的最大值,则跳转到default子句。而其他所有的case语句的耗时都回事O(1)。

相比于if-else结构,switch的效率绝对是要高很多的,但是switch使用查找表的方式决定了case的条件必须是一个连续的常量。而if-else则可以灵活的多。



转自: http://joehust.ycool.com/post.1692407.html

你可能感兴趣的:(c,汇编,struct,面试,gcc,include)