sizeof 字节的对齐,位域sizeof的计算

合集下载

C语言结构体字节对齐简单计算方法

C语言结构体字节对齐简单计算方法

C语⾔结构体字节对齐简单计算⽅法
1.在C语⾔⾥⾯每⼀种数据类型都有字节对齐⽐如在32位操作系统下:整型的⾃⾝对齐数就是 4 字节,字符型就是 1 字节,double就是 8 字节。

但是结构体的计算⽅式就和普通的数据类型不⼀样。

在C语⾔⾥⾯字节对齐的⽅式主要根据“有效对齐数”来确定,那么有效对齐数是怎杨确定的呢?
在结构体⾥⾯::: 有效字节对齐数 = (⾃⾝对齐数 < 最⼤字节)?(⾃⾝对齐数):(最⼤字节);
⾃⾝对齐数 = 4字节(32位操作系统);(8 字节为32位操作系统)。

最⼤字节数 = 结构体⾥⾯最⼤的⼀个数据类型所占的字节数。

列:struct test{
char a;
int a;
short c;
}d;
sizeof(d) == ? ; //在32位操作系统下为12字节,64位操作系统下也为12字节。

(每⼀次都开4个字节)
struct test2{
char a;
double b;
short c;
}d;
sizeof(d) == ? ;// 在32位操作系统下为16字节(每⼀次开4个字节),在64位操作系统下为24字节(每⼀次开8个字节)。

VC_Sizeof

VC_Sizeof

VC的sizeof、字节对齐、位域见到N多的笔试题目考到相关内容,作题目时老是非常迷糊,索性一怒,狂看,终于有所得。

在这做个总结:一、VC默认方式的字节对齐:1.数据成员对齐规则:在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量:sizeof(类型)或其倍数2.整体对齐规则:结构的总大小也有个约束条件:最大sizeof(类型)的整数倍如:struct MyStruct{char dda;double dda1;int type};//sizeof=1+7+8+4+4=24二、自己设定字节对齐方式VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。

1.数据成员对齐规则:n字节对齐就是说变量存放的起始地址的偏移量:min(sizeof(类型),对齐方式)或其倍数.2.整体对齐规则:结构的总大小也有个约束条件:min(最大的sizeof(类型),对齐方式)的倍数.#pragma pack(push) //保存对齐状态#pragma pack(4)//设定为4字节对齐struct test{char m1; //默认偏移量double m4;//非默认偏移量int m3; //默认偏移量}; //sizeof=1+3+8+4=16应为4的倍数#pragma pack(pop)//恢复对齐状态#pragma pack(push) //保存对齐状态#pragma pack(16)//设定为4字节对齐struct test{char m1;//默认偏移量double m4;//默认偏移量int m3;//默认偏移量}; //sizeof=1+7+8+4+4=24应为8的倍数。

#pragma pack(pop)//恢复对齐状态三、sizeof简单应用1.参数为数据类型或者为一般变量。

例如sizeof(int),sizeof(long)等等。

这种情况要注意的是不同系统系统或者不同编译器得到的结果可能是不同的。

关于字节对齐的sizeof的讨论

关于字节对齐的sizeof的讨论

关于字节对齐的sizeof的讨论众所周知,程序为了提高访问效率,编译器在编译的时候,进行字节对齐。

程序员也可以字节指定对齐方式。

Win32下的为progma指令,具体来说#pragma pack(push) //保存原对齐状态#pragma pack(4)//设定为4字节对齐struct test{int a;};#pragma pack(pop)//恢复对齐状态在linux下,gcc是默认的编译器。

g++ 支持progma指令,gcc也支持GNU扩展__attribute__指令参考《__attribute__》,对于字节对齐的举例为struct test{short b[3];} __attribute__ ((aligned (8)));__attribute__还支持aligned 和packed ,解释如下__attribute__ ((aligned)); 选择针对目标机器最大的对齐方式,可以提高拷贝操作的效率。

aligned属性使被设置的对象占用更多的空间,相反的,使用packed可以减小对象占用的空间。

需要注意的是,attribute属性的效力与你的连接器也有关,如果你的连接器最大只支持16字节对齐,那么你此时定义32字节对齐也是无济于事的。

__attribute__ ((packed))使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。

下面以pragma 来讨论指定结构体对齐方式!总的来说规律如下#pragma pack(n)来设定变量以n字节对齐方式。

n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及⾃然对齐)struct {}node;32为的x86,window下VC下sizeof(node)的值为1,⽽linux的gcc下值为0;⼀、WINDOWS下(VC--其实GCC和其原理基本⼀样,象这种问题,⼀般要查具体的编译器设置)字节对齐的规则:1、⼀般设置的对齐⽅式为1,2,4字节对齐⽅式,VC⼀般默认为4字节(最⼤为8字节)。

结构的⾸地址必须是结构内最宽类型的整数倍地址;另外,结构体的每⼀个成员起始地址必须是⾃⾝类型⼤⼩的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最⾼为4字节对齐),否则在前⼀类型后补0;这⾥特别提到的是数组⼀定要注意,⽽且在⼀些编程的技巧中,我们可以使⽤数组强制字节达到对齐的⽬的。

