zoukankan      html  css  js  c++  java
  • 做错过的C语法题目

    语法题目考察的比较集中,基本上包括以下几个方面:

    • 宏定义和预处理
    • 结构体、功用体对齐、长度
    • sizeof/typedef
    • 变量类型转换
    • 指针运算
    • 关键字
    • 运算符优先级
    • 语法解析

            需要认证啊,错很多基础的。本篇博客耗时4小时。

    一、宏定义和预处理

    1、写出下列代码的运行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <stdio.h>
    #define STRCPY(a, b) strcpy(a ## _p, #b)
     
    int main()
    {
        charvar1_p[20];
        charvar2_p[30];
     
        strcpy(var1_p,"aaaa";
        strcpy(var2_p,"bbbb";
     
        STRCPY(var1, var2);
        STRCPY(var2, var1);
     
        printf("var1 = %s/n", var1_p);
        printf("var2 = %s/n", var2_p);
     
        return0;
    }

    答:var1 = var2/nvar2 = var1/n

    析:#为字符串化操作符,讲锁连接的部分转化为一个字符串,##为字符串连接符,将两个字符串连接成一个字符串,均在预处理时完成字符串的替换。仔细点,应该错不了。

     

    2、写出下列代码的运行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
     
    #define f(a,b) a##b
    #define g(a)   #a
    #define h(a) g(a)  
    intmain()
    {
        printf("%s ", h(f(1,2)));
        printf("%s ", g(f(1,2)));
        return0;
    }

    答:12和f(1,2)。

    析:本题考察字符串化操作符#得作用得执行过程,以及宏定义替换的次序。如果该宏为带#号的宏定义,则直接替换字符串,无需再嵌套替换,如果该宏不是带#的宏,则先替换括号内部的宏定义,然后替换外部的。

     

    3、定义一个宏,求一个结构体struct中某个变量相对于struct的偏移量

    1
    #define OFFSET(struct, member)  ((unsigned int)&((struct *)0)->member)

     

    二、指针运算

    1、写出输出结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    intmain()
    {
        inta[3];
        a[0] = 0;
        a[1] = 1;
        a[2] = 2;
     
        int*p, *q;
        p = a;
        q = &a[2];
     
        intc = a[q - p];
     
        printf("value c = %d/n", c++);
        printf("value c = %d/n", c);
     
        return0;
    }

    答:value c =2/nvalue c=3/n

    析:此处q-p=2,容易错,地址相减得除以类型,表面上差了8,实际上差了2。不同类型的地址,比如char *p,额int *p,p-q不能操作,报错。

     

    2、写出下列函数运行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #incude <stdio.h>
     
    voidmain()
    {
       inta[5]={1,2,3,4,5};
       int*ptr=(int*)(&a+1);
     
       printf("%d,%d",*(a+1),*(ptr-1));
    }

    答:结果为2,5

     

    3、假如我们的a的地址是:0Xbfe2e100, 而且是32位机,那么这个程序会输出什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
    intmain()
    {
        inta[5];
        printf("%x ", a);
        printf("%x ", a+1);
        printf("%x ", &a);
        printf("%x ", &a+1);
        return0;
    }

    结果:0Xbfe2e100,0Xbfe2e104,0Xbfe2e100,0Xbfe2e114。

    分析:分清除哪个表示数组结构,哪个表示数组元素,a表示第一个元素的地址,&a表示数组结构的地址。

     

    三、关键字

    1、一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)

    一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)

    答:int (*a)[10];int (*fn)(int);

     

    2、const关键字的作用:

    const int a; 

    int const a; 

    const int *a; 

    int * const a; 

    int const * a const; 

    答:const一直理解的和初学者一样,什么东西被const修饰了,就只读了,无论你修饰的是变量、返回值或者指针。上面分别代表:

    整形常量a,a的值只读;

    整形常量a,a的值只读;

    整形常量指针a,*a的值只读,a可以修改;

    整形常量指针a,a的值只读,*a可以修改;

    整形常量指针a,a的值只读,*a也只读;

     

    3、写出打印结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    charstr1[] = "abc";
    charstr2[] = "abc";
     
    constchar str3[] = "abc";
    constchar str4[] = "abc";
     
    constchar *str5 = "abc";
    constchar *str6 = "abc";
     
    char*str7 = "abc";
    char*str8 = "abc";
     
     
    cout << ( str1 == str2 ) << endl;
    cout << ( str3 == str4 ) << endl;
    cout << ( str5 == str6 ) << endl;
    cout << ( str7 == str8 ) << endl;

    答:0 0 1 1。

    析:虽然都是常量,但是数组有空间,指针没空间。

     

    4、volatile关键字什么用处?

    答:volatile关键字修饰变量,提示编译器该变量是“易变”的,在执行与该变量有关的操作时,需要从变量中取值,而不要仅仅从寄存器中取,常用的情况有,状态寄存器变量、并发共享变量等等。

     

    五、类型强制转换

    1、下列代码输出是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
     
    voidfoo(void)
        unsignedinta = 6; 
        intb = -20; 
        (a+b > 6)? puts("> 6") : puts("<= 6");
    }
     
    intmain()
    {
        foo();
        return0;
    }

    答:>6。

    析:主要考察不同类型的变量在一块运行的转化原则:有符号要向无符号的方向转化。因此>6。

     

    2、下列操作没有任何打印,原因?

    #include <stdio.h> 
    #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) 
    int array[] = {23,34,12,17,204,99,16}; 
    int main() 
    {
        int d;
        for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
            printf("%d ",array[d+1]);
        return 0; 
    }

    答:由于TOTAL_ELEMENTS得出结果后为unsigned int类型,与-1比较时,将-1转化为无符号整形,也即0xFFFFFFFF,不满足条件退出。

     

    六、优先级与左值

    1、写出结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <stdio.h>
    intmain()
    {
        inta = 5, b = 7, c;
        c = a+++b;
     
        printf("a=%d,b=%d,c=%d ",a,b,c);
        return0;
    }

    答:a=6,b=7,c=12。

    析:这个题目考察语法解析。表面上可以理解为a++ + b,也可以理解为a+ ++b,因为编译器解析关键字是从左向右的,尽量包含更多的字符组成关键字,称为“贪心法”或者“大嘴法”。

     

    2、A、B、C、D的运算结果分别是:

    1
    2
    3
    4
    5
    inta = 4;
    (A) a += (a++);
    (B) a += (++a) ;
    (C) (a++) += a;
    (D) (++a) += (a++);

    答:前两个9,10没问题,后两个gcc报错左值问题。但网上有人说D位11

    析:本题考察左值运算,即等号左面的不能是一个数,可以是变量。

     

    3、写出运算结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    #define SQUARE(a) ((a)*(a))
     
    intmain(void)
    {
        inta=5;
        intb1,b2;
        b1 = SQUARE(a++);
        b2 = SQUARE(++a);
        printf("b1=%d, b2=%d ",b1,b2);
     
        return0;
    }

    答:25,81。

    析:相当于b1=((a++)*(a++)),b2=((++a)*(++a))。编译器编译时,a++先用再加(所为先用再加,应该是=后面的部分),而++a,是先加再用。

     

    4、写出结果

    1
    2
    3
    4
    5
    6
    7
    intmain()
    {
        inti = 6;
        if( ((++i < 7) && ( i++/6)) || (++i <= 9));
            printf("%d ",i);
        return0;
    }

    答:8

    分析:本题目考察&&短路径求解问题,所为短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。

     

    5、写出程序运行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include<stdio.h>
     
    intf(intn)
    {
        return++n;
    }
     
    intg(int*n)
    {
        return++*n;
    }
     
    main ()
    {
     
        intn=10;
        intk=0;
        k=f(n);
     
        printf("k is: %d ", k);
        printf("n is: %d ", n);
        k=g(&n);
        printf("k is: %d ", k++);
        printf("n is: %d ", n++);
    }

    答:11,10,11,11。

     

    七、类型长度

    1、下列代码执行结果:

    1
    2
    3
    4
    typedef union {long i; int k[5]; char c;} DATE;
    struct data { int cat; DATEcow; double dog;} too;
    DATEmax;
    printf("%d",sizeof(structdate)+sizeof(max));

    答:32为系统52,64位系统64.

    分析:关于对齐,32位默认4byte对齐,64位默认8byte对齐,或者通过#pragma pack(N)来实现执行对齐。union共享功用体最长的空间,而struct是各成员空间相加。

     

    2、下列代码运行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    #include <stdio.h>
    intmain()
    {
        inti = 1;
        sizeof(i++);
        printf("%d ", i);
        return0;
    }

    答:1

    分析:正因为sizeof是编译期求值的,所以如果它跟着表达式,那么表达式是不被计算的,只是根本表达式的类型得到它占用的空间。

     

     

    八、其他

    1、一语句实现x是否为2的若干次幂的判断(32位系统)

    1
    x|(x-1)=0xFFFFFFFF?puts("true"):puts("false");
  • 相关阅读:
    集合——iterator迭代器
    集合——顶层collection接口(单列集合)
    集合——集合框架
    构造方法
    接口作为方法的参数或返回值——List接口
    接口作为成员变量——实现类和匿名内部类和匿名对象
    距离和相似度度量
    Kmeans算法与KNN算法的区别
    linux命令
    MapReduce初级案例
  • 原文地址:https://www.cnblogs.com/longbiao831/p/4556284.html
Copyright © 2011-2022 走看看