姿势体系结构的详细解释 -- C

我基本上总结出以下4部分:

1、问题的足迹大小。

2、字节对齐问题。

3、特别保留位0。

4、这种结构被存储在存储器中的位置。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//基本概念
/*
struct _M
{
	(1)	类型 參数名 : 占位大小。
	(2)	类型 : 占位大小;
}

(1)
	类型 -- int,unsigned(32位),short,char。

參数名 -- 同个结构体里面不能重名參数。

占位大小 -- 不能大于类型最最大位数。

(2) 一般用于寄存器中保留位
*/

//占位大小问题:
/*
err -- int类型是32位。34大于32位,所以编译出错。
struct _A
{
	int x1:34;
};

err -- char类型是8位,9大于8位,所以编译出错。
struct _A1
{
	char x1:9;
};
*/

//字节对齐
/*
	偏移量 -- 类型和占位大小影响(与结构体字节对齐差点儿相同意思)。

*/
struct B
{
	char x1:1;//1位。字节对齐占1字节,8位。
	char x2:8;
	char x3:1;
	char x4:8;
	char x5:1;
};

struct C
{
	char x1:4;
	char :1;
	char x2:3;
};

struct _C
{
	char x1:4;
	char :8;
	char x2:3;
};

//特殊保留位0
struct C1
{
	char x1:4;
	char :0;//这个0占了4个字节
	char x2:3;
};

struct _C1
{
	char x1:4;
	char :4;//这个0占了4个字节
	char x2:3;
};

//内存中存放顺序
struct D
{
	char x1:1;//最低位
	char x2:1;
	char x3:1;
	char x4:1;
	char x5:1;
	char x6:1;
	char x7:1;
	char x8:1;//最高位
};

int
main()
{
	//字节对齐
	B b;
	printf("sizeof(b) = %d\n", sizeof(b));

	C c;
	printf("sizeof(c) = %d\n", sizeof(c));

	_C _c;
	printf("sizeof(_c) = %d\n", sizeof(_c));

	//特殊保留位0
	C1 c1;
	printf("sizeof(c1) = %d\n", sizeof(c1));
	memset(&c1, 0, sizeof(c1) );
	c1.x1 = 0xf;
	c1.x2 = 0x7;
	printf("c1 = 0x%x\n", c1);

	_C1 _c1;
	printf("sizeof(_c1) = %d\n", sizeof(_c1));
	memset(&_c1, 0, sizeof(_c1) );
	_c1.x1 = 0xf;
	_c1.x2 = 0x7;
	printf("_c1 = 0x%x\n", _c1);

	//内存中存放顺序
	D d;
	memset(&d, 0, sizeof(d) );
	printf("d = 0x%08x\n", d);
	d.x1 = 1;
	printf("d = 0x%08x\n", d);

}

/*
[[email protected] test_class]# gcc quote.cpp ;./a.out
sizeof(b) = 5
sizeof(c) = 1
sizeof(c1) = 2
c1 = 0x70f
sizeof(c2) = 3
d = 0x00000000
d = 0x00000001
[[email protected] test_class]# gcc quote.cpp ;./a.out
sizeof(b) = 5
sizeof(c) = 1
sizeof(_c) = 3
sizeof(c1) = 2
c1 = 0x70f
sizeof(_c1) = 2
_c1 = 0x70f
d = 0x00000700
d = 0x00000701

*/

以下是别人的博客:

在使用结构体位制的时候有两点要特别注意:
1.//位段成员的类型仅可以为unsigned或者int
2.
unsigned b:4;
        unsigned :0;    //定义长度为0的位段时不能指定名字,否则编译只是
        unsigned d:1;   //定义了0字段后,紧接着的下一个成员从下一个存储单元開始存放;                                       //此样例中,d前面那个存储单元中的余下的27位中被0填充了

/*
        DATE : 2010.6.24
        关于C中的位端igned或者int
*/
#include <stdio.h>

typedef struct _A
{
        unsigned int a:4;//位段成员的类型仅可以为unsigned或者int
        unsigned b:4;
        unsigned c:2;
        unsigned d:6;
        unsigned E:1;
        unsigned D:2;
        unsigned T:3;
        unsigned A:9;
        unsigned h:4; //前面已经为31,故4+31>32已超过一个存储单元,所以4在一个新的存储单元存放
        unsigned y:29;//由于前面的4在一个新的存储单元的开头存放,且29+4>32, 故在还有一个新的存储单元存放
}A;               //所以最后求出的A的大小是4 + 4 + 4 =12

/*对上面的详细解释: 一个位段必须存储在同一个存储单元中,不能跨两个单元.假设某存储单元空间中不能容纳
              下一个位段,则改空间不用,而从下一个存储单元起存放该位段. 结构体A中的h和y就是这样的情况.
                                        在gcc环境下,測试后,一个存储单元为4个字节.
*/

typedef struct _S
{
        unsigned a:4;
        unsigned b:4;
        unsigned c:22;
        unsigned q:1;
        unsigned h:1;
        //unsigned i:33;  // 错误:‘i’ 的宽度超过它自身的类型
        //unsigned i:1;当多出此行时,该结构体大小由4变为8,由于此行之前正好为32位
} S;

typedef struct _T
{       //当没有占满一个存储单元时,结构体的大小对齐为一个存储单元的大小
        unsigned a:2;
        unsigned b:2;
        unsigned j:1;
        unsigned : 1;//可以定义无名位段,此例中该无名位段占用1位的空间,该空间将不被使用
} T;

