字节对齐

首先工作经验告诉我们,定义结构体时,变量类型从小到大的顺序比较好,并且相同类型的变量尽量放一块。部分来自抄袭:

1、类

1、这是类为空的情况:
 
 
2、注意下面这种情况:
 
 
2、sizeof和strlen
 

sizeof():是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,

                       参数可以是数组、指针、类型、对象、函数等。

   功能是:获得保证能容纳实现所建立的最大对象的字节大小。

 

strlen():是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,

                         实际上数组就退化成指针了。

   功能是:返回字符串的长度。该字符串可能是自己定义的,也可能是内存中随机的,该函数实际

                        完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符NULL。

                        返回的长度大小不包括NULL。

 

1、

char* ss = "0123456789"; 

        sizeof(ss);    //结果 4 ;

        sizeof(*ss);  //结果 1;*ss其实是获得了字符串的第一位'0'所占的内存空间;

        strlen(ss);   //结果是10 ;

 

char str[20] = "0123456789"

         sizeof(str) = 20

         strlen(str) = 10

char str[] = "abc\0"

                 strlen(str) = 3;

                 sizeof(str) = 5;

char*str="i am ok!"

      sizeof(str)=4,     因为str是个指针变量,
     sizeof("i am ok!")=9;这里有5个字符,2个空格,1个叹号,还有字符串的结束符‘/0';
 

2、

int *p = NULL;     //  sizeof(p)=4,    sizeof(*p)=4

int a[100];          // sizeof(a)=400,   sizeof(&a)=4 ,     sizeof(a[100])=4 ,  sizeof(&a[0])=4

int b[100];

void fun(int b[100])

{   sizeof(b); }         //   sizeof(b)=4 

char (*pArray1)[4]={0};                             sizof(pArrya1)=4,
char (*pArray2[10])[4]={0};                       sizof(pArrya2)=40, 
char (*pArray3[100])[4]={0};                     sizof(pArrya3)=400                        

   3、

   int *p=malloc(100);  // sizeof(p) = 4         sizeof(p) 只能测定 指针大小,32位机上得4。    

                                                               sizeof 不能测定动态分配的数组大小

 

  int b[ ][3] = {{1},{3,2},{4,5,6},{0}};中,sizeof(b) = 48

3、字节对齐

对齐规则说起来太麻烦,直接用图表示,一眼就懂。

默认情况下4字节对齐

 

 

 1

1

4

=8

 

 1

4

1

=12

 

5

4

2

=16

 

 1

8

1

=24

好了,举例够多了,,,

另外,#pargma pack(n)表示约定n字节对齐,这个一般很少用。

 

4、大小端

提到字节对齐,就没道理不说大小端。

 

大端:较高的有效字节存放在较低的存储器地址,较低的有效字节存放在较高的存储器地址。

小端:较高的有效字节存放在较高的的存储器地址,较低的有效字节存放在较低的存储器地址。

假设从内存地址0x0000开始有以下数据:

内存地址:0x0000    0x0001    0x0002     0x0003

对应数据:0x12        0x34       0x56         0x78

如果我们去读取一个地址为0x0000的4字节变量

若字节序位为小端模式,读出为:0x78563412

若字节序位为大端模式,读出为:0x12345678

一般来说:X86系列的CPU都是小端字节序,powerPC通常是大端字节序。


int _tmain(int argc, _TCHAR* argv[])  
{  
     char *sz = "0123456789";  
     int *p = (int *)sz;  
     cout<<hex<<*++p<<endl;  
}  
运行结果为:37363534

分析:这里是小端字节序

地址从0x0000开始,那么sz在内存中的存储为:

内存地址:     0x00  0x01  0x02   0x03   0x04  0x05  0x06   0x07   0x08  0x09 

对应的值:      0      1     2      3      4     5     6      7     8      9

对应的值:      48     49    50     51     52    53    54     55    56     57

对应的16进制:0x30   0x31  0x32   0x33   0x34  0x35  0x36   0x37  0x38   0x39

                sz                         ++p

所以读取为:0x37363534。

那么,给你一个系统,怎么知道它是大端还是小端呢?

判断方法一:利用联合类型判断
union类型的主要特点如下:
union中可以定义多个成员,union的大小由最大的成员的大小决定;
union成员共享同一块大小的内存,一次只能使用其中的一个成员;
对某一个成员赋值,会覆盖其他成员的值;
联合体union的存放顺序是所有成员都从低地址开始存放。
所以我们可以定义联合体如下:

//method 1
union bit

{             //对齐原则,char与int指向的均是低位地址 

     int a;
    char b;
};
这个时候我们赋值 a = 0x12345678,如果低位字节的b存放的是0x78,则说明是小端模式,若为0x12则为大端模式:

#include <stdio.h>

union bit{//对齐原则,char与int指向的均是低位地址
int a;
char b;
};

int main(){
bit test;
test.a = 0x12345678;
if(test.b == 0x78)                       //如果低位地址保存的是1,即低位字节在低位地址,为小端
       printf("本机为小端模式\n");
else
       printf("本机为大端模式\n");
return 0;
}
判断方法二:利用强制类型转换判断
这种方式需要定义一个字节指针,指向int型的低位地址,因为要用到强制类型转换,故而称为利用强制类型转换的判断方法:
//method 2
void judge(void)

{
      int i = 0x12345678;
      char *p;
      p = (char *)&i;            //强制类型转换成char*型指针,指向的位置为低位地址
     if(*p == 0x78)               //低位地址存储的是低位字节,则为小端
    printf("本机为小端模式\n");
     else
      printf("本机为大端模式\n");

其实,知道了也没用!

posted @ 2020-07-03 22:34  道微真理  阅读(638)  评论(0编辑  收藏  举报