这在⽹络编程中是很常见的。

举例:⽐如CHAR型占⽤空间为1字节,则其起始位置必须可被1整除。

INT为4字节,其起始位置必须被4带队,依次类推。

(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。

)2、结构体的整体⼤⼩必须可被对齐值整除,默认4(默认,且结构中的类型⼤⼩都⼩于默认的4)。

3、结构体的整体⼤⼩必须可被本结构内的最宽类型整除。

(其实和上⼀条是⼀样的,但这⾥独⽴出来,起注意作⽤。

⽐如结构体⾥的有DOUBLE,那么结构的⼤⼩最后必须可被8整除)注意:GCC不是这样,就是最⾼只能被4整除,它是个死的。

否则(2、3条),编译器会在结构的最后添充⼀定的特定字符来补齐。

struct T{char ch;double d ;};在VC中是16个字节,GCC中为12个字节。

4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,⽽不能以嵌套结构⼤⼩来做为上三种使⽤的基准。

⼆、举例:struct A{int a;char b;short c;};struct B{char b;int a;short c;};struct C{double t;char b;int a;short c;};struct D{char b;double t;int a;short c;};在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;我们先谈第⼀个,(说明⼀下,在考虑结构体⼤⼩时,我们基本可以忽略起始地址的问题,因为这个编译器会⾃动为我们做好,见上⾯的说明),结构体内⾸先是⼀个INT的4字节,起始地址假定为0,整除4,其⼩于等于默认的4字节对齐且0为4(INT的占⽤空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,⼩于4且5为1(CHAR占⽤空间)的整数倍,故占⽤1个字节,然后是⼀个起始地址为5占2个字节的SHORT,其⼩于4,但5不为2的整数倍,故补齐⼀个字节,从第6个字节开始,占2字节空间。

C语言中sizeof的用法总结

C语言中sizeof的用法总结

C语言中sizeof的用法总结一、sizeof的概念sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。

它并不是函数。

sizeof操作符以字节形式给出了其操作数的存储大小。

操作数可以是一个表达式或括在括号内的类型名。

操作数的存储大小由操作数的类型决定。

二、sizeof的使用方法1、用于数据类型sizeof使用形式:sizeof(type)数据类型必须用括号括住。

如sizeof(int)。

2、用于变量sizeof使用形式:sizeof(var_name)或sizeof var_name变量名可以不用括号括住。

如sizeof (var_name),sizeof var_name等都是正确形式。

带括号的用法更普遍,大多数程序员采用这种形式。

注意:sizeof操作符不能用于函数类型,不完全类型或位字段。

不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。

如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。

三、sizeof的结果sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。

该类型保证能容纳实现所建立的最大对象的字节大小。

1、若操作数具有类型char、unsigned char或signed char,其结果等于1。

ANSI C正式规定字符类型为1字节。

2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、10。

一篇文章带你了解C语言内存对齐公式

一篇文章带你了解C语言内存对齐公式

⼀篇⽂章带你了解C语⾔内存对齐公式⽬录⼀、前⾔⼆、公式2.1、例⼦⼀2.2、例⼦⼆2.3、例⼦三总结⼀、前⾔每⼀个特定平台上的编译器都有⾃⼰的默认“对齐系数”(也叫对齐模数)。

GCC中默认#program pack(4),即4个字节的内存对齐。

Keil也是采⽤4字节对齐的。

也可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变这⼀系数,⼀般情况下尽量使⽤⾃然对齐系数,不要修改它。

STM32单⽚机上各个变量占⽤的字节数:⼆、公式公式⼀、结构体变量⾥,成员的起始地址必须满⾜:起始地址 % 成员的字节数(sizeof值)= 0 (说⽩了就是能整除)公式⼆、结构体变量的总字节数必须满⾜:总字节数 % 最⼤的成员字节数 = 0 (说⽩了就是能整除)2.1、例⼦⼀struct te_a{/* 公式⼀ */char a; /* a的起始地址0x00,然后⽤公式⼀计算:0x00 % 1(char为1个字节) = 0,所以成员a占⽤了内存0x00 */int b; /* b的起始地址0x01 % 4(int为4个字节)不等于0,那么再计算0x02%4还是不等于0,直到0x04 % 4 = 0 ,所以成员b占⽤了内存0x04 ~ 0x07 */char c; /* 成员b的结尾地址是0x07,所以成员c从0x08开始计算,那么计算0x08 % 1 = 0 , 所以成员c占⽤了内存0x08 */}Test1;OK,经过公式⼀的运算后,结构体⾥成员的分布如下:经过公式⼀的计算后,结构体变量Test1的⼤⼩是9个字节。

内存对齐的计算还没有结束,接着使⽤公式⼆计算:结构体变量的总字节数 % 最⼤的成员字节数 = 0 ,在结构体变量Test1⾥,最⼤的成员是b,b的⼤⼩是4个字节。

那么,当前的结构体变量⼤⼩9字节 % 4字节等于 0 。

当结构体变量⼤⼩为12字节 % 4字节 = 0,所以最终结构体变量Test1占⽤的内存字节数是12,其内存的分布如下:以上的都是根据公式计算出来的结果,那实际在单⽚机⾥是不是这样呢?把代码下载到STM32单⽚机⾥,进⼊DEBUG模式看看。

sizeof与字节对齐

sizeof与字节对齐

sizeof的用法sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着“辛苦我一个,幸福千万人”的伟大思想,我决定将其尽可能详细的总结一下。

但当我总结的时候才发现,这个问题既可以简单,又可以复杂,所以本文有的地方并不适合初学者,甚至都没有必要大作文章。

但如果你想“知其然,更知其所以然”的话,那么这篇文章对你或许有所帮助。

菜鸟我对C++的掌握尚未深入,其中不乏错误,欢迎各位指正啊1. 定义:sizeof是何方神圣sizeof乃C/C++中的一个操作符(operator)是也,简单的说其作用就是返回一个对象或者类型所占的内存字节数。

MSDN上的解释为:The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types). This keyword returns a value of type size_t.其返回值类型为size_t,在头文件stddef.h中定义。

