LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: zywwzy

我今天为招聘新员工出的C语言考题

[复制链接]
发表于 2004-10-20 11:23:20 | 显示全部楼层
多谢。请问哪里有 objdump 生成的信息的说明呀?我装了 binutils-doc 发现读到的信息同执行 man 得到的结果一样没有说明。

还有关于堆栈的问题。今天我又试了另外一个程序 (修改它使其只包含必要信息需要更多的时间,所以我没修改,抱歉):
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <ctype.h>
  7. static int val1;
  8. static char val2;
  9. [color=red]static char val3;
  10. static int val4;[/color]
  11. void dumpaddr(FILE *fp, char *desc, void *addr);
  12. void mkprnt(char *buf);
  13. int main(int argc, char *argv[], char *envp[])
  14. {
  15.         FILE *p;
  16.         int i;
  17.         if ((p = popen("sort -n -k3 | "
  18.                 "gawk '{ printf "%-32s   %s\\n", $1, $2 }'", "w"))
  19.                 == NULL) {
  20.                 fprintf(stderr, "%s: cannot open pipe in dump(): %s\n",
  21.                         argv[0], strerror(errno));
  22.                 exit(-2);
  23.         }
  24.         for (i = 0; argv[i]; i++) {
  25.                 char buf[32];
  26.                 strcpy(buf, "arg:");
  27.                 strncpy(buf+4, argv[i], sizeof(buf)-6);
  28.                 buf[sizeof(buf) - 1] = '\0';
  29.                 mkprnt(buf);
  30.                 dumpaddr(p, buf, argv[i]);
  31.         }
  32.         for (i = 0; envp[i]; i++) {
  33.                 char buf[32];
  34.                 buf[0] = '&';
  35.                 strncpy(buf+1, envp[i], sizeof(buf)-2);
  36.                 buf[sizeof(buf) - 1] = '\0';
  37.                 mkprnt(buf);
  38.                 dumpaddr(p, buf, envp[i]);
  39.         }
  40.         dumpaddr(p, "main", main);
  41.         dumpaddr(p, "stderr", stderr);
  42.         dumpaddr(p, "stdout", stdout);
  43.         char str_val1[]="24\n";
  44.         char str_val2[]="32\n";
  45.         char str_val3[]="48\n";
  46. [color=red]        char str_val4[]="80\n";[/color]
  47.         int mval1;
  48.         char mval2;
  49. [color=red]        char mval3;
  50.         int mval4;[/color]
  51.         dumpaddr(p, "str_val1", str_val1);
  52.         dumpaddr(p, "str_val2", str_val2);
  53.         dumpaddr(p, "str_val3", str_val3);
  54. [color=red]        dumpaddr(p, "str_val4", str_val4);[/color]
  55.         dumpaddr(p, "val1", &val1);
  56.         dumpaddr(p, "val2", &val2);
  57.         dumpaddr(p, "val3", &val3);
  58. [color=red]        dumpaddr(p, "val4", &val4);[/color]
  59.         dumpaddr(p, "i", &i);
  60.         dumpaddr(p, "p", &p);
  61.         dumpaddr(p, "mval1", &mval1);
  62.         dumpaddr(p, "mval2", &mval2);
  63.         dumpaddr(p, "mval3", &mval3);
  64. [color=red]        dumpaddr(p, "mval4", &mval4);[/color]
  65.         pclose(p);
  66.         return 0;
  67. }
  68. /* dumpaddr: write messege desc and addr into stream p */
  69. void dumpaddr(FILE *fp, char *desc, void *addr)
  70. {
  71.         fprintf(fp, "%-32s   0x%08X\t%-32lu\n",
  72.                 desc, (long) addr, (unsigned long) addr);
  73. }
  74. /* mkprnt: make buf printable */
  75. void mkprnt(char *buf)
  76. {
  77.         while (*buf)
  78.                 if (!isprint(*buf++))
  79.                         *buf = '@';
  80. }
复制代码

