c语言 - 如何解释 *( (字符*)&a )



我看到了一种了解平台端序的方法,就是这个程序,但我不理解它

#include <stdio.h>
int main(void)
{
  int a = 1;
  if( *( (char*)&a ) == 1) printf("Little Endiann");
  else printf("Big Endiann");
  system("PAUSE");  
  return 0;
}

这个测试做什么?

int几乎总是大于一个字节,并且经常跟踪体系结构的字大小。例如,32位体系结构可能具有32位int。因此,给定典型的32位整数,4个字节的布局可能是:

   00000000 00000000 00000000 00000001

或者先用最低有效字节:

   00000001 00000000 00000000 00000000

char*是一个字节,所以如果我们将这个地址转换为char*,我们将获得上面的第一个字节,或者

   00000000

   00000001

因此,通过检查第一个字节,我们可以确定体系结构的字节序。

这只适用于sizeof(int) > 1。举个例子,我们假设它是2,并且char是8位。

基本上,对于little-endian,数字1作为一个16位整数看起来是这样的:

00000001 00000000

但对于big-endian,它是:

00000000 00000001

因此,首先代码设置a = 1,然后这个:

*( (char*)&a ) == 1)

获取a的地址,将其视为指向char的指针,并取消对其的引用。因此:

  • 如果a包含一个小的endian整数,您将得到00000001部分,当作为char 插入时,它是1

  • 如果a包含一个大端数整数,那么您将得到00000000。对== 1的检查将失败,代码将假定平台是big-endian。

您可以使用int16_tint8_t而不是intchar来改进此代码。或者更好的是,只需检查htons(1) != 1

  • 您可以将整数视为4个字节的数组(在大多数平台上)。一个小端序整数将具有值01 00 00 00和一个大端序00 00 00 01
  • 通过执行&a,您可以获得该数组的第一个元素的地址
  • 表达式(char*)&a将其强制转换为单个字节的地址
  • 最后*( (char*)&a )得到该地址所包含的值
  1. a的地址
  2. 将其投射到char*
  3. 取消引用此char*,这将为您提供int第一个字节
  4. 检查它的值——如果它是1,那么它就是小端序。否则——大

假设sizeof(int) == 4,则:

|........||........||........||........|    <- 4bytes, 8 bits each for the int a
| byte#1 || byte#2 || byte#3 || byte#4 |

当执行步骤1、2和3时,*( (char*)&a )将为您提供第一个字节| byte#1 |

然后,通过检查byte#1的值,您可以了解它是big还是little endian。

程序只是将int占用的空间重新解释为chars的数组,并假设作为int的1将存储为一系列字节,其中最低阶为值为1的字节,其余为0。

因此,如果最低阶字节首先出现,那么平台是小端序,否则是大端序。

这些假设可能不适用于现有的每个平台。

a = 00000000 00000000 00000000 00000001
    ^                                 ^
    |                                 |
    &a if big endian                  &a if little endian
    00000000                   00000001
    ^                                 ^
    |                                 |
    (char*)&a for BE                  (char*)&a for LE
    *(char*)&a = 0 for BE             *(char*)&a = 1 for LE

以下是它的分解方式:

           a        -- given the variable a
          &a        -- take its address; type of the expression is int *
  (char *)&a        -- cast the pointer expression from type int * to type char *
*((char *)&a)       -- dereference the pointer expression
*((char *)&a) == 1  -- and compare it to 1

基本上,强制转换(char *)&a将表达式&a的类型从指向int的指针转换为指向char的指针;当我们将解引用运算符应用于结果时,它会给出存储在a的第一个字节中的值。

*( (char*)&a )

在BigEndian中,int i=1(大小为4字节)的数据将在内存中排列为:-(从较低地址到较高地址)。

00000000 -->Address 0x100
00000000 -->Address 0x101
00000000 -->Address 0x102
00000001 -->Address 0x103

而LittleEndian是:-

00000001 -->Address 0x100
00000000 -->Address 0x101
00000000 -->Address 0x102
00000000 -->Address 0x103

分析以上铸件:-

还有&a= 0x100,因此
*((char*)0x100)意味着考虑一次取一个字节(因为int加载了4个字节),因此0x100处的数据将被引用。

*( (char*)&a ) == 1 => (*0x100 ==1) that is 1==1 and so true,implying its little endian. 

最新更新