这是一个依赖于编译系统的值,一般定义为typedef unsigned int size_t;世上编译器林林总总,但作为一个规范,它们都会保证char、signed char和unsigned char的sizeof值为1,毕竟char是我们编程能用的最小数据类型。

2. 语法:sizeof有三种语法形式,如下:1) sizeof( object ); // sizeof( 对象 );2) sizeof( type_name ); // sizeof( 类型 );3) sizeof object; // sizeof 对象;所以,int i;sizeof( i ); // oksizeof i; // oksizeof( int ); // oksizeof int; // error既然写法3可以用写法1代替,为求形式统一以及减少我们大脑的负担,第3种写法,忘掉它吧!实际上,sizeof计算对象的大小也是转换成对对象类型的计算,也就是说,同种类型的不同对象其sizeof值都是一致的。

c语言结构体大小的计算公式

c语言结构体大小的计算公式

c语言结构体大小的计算公式C语言中的结构体是一种自定义的数据类型,它可以由不同类型的数据组成,用于表示一个复杂的数据结构。

在使用结构体时,我们需要了解它的大小,以便在内存中合理地分配空间。

本文将介绍计算C语言结构体大小的公式,并对其进行详细解析。

在C语言中,结构体的大小由其成员变量的大小决定。

常见的成员变量类型包括整型、浮点型、字符型、指针型等。

不同的数据类型在内存中占用的空间大小是不同的,因此结构体的大小也会受到成员变量类型的影响。

计算结构体大小的公式如下:```sizeof(结构体类型) = 对齐后的第一个成员变量的偏移量 + 结构体中所有成员变量的大小之和```其中,对齐后的第一个成员变量的偏移量是指结构体中第一个成员变量相对于结构体起始地址的偏移量。

在计算结构体大小时,编译器会根据对齐规则对结构体进行对齐,以提高访问效率。

对于结构体中的每个成员变量,编译器会根据其数据类型和对齐规则来确定其大小。

对齐规则是由编译器和编译选项决定的,不同的编译器和编译选项可能会有不同的对齐规则。

在计算结构体大小时,需要注意以下几点:1. 结构体的大小是成员变量大小的总和,不包括对齐字节。

2. 结构体的大小可能会受到编译器和编译选项的影响,不同的编译器和编译选项可能得到不同的结果。

3. 结构体的大小通常是按字节对齐的,即结构体的大小必须是成员变量大小的整数倍。

下面通过一个示例来说明结构体大小的计算方法:```c#include <stdio.h>struct Student {int id;char name[20];float score;};int main() {printf("Sizeof(struct Student) = %zu\n", sizeof(struct Student));return 0;}```在上述示例中,我们定义了一个名为`struct Student`的结构体,它包含三个成员变量:一个整型变量`id`、一个字符数组`name`和一个浮点型变量`score`。

C语言位运算和sizeof运算符详解

C语言位运算和sizeof运算符详解

C语言位运算和sizeof运算符详解C语言位运算和sizeof运算符详解C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的。

位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果。

下面,就和店铺一起来看一看C语言位运算和sizeof运算符详解,希望对大家有帮助!位运算和sizeof运算符C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的。

位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果。

位运算主要有6种:与(&),或(|),取反(~),异或(^),左移(<<),右移(>>)。

1.位运算中的类型转换位运算都必须进行Integer Promotion。

在进行运算之前,都必须将char型、short型的数据转换为int或者unsigned int型再参与运算。

如下面这段程序:#include<stdio.h>int main(void){unsigned char c=0xfc;unsigned int i=~c;printf("0x%xn",i);return 0;}在对c取反之前,先将c提升为int型,则为0x000000fc,取反之后结果就是0xffffff03,所以程序输出结果是0xffffff03,而不是0x00000003.2.异或运算的.一些特性。

a^0=a,a^a=0这两个特性是异或运算最常用的特性。

利用这个特性可以不借助临时变量就可以交换两个整数#include<stdio.h>int main(void){int a=3;int b=2;a=a^b;b=a^b;a=a^b;printf("%d %dn",a,b);return 0;}不借助临时变量交换两个数据还可以用另外一种方法。

C++位域和内存对齐问题

