zoukankan      html  css  js  c++  java
  • C语言补遗

    前些天公司摸底 C 语言考试,得分比较难看,回来发了考试答案,这篇博客把我做错的题目拿出来理一理,补补课。

    • 判断对错:在定义数据结构时,没有特殊理由的话,都定义成四字节对齐;这样做可能浪费几个字节,但是不会出问题。

      这道题答案是对的,需要仔细 Google。

    • 以下程序运行 (64 位系统) 后的输出结果是 6 5 8 5

      int main()
      {
        char str1[] = "Hello";
        char str2[] = {'H', 'e', 'l', 'l', 'o'};
        char *p = str1;
        printf("%d %d %d %d
      ", sizeof(str1), sizeof(str2), sizeof(p), strlen(p));
      }
      

      这道题我的答案是 6,5,4,5,原因在于 64 位的指针的长度大小是 8 个字节,而不是一般的 4 个字节。 考点为 字符串数组长度 (+1), 64 位指针长度 (8) 字符串数组 x 包含末尾的’’

    • 如下程序, 在 64bit 系统运行输出为 24 4 8 16

      struct s1
      {
          char a;
          int b;
          short c;
          double d;
      };
      int main(void)
      {
          printf("%d %d %d %d
      ",
          sizeof(struct s1), offsetof(struct s1, b), offsetof(struct
          s1, c), offsetof(struct s1, d) ) ;
          //注: offsetof 为计算偏移量的宏
          return 0;
      }
      

      我的答案是 48,8,16,32,错误成了 2 倍。主要为结构体对齐规则, 这部分需要强化 一般考生都可以看到 b 按 4 字节对齐,需要填充 忽视 double 也需要 8 字节对齐 double 在 32 位 linux 平台下可能按照 4 字节对齐

    • 如下指针计算, 结果为 4

      int *p1 = (int *)0x500;
      int *p2 = (int *)0x510;
      printf(“%d
      ”, (p2 - p1));
      

      我错成了 16,答案应该是 16/4,指针的减法,按照指针类型计算跨越的步长

    • 如下程序, 请问输出多少? -128,128

      void main(void)
      {
      char x = 127;
      char a = x + 1;
      int b = x + 1;
      printf("%d %d", a, b);
      }
      

      我的答案是 128,128,整型加法隐式提升到 int 然后运算,所以 x+1 就是 128 溢出出现在赋值运算,第一个溢出了,第二个没有。没有考虑到第一个溢出之后的数据显示问题

    • 如下程序片段, 输出为: 2 7

      int *p;
      int x[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
      p = x[0] + 1;
      printf("%d %d
      ", *p, x[2][0]);
      

      我的答案是 4 7 。x[0] 是对二级指针解引用,类型是指向整型的指针,指向 1,+1 后,指向 x[0][1] 没争议

    • 计算如下定义长度 (64 位系统)

      typedef union {
          int a;
          long b;
          char c[6];
      }un;
      sizeof(un) = 8
      

      我的答案是 48,联合体的内存大小不会算,共用体的占用空间的大小,按照其最大成员算 本题中 long 是 8 字节

    • 请问输出多少

      union packet
      {
          struct packet_bit
          {
              unsigned char a:2;
              unsigned char b:3;
              unsigned char c:4;
          } bit;
          int i;
      } data;
      
      int main()
      {
          data.i = 0;
          data.bit.a = 1;
          data.bit.b = 2;
          data.bit.c = 0xF;
          printf("0x%04x
      ", data.i);
      }
      

      我的答案是 0xf,这道题完全是蒙出来的,考察的是位域的概念,位域结构体,按地址从低到高依次存储 a、b、c 一个规则大家可能都不熟悉: 一个位域必须存储在同一个字节中,不能跨两个字节 所以 a 和 b 储存在一个字节,c 再进来存不下,所以 c 单独存放在一个字节 再就是注意输出格式

    • 如下程序, 请写出打印结果 A b

      void fun(char *a, char *b)
      {
          a = b;
          (*a)++;
      }
      void main()
      {
          char c1 = 'A', c2 = 'a';
          char *p1 = &c1;
          char *p2 = &c2;
          fun(p1, p2);
          printf("%c %c
      ", c1, c2);
      }
      

      我的结果是 a b, 函数入参是按值传递的,只有通过传递地址才能改变函数外部的值,这里有一个陷阱,使用的地址,实际是从参数 b 传进来的,所以改变的也是参数 b 指向的值 。这道题不该错,因为在 fun 函数里,a 的值已经是 b 了,所以 a 指向的就是 b 指向的地址,因此改变的就是 c2 指向的字母啊

    • 下面函数的输出是 token3 = 4

      #define paster( n ) printf( "token" #n " = %d", token##n )
      void fun()
      {
          int token3 = 4;
          int tokenn = 3;
          paster( 3 );
      }
      

      我的答案是 token3 = 3,这是个知识盲点,可以参考 C 语言宏定义 ## 连接符和 #符的使用,# 将本身的字符替换之后再在两边加上双引号,## 是机械单纯得将两个 token 连接在一起

    • 如下程序, 输出为 100008 100001 100004

      struct test
      {
          int a;
          int b;
      };
      int main ()
      {
          struct test *p = (struct test *)0x100000;
          printf("%x %x %x
      ", (p+1), (long)p+1, (int *)p +1);
      }
      

      我的答案是 0x100008,0x100001,0x11。这道题比较有意思,程序第 8 行已经说明了,p 的值就是 0x100000(也就是说 p 指向的地址是 0x100000),后面 (int *)p,说明了它指向的是 int 类型,那么 + 1 就是在原来的地址上一个 int 的字节数,也就是 0x100004。需要总结的是,指针前面的表明的是这个指针指向的数据类型。

  • 相关阅读:
    UVA
    HDU
    manacher求最长回文子串算法
    next数组求最小循环节
    HUST
    廖雪峰Java1-4数组操作-2数组排序
    廖雪峰Java1-4数组操作-1遍历数组
    廖雪峰Java1-3流程控制-9break、continue
    廖雪峰Java-3流程控制-7for循环
    廖雪峰Java1-3流程控制-6 do-while循环
  • 原文地址:https://www.cnblogs.com/bugxch/p/13833559.html
Copyright © 2011-2022 走看看