同昨天的程序相比只有红色的部分是不同的。这个程序生成的主要结果是这样的:
  1. main                               0x080485C4
  2. val1                               0x08049D28
  3. val2                               0x08049D2C
  4. val3                               0x08049D2D
  5. val4                               0x08049D30
  6. stdout                             0x40150F80
  7. stderr                             0x401510E0
  8. [color=blue]mval4                              0xBFFFF8D4
  9. mval3                              0xBFFFF8DA
  10. mval2                              0xBFFFF8DB
  11. mval1                              0xBFFFF8DC[/color]
  12. str_val4                           0xBFFFF8E0
  13. str_val3                           0xBFFFF8E4
  14. str_val2                           0xBFFFF8E8
  15. str_val1                           0xBFFFF8EC
  16. i                                  0xBFFFF918
  17. p                                  0xBFFFF91C
  18. arg:./y                            0xBFFFFA8E
  19. &KDE_MULTIHEAD=false               0xBFFFFA92
  20. &TERM=xterm                        0xBFFFFAA6
  21. &SHELL=/bin/bash                   0xBFFFFAB1
  22. &XDM_MANAGED=/var/run/xdmctl/xd    0xBFFFFAC1
  23. &GTK2_RC_FILES=/etc/gtk-2.0/gtk    0xBFFFFB08
  24. &GTK_RC_FILES=/etc/gtk/gtkrc:/h    0xBFFFFB68
  25. &GS_LIB=/home/herbert/.fonts       0xBFFFFBBF
  26. &WINDOWID=35651589                 0xBFFFFBDB
  27. &KDE_FULL_SESSION=true             0xBFFFFBED
  28. &USER=herbert                      0xBFFFFC03
  29. &LS_COLORS=no=00:fi=00:di=01;34    0xBFFFFC10
  30. &LD_LIBRARY_PATH=/usr/lib/wine     0xBFFFFE45
  31. &XCURSOR_SIZE=                     0xBFFFFE63
  32. &SESSION_MANAGER=local/natsu:/t    0xBFFFFE71
  33. &XPSERVERLIST=:64                  0xBFFFFEA1
  34. &KONSOLE_DCOP=DCOPRef(konsole-1    0xBFFFFEB3
  35. &DESKTOP_SESSION=default           0xBFFFFEDE
  36. &PATH=/usr/local/bin:/usr/bin:/    0xBFFFFEF6
  37. &KONSOLE_DCOP_SESSION=DCOPRef(k    0xBFFFFF32
  38. &PWD=/home/herbert                 0xBFFFFF67
  39. &XMODIFIERS=@im=fcitx              0xBFFFFF79
  40. &LANG=zh_CN                        0xBFFFFF8E
  41. &SHLVL=2                           0xBFFFFF99
  42. &HOME=/home/herbert                0xBFFFFFA1
  43. &XCURSOR_THEME=default             0xBFFFFFB4
  44. &LOGNAME=herbert                   0xBFFFFFCA
  45. &DISPLAY=:0.0                      0xBFFFFFDA
  46. &COLORTERM=                        0xBFFFFFE7
  47. &_=./y                             0xBFFFFFF2
复制代码

为了方便我把昨天的程序的执行结果也放在这里:
  1. main                               0x080485C4
  2. val1                               0x08049C50
  3. val2                               0x08049C54
  4. val3                               0x08049C58
  5. stdout                             0x40150F80
  6. stderr                             0x401510E0
  7. [color=blue]mval3                              0xBFFFF8D8
  8. mval2                              0xBFFFF8DF
  9. mval1                              0xBFFFF8E0[/color]
  10. str_val3                           0xBFFFF8E4
  11. str_val2                           0xBFFFF8E8
  12. str_val1                           0xBFFFF8EC
  13. i                                  0xBFFFF918
  14. p                                  0xBFFFF91C
  15. arg:./y                            0xBFFFFA87
  16. arg:abcdef                         0xBFFFFA8B
  17. &KDE_MULTIHEAD=false               0xBFFFFA92
  18. &TERM=xterm                        0xBFFFFAA6
  19. &SHELL=/bin/bash                   0xBFFFFAB1
  20. &XDM_MANAGED=/var/run/xdmctl/xd    0xBFFFFAC1
  21. &GTK2_RC_FILES=/etc/gtk-2.0/gtk    0xBFFFFB08
  22. &GTK_RC_FILES=/etc/gtk/gtkrc:/h    0xBFFFFB68
  23. &GS_LIB=/home/herbert/.fonts       0xBFFFFBBF
  24. &WINDOWID=48234501                 0xBFFFFBDB
  25. &KDE_FULL_SESSION=true             0xBFFFFBED
  26. &USER=herbert                      0xBFFFFC03
  27. &LS_COLORS=no=00:fi=00:di=01;34    0xBFFFFC10
  28. &LD_LIBRARY_PATH=/usr/lib/wine     0xBFFFFE45
  29. &XCURSOR_SIZE=                     0xBFFFFE63
  30. &SESSION_MANAGER=local/natsu:/t    0xBFFFFE71
  31. &XPSERVERLIST=:64                  0xBFFFFEA1
  32. &KONSOLE_DCOP=DCOPRef(konsole-3    0xBFFFFEB3
  33. &DESKTOP_SESSION=default           0xBFFFFEDE
  34. &PATH=/usr/local/bin:/usr/bin:/    0xBFFFFEF6
  35. &KONSOLE_DCOP_SESSION=DCOPRef(k    0xBFFFFF32
  36. &PWD=/home/herbert                 0xBFFFFF67
  37. &XMODIFIERS=@im=fcitx              0xBFFFFF79
  38. &LANG=zh_CN                        0xBFFFFF8E
  39. &SHLVL=2                           0xBFFFFF99
  40. &HOME=/home/herbert                0xBFFFFFA1
  41. &XCURSOR_THEME=default             0xBFFFFFB4
  42. &LOGNAME=herbert                   0xBFFFFFCA
  43. &DISPLAY=:0.0                      0xBFFFFFDA
  44. &COLORTERM=                        0xBFFFFFE7
  45. &_=./y                             0xBFFFFFF2
复制代码

请注意两个结果的蓝色部分。我搞不懂这些地址。请问这是怎么回事儿?另外,从结果上看如果出现了两个 char 类型的静态变量,它们不会都在 4 字节边界上对齐了。
发表于 2004-10-20 12:02:33 | 显示全部楼层
我写了个程序:

  1. #include <stdio.h>

  2. static int var1;
  3. static char var2;
  4. static char var3;
  5. static int var4;
  6. static char var5;
  7. static int var6;

  8. int main(void)
  9. {
  10.         printf("var1=%p,var2=%p,var3=%p\n",&var1,&var2,&var3);
  11.         printf("var4=%p,var5=%p,var6=%p\n",&var4,&var5,&var6);
  12.         return 0;
  13. }
复制代码

可以看出,如果是两个连续的char型,编译器就不单独按照每个char分配4字节的方式对齐。可能是4个以下(含4个)连续的char就分配一段连续的空间。如果说是5 个char,那么就前4 个分配4个连续的字节,最后一个单独分配4个字节,合起来5个连续的char占用8个字节空间。我没有做测试,你试试看。
发表于 2004-10-20 12:05:20 | 显示全部楼层
关于objdump的说明资料,我也是看《深入理解计算机系统》时得到的。这本书虽然贵,但讲的都很重要的基础知识,建议你也买一本。这本教材只是国外大学本科二年级的教材,看过之后,才能理解中国的教育和国外的差距有多么巨大。
发表于 2004-10-20 12:12:42 | 显示全部楼层
最初由 kj501 发表
关于objdump的说明资料,我也是看《深入理解计算机系统》时得到的。这本书虽然贵,但讲的都很重要的基础知识,建议你也买一本。这本教材只是国外大学本科二年级的教材,看过之后,才能理解中国的教育和国外的差距有多么巨大。


好的,多谢!:thank

请再看一下堆栈的问题吧。我本来的想法是,一个 (自动) 变量在堆栈中占用的空间同它的大小相同。昨天的程序出结果后,我又认为堆栈也是按 4 字节对齐的。可是今天的结果把这个也推翻了。到底是怎么回事儿呢?
发表于 2004-10-20 16:47:12 | 显示全部楼层
mval4                              0xBFFFF8D4
mval3                              0xBFFFF8DA
mval2                              0xBFFFF8DB
mval1                              0xBFFFF8DC

你迷惑的是这个吧。这也正好说明堆栈是按4字节对齐的。堆栈生长方向与内存地址增加方向相反。因此,mval4占用0xBFFFF8D4,0xBFFFF8D5,0xBFFFF8D6,0xBFFFF8D7共4个字节。由于接下来是两个连续的char,这两个char要占用从0xBFFFF8D8到0xBFFFF8DB这4个字节,然后下面的mval1占用 0xBFFFF8DC到0xBFFFF8DF的4个字节。这与静态编译时的做法是一致的。从结果上看,两个char是被分配到了所占用的4个字节的高地址端。
发表于 2004-10-20 21:00:56 | 显示全部楼层
唉,今天上午算晕了。多谢啦,嘻嘻。
发表于 2004-10-20 21:24:25 | 显示全部楼层
最初由 无双 发表
有long long吧VC中
我没试过

但这个好像是一个新类型添加了

自己定义一下
long long i;

long long是gcc自己的扩展!
发表于 2004-10-20 21:33:07 | 显示全部楼层
最初由 小锁 发表
long long是gcc自己的扩展!


最新的 C99 标准已经加入了 long long int 类型。
发表于 2004-10-26 14:01:25 | 显示全部楼层
把汇编学好了,估计这个问题就好解决了。
发表于 2004-10-26 14:05:53 | 显示全部楼层
把汇编学好了,估计这个问题就好解决了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表