C++位域和内存对齐问题

C++位域和内存对齐问题1. 位域:1.在C中,位域可以写成这样(注:位域的数据类型⼀律⽤⽆符号的,纪律性)。

1struct bitmap2 {3 unsigned a : 1;4 unsigned b : 3;5 unsigned c : 4;6 }bit; sizeof(bitmap) == 4;(整个struct的⼤⼩为4,因为位域本质上是从⼀个数据类型分出来的,在我们的例⼦中数据类型就是unsigned,⼤⼩为4,并且位域也是满⾜C和C++的结构体内存对齐原则的,等下我们会说到)。

2.当然了位域也可以有空域。

1struct bitmap2 {3 unsigned a:4;4 unsigned :0; /*空域*/5 unsigned b:4; /*从下⼀单元开始存放*/6 unsigned c:4;7 }8sizeof(bitmap) == 8;3.在这个位域定义中,a占第⼀字节的4位,后4位填0表⽰不使⽤,b从第⼆字节开始,占⽤4位,c占⽤4位。

这⾥我们可以看到空域的作⽤是填充数据类型的剩下的位置,有时候我们只是想调整⼀下内存分配,则我们可以使⽤⽆名位域:1struct bitmap2 {3 unsigned a:1;4 unsigned :2;5 unsigned b:3;6 unsigned c:2;7 };8sizeof(bitmap) == 4;4.如果⼀个位域的位的分配超过了该类型的位的总数,则从下⼀个单元开始继续分配,这个很好理解:1struct bitmap2 {3 unsigned a : 8;4 unsigned b : 30;5 unsigned c : 4;6 };7sizeof(bitmap) == 12; 注意这个位域的⼤⼩是12⽽不是8,说明如果超了⼤⼩是⽴马从下⼀个单元开始分配⽽不是cast在后⾯。

5. C++的位域: 由于C++有类,所以呢位域可以写进类⾥⾯,很简单⽐如:1class Demo2 {3 unsigned mode : 8;4 unsigned modeifed : 2;5 unsigned protA : 3;6 unsigned protB : 4;7public:8 ...9 }; 另外就是需要注意的是,取地址运算符不能作⽤于位域,所以任何指针都⽆法指向类的位域,访问位域的⽅法和访问类的成员的⽅法⼀样,这⾥就不多说了。

c语言的sizeof

c语言的sizeof

c语言的sizeofC语言是一种通用的计算机编程语言,是许多程序员最常用的语言之一。

在C语言中,sizeof是一个非常重要的运算符,它用来计算数据类型或变量在内存中所占的字节数。

sizeof运算符可以用于计算各种数据类型的字节数,包括基本数据类型(如整型、浮点型、字符型等)和自定义数据类型(如结构体、联合体等)。

本文将介绍C语言中sizeof运算符的使用方法和注意事项。

一、sizeof的用法在C语言中,sizeof运算符的一般格式为:sizeof (类型或表达式)其中,类型可以是C语言中的任何数据类型,表达式可以是变量、数组、指针等。

sizeof的计算结果是一个整数值,表示该类型或表达式在内存中所占的字节数。

下面是几个示例:1. 计算整型数据类型的字节数```int n = sizeof(int);```上述代码中,sizeof(int)计算整型数据类型int在内存中所占的字节数,并将结果赋值给变量n。

2. 计算数组的字节数```int arr[10];int size = sizeof(arr);```上述代码中,sizeof(arr)计算整型数组arr在内存中所占的字节数,并将结果赋值给变量size。

3. 计算指针的字节数```int* ptr;int size = sizeof(ptr);```上述代码中,sizeof(ptr)计算整型指针ptr在内存中所占的字节数,并将结果赋值给变量size。

二、sizeof的注意事项1. sizeof运算符的结果是一个常量表达式,它在编译时求值,并不会运行时计算。

因此,sizeof运算符的操作数不能包含变量或表达式,只能是类型名、类型说明符或已定义的结构体/联合体的标识符。

2. 在sizeof运算符中,数组名作为操作数时,计算的是整个数组的字节数。

而指针名作为操作数时,计算的是指针所指向类型的字节数。

3. 注意C语言中的指针与指向数组的指针是不同的概念。

ARM内存边界对齐以及sizeof问题

ARM内存边界对齐以及sizeof问题
对齐.
不得不说,确实有那幺些质量较差的程序可能需要你部分自然对齐,部
分一字节对齐,此时
2.typedefstructpack{
}__attribute__((packed))
可利用__attribute__属性
当然最后的方式,还是自己去看arm体系结构与gcc编译选项了。
ARM内存边界对齐以及sizeof问题
默认情况下,在32位cpu里,gcc对于结构体的对齐方式是按照四
个字节来对齐的。看以下结构体
typedefstructpack{
chara;
intb;
shortc;
}pack;
对于Pack结构体,默认情况下在arm/386平台下(别的平台没试
过)sizeof(pack)=12,求解过程如下:
பைடு நூலகம்sizeof(char)=1;
下一个intb,由于是四个字节,要求b的开始地址从32的整数倍开始,
故需要在a后面填充3个没用的字节,记为dump(3),sizeof(b)=4,此时相当于结
构体扩充为
chara;
chardump(3);
intb;
看shortc,现在c的前面有8个字节,c是两个字节,c的开始地址是从
#pramapack(1)
后,sizeof(pack)=142=7
而在arm下同样的操作sizeof(pack)=1421=8,即虽然b根a之间不要
填充但总的长度必须要是4的整数倍.
在arm下要使结构体按指定字节对齐,可行的方法
1.在makefile里加-fpack-struct选项,这样的话对所有的结构按一字节
16的整数开始,在b前面不需再加东西.此时对于结构体来说,sizeof(pack)=10,