typedef struct _V
{
        unsigned a:1;
        unsigned b:4;
        unsigned :0;    //定义长度为0的位段时不能指定名字,否则编译只是
        unsigned d:1;   //定义了0字段后,紧接着的下一个成员从下一个存储单元開始存放;
}V;                                     //此样例中,d前面那个存储单元中的余下的27位中被0填充了

int main()
{
        A a; S s; T t; V v;
        printf("sizeof(a)=%d\n", sizeof(a));
        printf("sizeof(s)=%u\nsizeof(t)=%u\n", sizeof(s), sizeof(t));
        printf("sizeof(v)=%d\n", sizeof(v));
        return 0;
}

版权声明:本文博主原创文章。博客,未经同意不得转载。

时间: 2024-08-27 18:11:51

姿势体系结构的详细解释 -- C的相关文章

Android中多线程编程(四)AsyncTask类的详细解释(附源码)

Android中多线程编程中AsyncTask类的详细解释 1.Android单线程模型 2.耗时操作放在非主线程中执行 Android主线程和子线程之间的通信封装类:AsyncTask类 1.子线程中更新UI 2.封装.简化异步操作. 3.AsyncTask机制:底层是通过线程池来工作的,当一个线程没有执行完毕,后边的线程是无法执行的.必须等前边的线程执行完毕后,后边的线程才能执行. AsyncTask类使用注意事项: 1.在UI线程中创建AsyncTask的实例 2.必须在UI线程中调用As

我对CONTAINING_RECORD宏的详细解释

宏CONTAINING_RECORD的用处其实还是相当大的, 而且很是方便, 它的主要作用是: 根据结构体中的某成员的指针来推算出该结构体的指针! 下面从一个简单的例子开始说起: 我们定义一个结构体, 同时类型化: typedef struct{ int a; int b; int c; }ss; 这是一个很简单的结构体, 没什么特殊的, 稍微分析下该结构体: 结构体的大小(字节):4+4+4=12字节 成员a的偏移:0 成员b的偏移:4 成员c的偏移:8 我们用ss来定义一个变量: ss s

Atitit&#160;.jvm&#160;虚拟机指令详细解释

Atitit .jvm 虚拟机指令详细解释 1. 一.未归类系列A1 2. 数据mov系列2 2.1. 二.const系列2 2.2. 三.push系列2 2.3. ldc系列 该系列命令负责把数值常量或String常量值从常量池中推送至栈顶.3 2.4. 5.1.load系列A 该系列命令负责把本地变量的送到栈顶.3 2.5. 5.2.load系列B 该系列命令负责把数组的某项送到栈顶.4 2.6. 6.1.store系列A 该系列命令负责把栈顶的值存入本地变量.5 2.7. 6.2.stor

Sed命令的使用详细解释

Sed命令的使用详细解释 一:sed命令的简介 sed是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕.接着处理下一行,这样不断重复,直到文件末尾.文件内容并没有改变,除非你使用重定向存储输出.Sed主要用来自动编辑一个或多个文件:简化对文件的反复操作:编写转换程序等.     二:Sed的用法格式 Sed [options] 'scri

设计模式 - 迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释

迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考迭代器模式(iterator pattern): http://blog.csdn.net/caroline_wendy/article/details/35254643 Java的标准库(util)中包括迭代器接口(iterator interface), import java.util.Iterator; 继承

C语言 - 结构体(struct)比特字段(:) 详细解释

结构体(struct)比特字段(:) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26722511 结构体(struct)能够使用位字段(:), 节省空间, 例如以下面代码, 结构体a中的, 第一个变量x占用1个字符, y占用2个字符, z占用33个字符(越界); 可是sizeof()会自己主动补齐, 如x+y一共占用4个字节, z占用8个字节, 所以结构体占用12个字节; 当使用加法运算时, 会初始化为0; 代码

445port入侵详细解释

445port入侵详细解释   大约"445port入侵"内容445port入侵详细解释网站搜索许多其他的"445port入侵"内容 445port入侵,以前我们先来看看或445port早干嘛去了,成为侵入port呢?445port就是IPC 服务的默认port                                                            ipc$一 摘要 二 什么是 ipc$ 三 什么是空会话 四 空会话能够做什么 五 ip

关于javascript中静态成员和实例成员的详细解释

关于javascript中静态成员和实例成员的详细解释  在我们了解什么是静态成员和实例成员之前,我们首先来了解一下什么是实例? 实例就是由构造函数创建出来的对象. 例如案例中 p 就是实例: function Person() {}//  此函数为构造函数 var p=new Person();  // p为构造函数创建出来的对象 我们在讨论静态成员和实例成员时候,把函数当成构造函数, 把创建出来的对象称之为实例.在此明白了什么是实例,下面我们就可以说什么是静态  成员和实例成员了. 首先什么

cmd批处理转义字符%的详细解释

cmd批处理转义字符%的详细解释 在命令行中使用for时不需要双%,这源于命令解释器对命令行与批处理的处理方式不同. 1.%是个ESCAPE字符,通常将之译为转义字符,但也有更形象的译名脱逸字符.逃逸字符等.也就是说%不仅仅将与其相关的特定字符串转义并替换为特定字符串,而且自身也会被“脱逸”.而且类似于C语言中的转义字符"\",双%会转义并脱逸为单%,四%则脱为双%. 2.for本身是一个特殊的命令,类似于一个特化的命令解释器,因为它的功能实现需要执行多条语句,因此它必须也具有对命令行