內表、結構賦值轉換規則

內錶轉換規則

內表只能被轉換成其他內表,而不能轉換成結構或基本類型。

 

一個內表能否轉換成其他內表與內表中的現有數據行沒有關係,而是看兩個內表的行結構是否可轉換。

 

只要類型行是可以轉換的,則內表就可以轉換

C語言中的結構對齊

C中結構的內存分配是這樣的:編譯器會按照成員列表的順序(聲明的順序)一個接一個地給每個成員分配內存,只有當存儲成員時需要滿足正確的邊界要求時,成員之間纔可能出現用於填充的額外內存空間(被浪費掉了的),如下面圖中的灰色地帶:

#include <stddef.h>

       typedefstruct ALIGN {

       chara;

       intb;

       charc;

    }ALIGN;

    printf("%d"offsetof(struct ALIGN,a));//0

    printf("%d", offsetof(struct ALIGN,b));//4

    printf("%d", offsetof(struct ALIGN,c));//8

    printf("%d"sizeof (struct ALIGN));//12

image048

如果編譯器有成員對齊這一要求時,會按照最長類型來分配每一個成員,如上面的a成員,在整型類型長度爲4字節的機器上,由於a是一個字符型,雖然本身只需一個字節,但也爲a分配了4個字節,這將浪費3個字節的空間,c也是一樣,此時需要總共12個字節的空間。如果將短的類型放在一起,這將會節約空間(此時只需要8個字節的空間):

    typedefstruct ALIGN {

       intb;

       chara;

       charc;

    }ALIGN;

    printf("%d", offsetof(struct ALIGN,b));//0

    printf("%d", offsetof(struct ALIGN,a));//4

    printf("%d", offsetof(struct ALIGN,c));//5

    printf("%d"sizeof (struct ALIGN));//8

image049

下面與上面也是一樣節約空間:

    typedefstruct ALIGN {

       chara;

       char c;

       int b;

    }ALIGN;

    printf("%d", offsetof(struct ALIGN,a));//0

    printf("%d", offsetof(struct ALIGN,c));//1

    printf("%d", offsetof(struct ALIGN,b));//4

    printf("%d"sizeof (struct ALIGN));//8

 

sizeof操作符能夠得出一個結構體的整體長度,包括因邊界對齊而填充的那些字節,如果想得到每個成員偏離結構首的字節數,則可以使用offsetof宏。

 

按照成員所佔空間大小降序排列結構成員的聲明可以最大限度地減少結構存儲中浪費的內存空間。sizeof返回的值包含了結構中浪費的內存空間。

ABAP結構體對齊

ABAP中與C中是一樣的,當組件的成員爲混合類型時,就會出現對齊要求,如:

DATA: BEGIN OF struc,
      c,
      x TYPE x,
  END OF struc.
DATA: bits TYPE i,
      descr_ref TYPE REF TO cl_abap_structdescr.
descr_ref ?= cl_abap_structdescr=>describe_by_data( struc ).
bits = descr_ref->length.
WRITE :/ 'struc : ' , bits , ' byte'.

struc :           4   byte

 

與C程序中的結構一樣,以所佔空間最大的成員單位進行對齊。下面結構就不存在對齊要求:

DATA: BEGIN OF struc,
      x TYPE x,
      x1 TYPE x,
      x2 TYPE x,
  END OF struc.
DATA: bits TYPE i,
      descr_ref TYPE REF TO cl_abap_structdescr.
descr_ref ?= cl_abap_structdescr=>describe_by_data( struc ).
bits = descr_ref->length.
WRITE :/ 'struc : ' , bits , ' byte'.

struc :           3   byte

 

在兩個結構體之間轉換或賦值時需要考慮對齊問題。

結構體相互賦值轉換規則

結構是否可轉換(相互賦值)主要由結構的聲明佈局決定。

The Unicode fragment view splits the structure into fragments as follows:

某個結構將根據下面的規則分成多個Unicode段視圖:

  • X類型組件在一起連續聲明時,會形成連續的X類型片段,中間不會出現對齊的gap,對齊只會發生在X段最後面(具體補多少,則根據結構體中類型最長的組件來決定)
  • 類型C,N,D, and T這些類型在一起連續聲明時,會形成連續的C類型片段,中間不會出現對齊的gap,對齊只會發生在C片段最後面(具體補多少,則根據結構體中類型最長的組件來決定)
  • 其它類型的組件,如IFPSTRINGXSTRING引用類型內表——————每個組件都會形成獨立的不同類型的連續片段。

Thus there are no alignment gaps within each fragment in the Unicode fragment view. In Unicode systems, the order and formation of fragments in operands is compared, to determine the convertibility of structures.

每一種fragment片斷內部是連續,在其內部是不存在補齊的空白字節,但可能發生片斷尾部。

個結果是否可以轉換,主要是看fragment片段的種類(X、C、I、F、P、STRING、XSTRING、引用類型、內表)、fragment佈局順序、以及每種fragment的長度要相同(或者fragment尾部所補對齊要相同——但如果某個結構是另一結構的子佈局,最後一個fragment長度並不要求一樣,只要類型一樣即可)。

不同長度結構體賦值(指在佈局相同的情況下)

如果將一個結構賦給一個短的結構,源結構將會被截。如果將一個結構賦給長的結構,末尾不足的地方字符類型使用空格填充(包括日期與NUM類型),數字類型會使用0來初始化。