sizeof 参数

sizeof 参数

sizeof 参数sizeof 参数是在编程中常用的一个关键字,用于获取数据类型或变量的大小。

在不同的编程语言中,sizeof 参数的用法和具体实现可能会有所差异,下面将以C语言为例,详细介绍sizeof 参数的用法和相关注意事项。

一、sizeof 参数的基本概念sizeof 是C语言中的一个运算符,用于计算数据类型或变量在内存中所占的字节数。

sizeof 参数可以是数据类型、变量、表达式或者函数名。

sizeof 参数的结果是一个整数值,表示所计算的数据类型或变量在内存中所占的字节数。

1. 计算数据类型的大小sizeof 参数可以直接跟数据类型名,用于计算该数据类型在内存中所占的字节数。

例如,sizeof(int) 用于计算整型数据在内存中所占的字节数,sizeof(float) 用于计算单精度浮点数在内存中所占的字节数。

2. 计算变量的大小sizeof 参数可以跟变量名,用于计算该变量在内存中所占的字节数。

例如,int a; sizeof(a) 用于计算整型变量a在内存中所占的字节数。

3. 计算表达式的大小sizeof 参数可以跟表达式,用于计算该表达式的结果在内存中所占的字节数。

例如,sizeof(a + b) 用于计算整型变量a和b相加的结果所占的字节数。

4. 计算函数名的大小sizeof 参数可以跟函数名,用于计算该函数所占的字节数。

注意,函数名在sizeof 参数中并不会被真正执行,只是用于计算函数的大小。

例如,sizeof(main) 用于计算主函数main所占的字节数。

三、sizeof 参数的注意事项1. sizeof 参数返回的是一个整数值,单位是字节。

不同的数据类型在内存中所占的字节数可能不同,需要根据具体的编程语言和编译器来确定。

2. sizeof 参数只能计算静态类型的大小,不能计算动态类型的大小。

例如,对于指针变量sizeof(p),返回的是指针本身的大小,而不是指针所指向的对象的大小。

sizeof在计算结构体大小的时候具体是怎样计算的

sizeof在计算结构体大小的时候具体是怎样计算的

sizeof在计算结构体大小的时候具体是怎样计算的下面看一下sizeof在计算结构体大小的时候具体是怎样计算的1.test1 空结构体typedef struct node{}S;则sizeof(S)=1;或sizeof(S)=0;在C++中占1字节,而在C中占0字节。

2.test2typedef struct node1{int a;char b;short c;}S1;则sizeof(S1)=8。

这是因为结构体node1中最长的数据类型是int,占4个字节,因此以4字节对齐,则该结构体在内存中存放方式为|--------int--------| 4字节|char|----|--short-| 4字节总共占8字节3.test3typedef struct node2{char a;int b;short c;}S2;则siezof(S3)=12.最长数据类型为int,占4个字节。

因此以4字节对齐,其在内存空间存放方式如下:|char|----|----|----| 4字节|--------int--------| 4字节|--short--|----|----| 4字节总共占12个字节4.test4 含有静态数据成员typedef struct node3{int a;short b;static int c;}S3;则sizeof(S3)=8.这里结构体中包含静态数据成员,而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的)。

其在内存中存储方式如下:|--------int--------| 4字节|--short-|----|----| 4字节而变量c是单独存放在静态数据区的,因此用siezof计算其大小时没有将c所占的空间计算进来。

5.test5 结构体中含有结构体typedef struct node4{bool a;S1 s1;short b;}S4;则sizeof(S4)=16。

sizeof计算struct占字节数的方法总结

sizeof计算struct占字节数的方法总结

sizeof计算struct占字节数的⽅法总结⽭盾焦点:1、结构体的内存对齐⽅式字节对齐的⽬的:1、提⾼CPU存储变量的速度计算的核⼼点(默认对齐⽅式):1、结构体内的每⼀个成员的起始地址跟结构体起始地址的偏移量要刚好是⾃⼰字节数的整数倍,不⾜则⾃动填充。

2、结构体总的字节⼤⼩要刚好是结构体的字节边界数的倍数,不⾜则⾃动填充。

(字节边界数:结构体中占⽤最⼤空间的类型的字节数)3、static修饰的结构体成员不占⽤结构体字节数,因为静态变量的存储地址跟结构体的实例地址⽆关。

4、空结构体的字节数为1,因为必须保证结构体的实例地址唯⼀。

