1. 結構體中元素的地址

我們知道,結構體一般包括很多元素,結構體的大小為所有元素的大小總和(包括字節對齊)。

那麼在結構體中,不同元素之間的地址相對位置是什麼關係呢?

是先定義的元素地址在低地址還是後定義的元素地址在低地址呢?

我們通過一段代碼來測試一下(我電腦型號為R9000P,AMD處理器,x86架構,win10操作系統,DevC++)

#include <stdio.h>
typedef struct {
	int a;
	int b;
}Test;
Test test1;
int main() {
	Test test2;
	printf("test1的a地址為%d,b地址為%d\n", &test1.a, &test1.b);
	printf("test2的a地址為%d,b地址為%d\n", &test2.a, &test2.b);
	return 0;
}

運行結構如下圖所示

codesys結構體地址和結構描述_codesys結構體地址和結構描述

這邊一起測試了一下全局變量和局部變量的情況。

test1為全局變量(存儲在堆區),test2為局部變量(存儲在棧區)。

可以看出都是先定義的元素在低地址,後定義的元素在高地址。

2. 大小端的概念(字節大小端、位的大小端)


舉例説明字節大小端:

內存地址

0x00004000

0x00004001

0x00004002

0x00004003

0X12

0x34

0x56

0X78

  • 如果是大端處理器:這段數代表:0x12345678;
  • 如果是小段處理器:這段數代表:0x78563412 ;

可以用代碼測試一下本機的字節大小端

#include <stdio.h>
typedef union {
	int a;
	char b[4];
}Test;

int main() {
	Test test1;
	test1.a = 1;
	printf("b數組的第四個元素的值為%d", test1.b[0]);
	return 0;
}

運行結果如下圖

codesys結構體地址和結構描述_#c語言_02

我們知道對於數組,低索引的元素是位於低地址的,根據數組b的第一個元素為1可以看出,測試電腦是字節小端模式。


對於二進制數10011101B

  • 如果在內存中的位置為(LSB)10111001(MSB),則為小端模式;
  • 如果內存中的位置為(MSB)10011101(LSB),則為大端模式。

繼續可以用代碼測試一下位的大小端:

#include <stdio.h>
typedef union {
	int  a;
	struct {
		unsigned int d1:1;
		unsigned int d:30;
		unsigned int d2:1;
	}bitField;
}Test;

int main() {
	Test test1;
	test1.a = 1;
	printf("bitField的值d1為%d\n", test1.bitField.d1);
	printf("bitField的值d2為%d", test1.bitField.d2);
	return 0;
}

運行結果如下圖:

codesys結構體地址和結構描述_#c語言_03

通過運行結果可知,此係統的位的大小端為小端模式,d1代表最低位LSB。

再看一段代碼

#include "stdio.h" 
struct kk 
{ 
unsigned a:2; 
unsigned b:3; 
unsigned c:2; 
unsigned d:1; 
} 
kt; 
int main() 
{ 
        char result =3; 
        memcpy(&kt,&result,1); 
        printf(" a = %d, b = %d, c = %d, d = %d,ok/n",kt.a,kt.b,kt.c,kt.d); 
        return 1; 
}

在sun unix上用cc編譯,結果為0,0,1,1

在2000上用VC6.0編譯,結果為3,0,0,0

C語言的位域中,每個field是嚴格按照bit地址從低到高排列的:

==============

-低->->->高-

a b c d

==============

接下來看如何解析這個字節。

在little-endian機器上,result字節中各個比特的存放排列如下所示

==============

-低->->->高-

11000000

==============

對應到四個位域,得

a=3

b=0

c=0

d=0

在big-endian機器上,result字節中各個比特的存放排列如下所示

==============

-低->->->高-

00000011

==============

對應到四個位域,得

a=0

b=0

c=1

d=1


總結:

  1. C語言的位域類型使用時,各個field的擺放是按從低到高的bit順序排列的。
  2. 把數據的存放和解析分開,就可以很容易解釋字節序的問題。