DATA: BEGIN OF fs1,
  int TYPE i VALUE 5,
  pack TYPE p DECIMALS 2 VALUE '2.26',
  text(10) TYPE c VALUE 'fine text',
  float TYPE f VALUE '1.234e+05',
  data TYPE d VALUE '19950916',
END OF fs1.
DATA: BEGIN OF fs2,
  int TYPE i VALUE 3,
  pack TYPE p DECIMALS 2 VALUE '72.34',
  text(5) TYPE c VALUE 'hello',
END OF fs2.
WRITE: / fs1-int, fs1-pack, fs1-text, fs1-float, fs1-data.
WRITE: / fs2-int, fs2-pack, fs2-text.
MOVE fs1 TO fs2.
WRITE: / fs2-int, fs2-pack, fs2-text.

         5              2.26  fine text    1.2340000000000000E+05 19950916

         3             72.34  hello

         5              2.26  fine

可相互轉換結構

DATA: BEGIN OF struc1,
        a(1) TYPE x,
        b(1) TYPE x,
        c(6) TYPE c,
f TYPE f ,
      END OF struc1.

DATA: BEGIN OF struc2,
        a(2) TYPE x,
        b(2) TYPE c,
        c(4) TYPE n,
f TYPE f ,
      END OF struc2.

The Unicode fragment view of both structures is: 
     X(2)
     C(6)
      F(8)

struc1 can be assigned to struc2 in Unicode systems.

如果將struc2的a的長度修改爲其他值,則不可轉換,但如果在struc2的尾部,即f字段後面加上一個其他任何類型的字段,這兩個結構都是可以相互賦值轉換的

不可相互轉換結構

DATA: BEGIN OF struc1,
        a    TYPE d,
        b    TYPE t,
        c    TYPE f,
        d(2) TYPE x,
        e(4) TYPE x,
        f(8) TYPE c,
      END OF struc1.

DATA: BEGIN OF struc2,
        a    TYPE d,
        b    TYPE t,
        BEGIN OF struc3,
          c    TYPE f,
          d(2) TYPE x,
        END OF struc3,
        e(4) TYPE x,
        f(8) TYPE c,
      END OF struc2.

DATA: len1 TYPE i,len2 TYPE i.

DESCRIBE FIELD struc1 LENGTH  len1 IN BYTE MODE.

DESCRIBE FIELD struc2 LENGTH  len2 IN BYTE MODE.

WRITE:/ len1,len2. "64          72

The Unicode fragment view of the two structures is: 

  struc1                  struc2
   C(
14字符=28字節)後面補4字節                             C(14字符=28字節)後面補4字節 
   F(8字節)                              F(8字節)
   X(6
字節)後面補2字節                    X(2字節)後面補6字節
   C(8字符=16字節)                       X(4字節)後面補4字節
                                        C(8字符=16字節)

在內部嵌套結構struc3中發生了對齊(注:嵌套結構尾部與外部結構相鄰字段即使類型相同,但他們形成的fragment片段是獨立的,不會合併在一起,即這裏的d與e兩個字段),並在struc2與內部嵌套結構struc3之間(即d與e之間)填補了對齊空白,但這種對齊空白在struc1中沒有發生;

如果去掉struc2的e與f,則這兩個結構是可以轉換的(因爲此時struc2比struc1要短,並且此時struc2現有的fragment片段佈局與struc1基本上一樣——除最後不一樣,但因struc2比struc1要短,所以可以忽略尾部對齊大小);

但如果只去掉struc2的e字段,還是不能相互轉換,因爲此時雖然長度一樣,但佈局還是不一樣(struc2的d字段後面補了6字節對齊空白,而struc1的e字段後面只需補2字節的對齊空白————雖然此時形成 的X類型fragment片段總體長度都是8字節,但從佈局上來看還是不一樣的)

縱深結構體賦值轉換

含有縱深類型的結構也是可以相互轉換的,但結構中相鄰同類型字段並不會合併爲一個fragment,所以如果有縱深類型的組件的兩個結構可轉換時需要這兩個結構中所聲明的字段個數、類型、位置要完全一樣(包括兩個結構體的長度也要一樣),否則也是不能轉換的,如下面兩個結構是可以相互轉換:

DATA: BEGIN OF struc1,
        a(1) TYPE c,
        b(1) TYPE c,
        s TYPE string,
      END OF struc1.
DATA: BEGIN OF struc2,
        a(1) TYPE c,
        b(1) TYPE c,
        s TYPE string VALUE 'string',
      END OF struc2.

但下面兩個結構是不能相互轉換的:

DATA: BEGIN OF struc1,
        a(1) TYPE c,
        b(1) TYPE c,
        s TYPE string,
      END OF struc1.
DATA: BEGIN OF struc2,
        a(2) TYPE c,
        s TYPE string VALUE 'string',
      END OF struc2.

MOVE-CORRESPONDING(結構體賦值)

MOVE-CORRESPONDING <struct1>TO<struct2>.

該語句將struct1中與struct2中名稱相同的組件複製過去

 

使用MOVE或“=”進行結構體賦值時,不是按照對應的組件名來進行的,它只與聲明的順序與類型有關,如果類型不同會出錯,可以進行賦值轉換的需要滿足結構體相互賦值轉換規則(參考上面)

 

原文出自 江正軍 技術博客,博客鏈接:www.cnblogs.com/jiangzhengjun
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章