计算的核⼼点(#pragma pack设置字节对齐⼤⼩):#pragma pack(push)#pragma pack(n)...#pragma pack(pop)⼀、结构体每个成员的地址偏移量1、如果n⼤于等于当前成员的字节数,则当前成员的地址偏移量要刚好是⾃⼰字节数的整数倍,不⾜则⾃动填充。

2、如果n⼩于当前成员的字节数,则当前成员的地址偏移量要刚好是n的整数倍,不⾜则⾃动填充。

⼆、结构体总的字节数1、如果n⼤于等于结构体中占⽤最⼤空间的类型的字节数,则结构体总字节数⼤⼩要刚好是结构体中占⽤最⼤空间的类型的字节数的整数倍。

2、如果n⼩于结构体中最⼤空间的类型的字节数,则结构体总字节数的⼤⼩要刚好是n的整数倍。

计算的核⼼(补充):1、static修饰的结构体成员不占⽤结构体字节数,因为静态变量的存储地址跟结构体的实例地址⽆关。

2、空结构体的字节数为1,因为必须保证结构体的实例地址唯⼀。

//try ⼀ trystruct F{char a;short b;double c;float d;char e;};int FCount = sizeof(F);cout << "F count = " << FCount << endl; //F count = 24#pragma back(push)#pragma pack(2)struct E{char a;short b;double c;float d;char e;};#pragma back(pop)int ECount = sizeof(E);cout << "E count = " << ECount << endl; //E count = 18//n⼤于等于结构体所占最⼤空间的类型的字节数的情况,按照默认对齐⽅式处理上述代码有⼀个疑问点://try ⼀ trystruct FF{char a;short b;double c;float d;char e;static double h;};int FFCount = sizeof(FF);cout << "FF count = " << FFCount << endl; //FF count = 24struct G{};int GCount = sizeof(G);cout << "G count = " << GCount << endl; //G count = 1追加:类类型占据字节数跟结构体的计算⽅法⼀致。

字节对齐时struct数据结构的sizeof结果

字节对齐时struct数据结构的sizeof结果

字节对齐时struct数据结构的sizeof结果⽤⼀句话可以概括为:⾸先,结构体中的每个成员按【有效值】对齐,并最⼩化长度;然后,结构体本⾝按【有效值】对齐,并最⼩化长度。

这⾥⾯有三个值:1.⾃⾝的对齐值:数据类型的⾃⾝对齐值⼀般是数据类型的字节数;结构体或者类的⾃⾝对齐值是其数据成员中⾃⾝对齐值最⼤的那个值。

2.指定对齐值:#progma pack (value)时的指定对齐值value(不同编译器的默认值不同)。

3.数据成员、结构体和类的【有效对齐值】:⾃⾝对齐值和指定对齐值中较⼩的那个值。

假设编译器的默认对齐值为1、2、4、8中的⼀个,计算默认对齐值的⽅法如下:int def_pack(){struct Node{char a;double b;}x;return (unsigned)&x.b - (unsigned)&x.a}这个实现不完全正确,欢迎拍砖。

计算struct的sizeof结果时,先计算结构体成员的地址对齐,再计算结构体本⾝的地址对齐。

下⾯贴出两个例⼦以供参考:(1)struct B { char b; int a; short c; };假设B从地址空间0x0000开始排放。

该例⼦中没有定义指定对齐值,假设编译器的默认为4。

第⼀个成员变量b的⾃⾝对齐值是1,⽐指定或者默认指定对齐值4⼩,所以其有效对齐值为1,所以其存放地址0x0000符合0x0000%1=0.第⼆个成员变量a,其⾃⾝对齐值为4,所以有效对齐值也为4,所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,符合0x0004%4=0, 且紧靠第⼀个变量。

第三个变量c,⾃⾝对齐值为2,所以有效对齐值也是2,可以存放在0x0008到0x0009这两个字节空间中,符合0x0008%2=0。

所以从0x0000到0x0009存放的都是B内容。

再看数据结构B的⾃⾝对齐值为其变量中最⼤对齐值(这⾥是b)所以就是4,所以结构体的有效对齐值也是4。

SIZEOF 及 结构体联合体大小计算方法

SIZEOF 及 结构体联合体大小计算方法

SIZEOF 及结构体联合体大小计算方法2010-09-06 16:30Cpp代码// Example of the sizeof keywordsize_t i = sizeof( int );struct align_depends {char c;int i;};size_t size = sizeof(align_depends); // The value of size depends on// the value set with /Zp or// #pragma packint array[] = { 1, 2, 3, 4, 5 }; // sizeof( array ) is 20// sizeof( array[0] ) is 4size_t sizearr = // Count of items in arraysizeof( array ) / sizeof( array[0] );// Example of the sizeof keywordsize_t i = sizeof( int );struct align_depends {char c;int i;};size_t size = sizeof(align_depends); // The value of size depends on// the value set with /Zp or// #pragma packint array[] = { 1, 2, 3, 4, 5 }; // sizeof( array ) is 20// sizeof( array[0] ) is 4size_t sizearr = // Count of items in arraysizeof( array ) / sizeof( array[0] );<script src="ms-its:dsmsdn.chm::/html/msdn_footer.js"></script>1. 用法1.1 sizeof和new、delete等一样,是关键字,不是函数或者宏。

CC++结构体字节对齐详解

CC++结构体字节对齐详解

CC++结构体字节对齐详解结构体的sizeof先看⼀个结构体:struct S1{char c;int i;};sizeof(S1)在VC6中按默认设置得到的结果为8。

我们先看看sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那就让我们来看看S1的内存分配情况S1 s1 = { 'a', 0xFFFFFFFF };定义上⾯的变量后,加上断点,运⾏程序,观察s1所在的内存,你发现了什么以我的VC6.0(sp6)为例,s1的地址为0x0012FF78,其数据内容如下:0012FF78: 61 CC CC CC FF FF FF FF发现了什么怎么中间夹杂了3个字节的CC看看MSDN上的说明:When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment.原来如此,这就是传说中的字节对齐啊!⼀个重要的话题出现了。

为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多花指令周期了。

为此,编译器默认会对结构体进⾏处理(实际上其它地⽅的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。

这样,两个数中间就可能需要加⼊填充字节,所以整个结构体的sizeof值就增长了。

让我们交换⼀下S1中char与int的位置:struct S2{int i;char c;};看看sizeof(S2)的结果为多少,怎么还是8再看看内存,原来成员c后⾯仍然有3个填充字节,这⼜是为什么啊别着急,下⾯总结规律。

字节对齐的细节和编译器实现相关,但⼀般⽽⾔,满⾜三个准则:1) 结构体变量的⾸地址能够被其最宽基本类型成员的⼤⼩所整除;2) 结构体每个成员相对于结构体⾸地址的偏移量(offset)都是成员⼤⼩的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);3) 结构体的总⼤⼩为结构体最宽基本类型成员⼤⼩的整数倍,如有需要编译器会在最末⼀个成员之后加上填充字节(trailing padding)。

