Chinaunix首页 | 论坛 | 博客
  • 博客访问: 198429
  • 博文数量: 28
  • 博客积分: 1179
  • 博客等级: 上尉
  • 技术积分: 405
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-21 22:51
文章分类

全部博文(28)

文章存档

2012年(4)

2011年(8)

2010年(2)

2009年(6)

2008年(8)

分类: LINUX

2008-12-29 22:59:24

程序如下:
#include
#include
#include

int main(int argc, char** argv)
{
union
{
struct
{
char a:1;
char b:2;
char a:3;
}d;
char e;
} f;
f.e = 1;
printf("%d\n",f.d.a);
getchar();
return 0;
}

分析:

1.分析结构体(struct)中的含义.
char a:1; a占1位;
char b:2; b占2位;
char a:3; c占3位;
这个地方涉及到 struct 中的位段.

2.分析联合体(union)的含义.
union,共享内存,里面的数据是从低位开始的,这点很重要哦!
所以我们清楚,在 f.e = 1 之前, struct里面的内存是混乱的,因为没有初始化.
赋值之后,该Union中的内存应是下面的情况.("s"代表未知)
s s s s s s s s 1

?3.这里我们假设是小端模式.(同样,大端模式,小端模式自己Baidu下拉,这里不罗嗦了)
  大小端模式是指多字节下,字节的顺序。但是这里只有一个字节。
  这里有待商榷。也许是和编译器的实现有关。

4.printf("%d",f.d.a);
我们以 %d 的模式输出,因为此时读的是 a 所在的一位而 %d 需要32位.
怎么办呢,这个时候就需要类型提升了. (关于类型提升,照例去Baidu)
此时,1被作为符号位,做类型提升,使得 %d 读出的数据 32位全为 1.
即 0xFFFF.

5.0xFFFF,正是 -1 在内存中的补码形式. 所以这个程序会输出 -1.



延伸分析:

1.类型提升,是按照什么样的规则?
如果 a 不是占一位,而是占4位,5位,内存分布值为 10010/10100/01011 等等,会被提升成什么?
解答:首先提取符号位,也就是第一位.后面的原则未知.

?2.大端模式和小端模式. 针对上题中的 char 类型,两者有区别么?
可以找一个大端模式的编译器,测试即得.

3.有兴趣的朋友可以尝试将 char类型改为 int/unsigned int,进行更多的调试.
解答:int 是 -1;unsigned int 是 1。

4.关于原码,反码,补码.
众所周知,反码是原码各位取反,补码末位加1.我只想说,这不是绝对正确的.


5.关于赋值.
这需要有点ASCII的基础.因为ASCII可以表示char型常用的128个字符.(这些可以Baidu下)
此时将 char e 的值赋给了 这个 Union,所以 a,b,c 三个值都会有自己对应的位值.(0或者1)
不管我们赋的值是多少,只需保证最末一位是 1,也就是 a 的位是1,程序就会输出 -1.


提到ASCII码,让我想起了一个可以让windows死机的小程序.(只有几行代码,利用了ASCII码的控制符)
#include
#include

int main()
{
for(;;)
{
    printf("hung up\t\t\b\b\b\b\b\b");
    print("hung up\t\t\b\b\b\b\b\b";
    }
  return 0;
}

大概是这个样子,我记不太清楚了.还请高手留言赐教~!
阅读(1655) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~