c关键字-sizeof的种种

  文章开始,先看一个结构体的代码: //爱立信2011笔试 360 2011笔试均涉及

  structnode{inta;intb;};

  问:sizeof(Node)是多少?答案很简单,在32位机器上,一个int是4个字节,两个int就是8个字节,sizeof(Node)就是8。

  好的,上面那个答案确实是8,那么再看下面这个结构体:

  structnode{chara;intb;};

  问:这个时候sizeof(Node)又是多少呢?int是4个字节,char是1个字节,答案是5?

  这回,没有那么幸运,经过在机器上的操作,答案是8! Why?

  实际上,这不是语言的问题,你在ANSI C中找不到为什么会这样!甚至你在不同的体系结构、不同的编译器下会得到不同的答案。那么,到底是谁把5改成了8呢?

  这就引入了一个概念,叫做“内存对齐”。所谓的内存对齐,是指一种计算机体系结构(如X86)对基本数据类型的存储位置有限制,要求其地址为某个数 的倍数,通常这个数为4或8。这种要求会简化处理器的设计以及提升数据访问的效率。至于为什么会有这样的设计,简单的说访存总线的位数固定,以32位总线 为例,地址总线的地址总是4对齐的,所以数据也四对齐的话,一个周期内就可以把数据读出。这里不理解的话可以跳过去,只要记得对齐这回事儿就行了。如果想 更深入的理解,可以看这里另一篇文章。

  知道这个之后,那么我们就可以理解,实际上是编译器为了效率,在相邻的变量之间放置了一些填充字节来保证数据的对齐。X86结构是4对齐的,所以sizeof(Node)是8不是5。

  再来看一个例子:

  structnode{inta;charb;charc;intd;chard;};

  这时的sizeof(Node)是多少呢?没错,是16。

  好的,既然我们知道对齐是由编译器来作的,那么我们可不可以更改对齐数呢?答案是可以的,在C语言中,我们可以通过

  #pragma pack(n)

  来更改对齐模数。

  注:以上都是在现x86 linux下使用gcc编译器验证,不乏有其他系统和编译器会得到不同的结果。

  再让我们来看个例子:

  structnode{doublea;intb;intc;chard;};

  这个时候的sizeof(node)是多少?20?24?

  其实,这个时候你会发现,当你在windows上使用VC编译的时候,你会得到24;当你在linux上使用gcc编译的时候,你会得到20!其实,这恰好说明这种数据的对齐是由编译器决定的!在VC中规定, 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;而在gcc中规定对齐模数最大只能是4,也就是说,即使结构体中有double类型,对齐模数还是4,所以数据是按照1,2,4对齐的。所以,在两个不同编译器上,你得到了不同的答案!本文由“www.no1nk.com”编辑

时间: 2024-10-05 04:25:54

c关键字-sizeof的种种的相关文章

细说关键字sizeof及其十大特性

     Sizeof是c/c++中的关键字,它是一个运算符,其作用是取得一个对象(数据类型或数据对象)的长度(即占用内存的大小,以byte为单位).其中类型包括基本数据类型(不包括void).用户自定义类型(结构体.类).函数类型.数据对象是指用前面提到的类型定义的普通变量和指针变量(包含void指针). 十大特性: 特性0:sizeof是运算符,不是函数: 特性1:sizeof不能求void类型的长度: 特性2:sizeof能求void类型的指针的长度:    其实指针也是变量,只不过这个变

最冤枉的关键字----sizeof

<h4>一.常年被人误认为函数.</h4> sizeof 是关键字不是函数,其实就算不知道它是否为32 个关键字之一时,我们也可以借助编译器确定它的身份.看下面的例子: int i=0:A),sizeof(int): B),sizeof(i): C),sizeof int: D),sizeof i: 毫无疑问,32 位系统下A),B)的值为4.那C)的呢?D)的呢?在32 位系统下,我们发现D)的结果也为4. 咦?sizeof 后面的括号呢?没有括号居然也行,那想想,函数名后面没有

关键字sizeof()

首先我们必须知道,sizeof()是一个关键字而不是一个函数,这一点我们可以证明: int main() {                  int a = 5;                  short b = 3;                 printf( "%d\n", sizeof (b = a + 2));                 printf( "b=%d\n", b);                 system( "p

C语言基础(4)-原码,反码,补码及sizeof关键字

1. 原码 +7的原码是0000 0111 -7的原码是1000 0111 +0的原码是0000 0000 -0的原码是1000 0000 2. 反码 一个数如果值为正,那么反码和原码相同. 一个数如果为负,那么符号位为1,其他各位与原码相反 +7的反码0000 0111 -7的反码1111 1000 -0的反码1111 1111 3. 补码 原码和反码都不利于计算机的运算,如:原码表示的7和-7相加,还需要判断符号位. 正数:原码,反码补码都相同 负数:最高位为1,其余各位原码取反,最后对整个

c#关键字和常用类型表快查

类型 字节 取值范围 说明 bool 1 true/false/null 布尔类型 char 2 0x0000~0xffff Unicode 16 位字符 byte 1 0~255 无符号的 8 位整数 sbyte 1 -128 到 127 8 位带符号整数 short 2 -32,768 到 32,767 有符号 16 位整数 ushort 2 0~65535 无符号 16 位整数 int 4 -2,147,483,648 到 2,147,483,647 带符号的 32 位整数 uint 4

涛哥为你讲解C语言的关键字所涉及的基本知识

\1.1.2存储相关关键字 register.static.const.auto.extern1.1.3控制语句相关的关键字if .else .break.continue.for .while.do.switch casegoto.default1.1.4其他关键字sizeof.typedef.volatile sizeof使用来测变量.数组的占用存储空间的大小(字节数)例4:int a;int num;num=sizeof(a); typedef 关键字 ,作用是给一个已有的类型,重新起个类

深入C(关键字)

C语言标准定义的32个关键字 关键字 意 义 auto 声明自动变量,缺省时编译器一般默认为auto int 声明整型变量 double 声明双精度变量 long 声明长整型变量 char 声明字符型变量 float 声明浮点型变量 short 声明短整型变量 signed 声明有符号类型变量 unsigned 声明无符号类型变量 struct 声明结构体变量 union 声明联合数据类型 enum 声明枚举类型 static 声明静态变量 switch 用于开关语句 case 开关语句分支 d

C语言关键字 (一)

0.定义和声明的区别 1.什么是定义? 所谓的定义就是编译器创建一个对象,为这个对象分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名或对象名.这个名字一旦和这块内存匹配起来,他们就同生共死,不离不弃,并且这块内存的位置也不能被改变.一个变量或对象在一定的区域内只能被定义一次. 2.什么事声明? 声明就是告诉编译器,这个名字已经匹配到一块内存上了,声明可以出现多次.同时也告诉编译器,这个名字已被定义了,别的地方再也不能用它来作为变量名或对象名. 3.声明和定义的区别? 定义创建了对

编程珠玑之关键字(1)--《c语言深度剖析》整理(转)

一.最快关键字register 关键字regiter请求编译器尽可能的将变量存在CPU的寄存器中.有几点注意的地方. 1.register变量必须是能被CPU寄存器所接受的类型,这通常意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度. 但是,有些机器的寄存器也能存放浮点数. 2.register变量可能不存放在内存中,所以不能用取址符运算符“ & ”. 3.只有局部变量和形参可以作为register变量,全局变量不行. 4.静态变量不能定义为register.  总