内存对齐及sizeof总结

内存对齐及sizeof总结

1,实例:char *ss1 = "0123456789";char ss2[] = "0123456789";char ss3[100] = "0123456789";int ss4[100];char *str1 = new char[100];int *str2 = new int[100];输出cout<<"ss1 = "<<sizeof(ss1)<<endl;//ss1是字符指针,字符指针大小是定值4 4 cout<<"ss2 = "<<sizeof(ss2)<<endl;//ss2是字符数组,最初大小未定,由具体填充值来定//包含最后一个'\0' 11 cout<<"ss3 = "<<sizeof(ss3)<<endl;//ss3是字符数组,开始分配100字节100 cout<<"ss4 = "<<sizeof(ss4)<<endl;//ss4是整形数组400 cout<<"str1 = "<<sizeof(str1)<<endl;//ss1是字符指针,指针大小是定值4 4 cout<<"str2 = "<<sizeof(str2)<<endl;//ss1是字符指针,指针大小是定值4 42,内存对齐对于大部分程序员来说,“内存对齐”是“透明的”,“内存对齐”应该是编译器的“管辖范围”。

编译器把程序中的每个“数据单元”安排在适当的位置。

C语言的灵活性允许你干预“内存对齐”。

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2,所以有效对齐值也是 2,可以存放在 0x0008 到 0x0009 这两个字节空间中, 符合 0x0008%2=0。所以从 0x0000 到 0x0009 存放的都是 B 内容。再看数据结 构 B 的自身对齐值为其变量中最大对齐值(这里是 b)所以就是 4,所以结构体 的有效对齐值也是 4。根据结构体圆整的要求,0x0009 到 0x0000=10 字节,(10 +2)%4=0。所以 0x0000A 到 0x000B 也为结构体 B 所占用。故 B 从 0x0000 到 0x000B 共有 12 个字节,sizeof(struct B)=12;其实如果就这一个就来说它已将 满足字节对齐了,因为它的起始地址是 0,因此肯定是对齐的,之所以在后面补充 2 个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结 构 B 的数组,那么第一个结构起始地址是 0 没有问题,但是第二个结构呢?按照数 组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为 4 的整 数倍,那么下一个结构的起始地址将是 0x0000A,这显然不能满足结构的地址对 齐了,因此我们要把结构补充成有效对齐大小的整数倍.其实诸如:对于 char 型数 据,其自身对齐值为 1,对于 short 型为 2,对于 int,float,double 类型,其自身 对齐值为 4,这些已有类型的自身对齐值也是基于数组考虑的,只是因为这些类型 的长度已知了,所以他们的自身对齐值也就已知了.
代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。例如: unsigned int i = 0x12345678; unsigned char *p=NULL; unsigned short *p1=NULL; p=&i; *p=0x00; p1=(unsigned short *)(p+1); *p1=0x0000; 最后两句代码,从奇数边界去访问 unsignedshort 型变量,显然不符合对齐的规 定。 在 x86 上,类似的操作只会影响效率,但是在 MIPS 或者 sparc 上,可能就是一 个 error,因为它们要求必须字节对齐. 八.如何查找与字节对齐方面的问题: 如果出现对齐或者赋值问题首先查看 1. 编译器的 big little 端设置 2. 看这种体系本身是否支持非对齐访问 3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标 志其特殊访问操作。 九.相关文章:转自 /goodluckyxl/archive/2005/10/17/506827.aspx ARM 下的对齐处理 from DUI0067D_ADS1_2_CompLib 3.13 type qulifiers 有部分摘自 ARM 编译器文档对齐部分 对齐的使用: 1.__align(num)
如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址 是 0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变 量按照 类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取 时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做 法是显式的插入 reserved 成员:
还是让我们来看看例子。
示例 1: struct BF1 {
char f1 : 3; char f2 : 4; char f3 : 5; }; 其内存布局为: |__f1___|____f2___ |__|____f3______|______| |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__| 位域类型为 char,第 1 个字节仅能容纳下 f1 和 f2,所以 f2 被压缩到第 1 个字节 中,而 f3 只 能从下一个字节开始。因此 sizeof(BF1)的结果为 2。 示例 2: struct BF2 { char f1 : 3; short f2 : 4; char f3 : 5; }; 由于相邻位域类型不同,在 VC6 中其 sizeof 为 6,在 Dev-C++中为 2。 示例 3:
struct BF3 {
char f1 : 3; char f2; char f3 : 5; }; 非位域字段穿插在其中,不会产生压缩,在 VC6 和 Dev-C++中得到的大小均为 3。
五.如何修改编译器的默认对齐值? 1.在 VC IDE 中,可以这样修改:[Project]|[Settings],c/c++选项卡 Category 的 Code Generation 选项的 Struct Member Alignment 中修改,默认是 8 字节。 2.在编码时,可以这样动态修改:#pragma pack .注意:是 pragma 而不是 progma. 六.针对字节对齐,我们在编程中如何考虑?
sizeof 字节的对齐,位域 sizeof 的计算
分类: 技术 2009-03-23 21:45 1411 人阅读 评论(0) 收藏 举报
struct 编译器数据结构 alignmentfloat 汇编
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照 byte 划分的,从理论上讲似乎对任何类型的
面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍; 3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6 采取 不压缩方式,Dev-C++和 GCC 采取压缩方式; 4) 如果位域字段之间穿插着非位域字段,则不进行压缩; 5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
struct A{ char a; char reserved[3];//使用空间换时间 int b;
}
reserved 成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐 的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加
上它只是起到显式的提醒作用. 七.字节对齐可能带来的隐患:
变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常 在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列, 而不是顺序的一个接一个的排放,这就是对齐。
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些 平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的 CPU 在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程 必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适 合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每 次读都是从偶地址开始,如果一个 int 型(假设为 32 位系统)如果存放在偶地 址开始的地方,那么一个读周期就可以读出这 32bit,而如果存放在奇地址开始 的地方,就需要 2 个读周期,并对两次读出的结果的高低字节进行拼凑才能得到 该 32bit 数据。显然在读取效率上下降很多。
#pragma pack () /*取消指定对齐,恢复缺省对齐*/ sizeof(struct C)值是 8。 修改对齐值为 1: #pragma pack (1) /*指定按 1 字节对齐*/ struct D {
char b; int a; short c; }; #pragma pack () /*取消指定对齐,恢复缺省对齐*/ sizeof(struct D)值为 7。 后面我们再讲解#pragma pack()的作用. 三.编译器是按照什么样的原则进行对齐的? 先让我们看四个重要的基本概念: 1.数据类型自身的对齐值: 对于 char 型数据,其自身对齐值为 1,对于 short 型为 2,对于 int,float,double 类型,其自身对齐值为 4,单位字节。 2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。 3.指定对齐值:#pragma pack (value)时的指定对齐值 value。 4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。 有 了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐 方式。有效对齐值 N 是最终用来决定数据存放地址方式的值,最重要。有效对 齐 N,就是表示“对齐在 N 上”,也就是说该数据的"存放起始地址%N=0".而数据 结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址 就是数据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据 自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对 齐值的整数倍,结合下面例子理解)。这样就不能理解上面的几个例子的值了。 例子分析:
同理,分析上面例子 C: #pragma pack (2) /*指定按 2 字节对齐*/ struct C {
char b; int a; short c; }; #pragma pack () /*取消指定对齐,恢复缺省对齐*/ 第 一个变量 b 的自身对齐值为 1,指定对齐值为 2,所以,其有效对齐值为 1, 假设 C 从 0x0000 开始,那么 b 存放在 0x0000,符合 0x0000%1= 0;第二个变量,自身对齐值为 4,指定对齐值为 2,所以有效对齐值为 2,所以 顺序存放在 0x0002、0x0003、0x0004、0x0005 四个连续 字节中,符合 0x0002%2=0。第三个变量 c 的自身对齐值为 2,所以有效对齐值 为 2,顺序存放 在 0x0006、0x0007 中,符合 0x0006%2=0。所以从 0x0000 到 0x00007 共八字节存放的是 C 的变量。又 C 的自身对齐值为 4,所以 C 的有效对齐值为 2。又 8%2=0,C 只占用 0x0000 到 0x0007 的八个字节。所以 sizeof(struct C)=8.
二.字节对齐对程序的影响: 先让我们看几个例子吧(32bit,x86 环境,gcc 编译器):
设结构体如下定义: struct A {
int a; char b; c;
相关文档
最新文档