Chinaunix首页 | 论坛 | 博客
  • 博客访问: 467013
  • 博文数量: 62
  • 博客积分: 1742
  • 博客等级: 中尉
  • 技术积分: 859
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-06 00:13
个人简介

这是一句很长很长而且又很啰嗦并且很无聊的废话...

文章分类

全部博文(62)

文章存档

2013年(1)

2012年(13)

2011年(48)

分类: C/C++

2011-05-17 22:19:21

   还是照旧,先贴两段代码说明问题.

  1. #include <stdio.h>

  2. typedef struct{
  3.     int a;
  4.     int b;
  5.     char c;
  6.     int d;
  7. }*p_Test;

  8. int main(){
  9.     printf("%#X\n",&(((p_Test)0)->d));

  10.     printf("%#X\n",&(*((int *)0)));
  11.     return 0;
  12. }

对应汇编:

  1. .file "test1.c"
  2. .section .rodata
  3. .LC0:
  4. .string "%#X\n"
  5. .text
  6. .globl main
  7. .type main, @function
  8. main:
  9. pushl %ebp
  10. movl %esp, %ebp
  11. andl $-16, %esp
  12. subl $16, %esp
  13. movl $.LC0, %eax
  14. movl $12, 4(%esp)
  15. movl %eax, (%esp)
  16. call printf
  17. movl $.LC0, %eax
  18. movl $0, 4(%esp)
  19. movl %eax, (%esp)
  20. call printf
  21. movl $0, %eax
  22. leave
  23. ret
  24. .size main, .-main
  25. .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
  26. .section .note.GNU-stack,"",@progbits

另外一段为:

  1. #include <stdio.h>

  2. typedef struct{
  3.     int a;
  4.     int b;
  5.     char c;
  6.     int d;
  7. }*p_Test;

  8. int main(){
  9.     printf("%#X\n",(((p_Test)0)->d));

  10.     printf("%#X\n",(*((int *)0)));
  11.     return 0;
  12. }

对应汇编为:

  1. .file "test1.c"
  2. .section .rodata
  3. .LC0:
  4. .string "%#X\n"
  5. .text
  6. .globl main
  7. .type main, @function
  8. main:
  9. pushl %ebp
  10. movl %esp, %ebp
  11. andl $-16, %esp
  12. subl $16, %esp
  13. movl $0, %eax
  14. movl 12(x), %edx
  15. movl $.LC0, %eax
  16. movl %edx, 4(%esp)
  17. movl %eax, (%esp)
  18. call printf
  19. movl $0, %eax
  20. movl (%eax), %edx
  21. movl $.LC0, %eax
  22. movl %edx, 4(%esp)
  23. movl %eax, (%esp)
  24. call printf
  25. movl $0, %eax
  26. leave
  27. ret
  28. .size main, .-main
  29. .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
  30. .section .note.GNU-stack,"",@progbits
今天老师讲了Linux源码中include/linux/kernel.h中的container_of,代码是这样的:

/**
* container_of - cast a member of a structure out to the containing structure
* @ptr:     the pointer to the member.
* @type:     the type of the container struct this is embedded in.
* @member:     the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({             \
         const typeof( ((type *)0)->member ) *__mptr = (ptr);     \
         (type *)( (char *)__mptr - offsetof(type,member) );})


开始不太理解,他以0作为指针地址去访问一个结构,难道不会发生段错误吗?后来自己又写了个测试,发现如果用任意数作为的指针不是进行实质性的内存访问的话,那么编译器是允许的,怎么说?看上面对照的汇编代码就知道了,编译器在编译成汇编代码的时候就已经把值计算出来了,而不是在运行时作为内存地址偏移进行操作,所以...哎,我也说不清楚,反正这些细节,自己长点记性...按老师那句话,领会精神!

阅读(1476) | 评论(1) | 转发(1) |
0

上一篇:小小的发现

下一篇:Linux汇编

给主人留下些什么吧!~~

GFree_Wind2011-05-18 12:18:10

稍微说两句。
1. container_of是宏定义,那么在编译期间,值已经确定;
2. 即使不是宏定义,是运行时进行运算,也没有关系。因为不牵涉任何的地址访问。
3. 发生段错误的原因,是因为发生了非法的内存访问。也就是说,你可以把任何地址赋给指针,只要不访问该地址,都不会有问题。