内表、结构赋值转换规则

摘要:
内部表转换规则…57C结构对齐…57ABAP结构对齐…58结构相互分配转换规则…59MOVE-CORRESPONSING…62内部表转换准则内部表只能转换为其他内部表,不能转换为结构或基本类型。根据成员占用的空间按降序声明结构成员可以最小化结构存储中浪费的内存空间=cl_abap_structdescr=˃describe_by_data。bits=descr_ref-˃length。写入:/“结构:”,bits,“字节”。struc:3byte在转换或分配两个结构之间的值时需要考虑对齐。结构相互赋值的转换规则结构是否可以转换主要取决于结构的声明布局。如果将结构分配给短结构,则源结构将被截断。

内表转换规则... 57

C语言中的结构对齐... 57

ABAP结构体对齐... 58

结构体相互赋值转换规则... 59

MOVE-CORRESPONDING(结构体赋值)... 62

内表转换规则

内表只能被转换成其他内表,而不能转换成结构或基本类型。

一个内表能否转换成其他内表与内表中的现有数据行没有关系,而是看两个内表的行结构是否可转换。

只要类型行是可以转换的,则内表就可以转换

C语言中的结构对齐

C中结构的内存分配是这样的:编译器会按照成员列表的顺序(声明的顺序)一个接一个地给每个成员分配内存,只有当存储成员时需要满足正确的边界要求时,成员之间才可能出现用于填充的额外内存空间(被浪费掉了的),如下面图中的灰色地带:

#include<stddef.h>

typedefstructALIGN {

chara;

intb;

charc;

}ALIGN;

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

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

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

printf("%d",sizeof(structALIGN));//12

image048

如果编译器有成员对齐这一要求时,会按照最长类型来分配每一个成员,如上面的a成员,在整型类型长度为4字节的机器上,由于a是一个字符型,虽然本身只需一个字节,但也为a分配了4个字节,这将浪费3个字节的空间,c也是一样,此时需要总共12个字节的空间。如果将短的类型放在一起,这将会节约空间(此时只需要8个字节的空间):

typedefstructALIGN {

intb;

chara;

charc;

}ALIGN;

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

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

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

printf("%d",sizeof(structALIGN));//8

image049

下面与上面也是一样节约空间:

typedefstructALIGN {

chara;

charc;

intb;

}ALIGN;

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

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

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

printf("%d",sizeof(structALIGN));//8

sizeof操作符能够得出一个结构体的整体长度,包括因边界对齐而填充的那些字节,如果想得到每个成员偏离结构首的字节数,则可以使用offsetof宏。

按照成员所占空间大小降序排列结构成员的声明可以最大限度地减少结构存储中浪费的内存空间sizeof返回的值包含了结构中浪费的内存空间。

ABAP结构体对齐

ABAP中与C中是一样的,当组件的成员为混合类型时,就会出现对齐要求,如:

DATA: BEGINOF struc,
c
,
xTYPEx
,
ENDOF
struc.
DATA: bits TYPEi
,
descr_ref
TYPEREFTO
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: BEGINOF struc,
xTYPEx
,
x1
TYPEx
,
x2
TYPEx
,
ENDOF
struc.
DATA: bits TYPEi
,
descr_ref
TYPEREFTO
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 arenoalignment 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段的种类(XCIFPSTRINGXSTRING、引用类型、内表)、fragment布局顺序、以及每种fragment的长度要相同(或者fragment尾部所补对齐要相同——但如果某个结构是另一结构的子布局,最后一个fragment长度并不要求一样,只要类型一样即可)

不同长度结构体赋值(指在布局相同的情况下)

如果将一个结构赋给一个短的结构,源结构将会被截。如果将一个结构赋给长的结构,末尾不足的地方字符类型使用空格填充(包括日期与NUM类型),数字类型会使用0来初始化。

DATA: BEGINOF fs1,
int
TYPEiVALUE5
,
packTYPE p DECIMALS2VALUE'2.26'
,
text(10) TYPEcVALUE'fine text'
,
float
TYPE f VALUE'1.234e+05'
,
dataTYPE d VALUE'19950916'
,
ENDOF
fs1.
DATA: BEGINOF
fs2,
int
TYPEiVALUE3
,
packTYPE p DECIMALS2VALUE'72.34'
,
text(5) TYPEcVALUE'hello'
,
ENDOF
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) TYPEc,
f TYPE f ,
END OF struc1.
DATA: BEGIN OF struc2,
a(2) TYPE x,
b(2) TYPE c,
c(4) TYPEn,
f TYPE f ,
END OF struc2.

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

struc1can be assigned tostruc2in Unicode systems.

如果将struc2a的长度修改为其他值,则不可转换,但如果在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片段是独立的,不会合并在一起,即这里的de两个字段),并在struc2与内部嵌套结构struc3之间(即de之间)填补了对齐空白,但这种对齐空白在struc1中没有发生;

如果去掉struc2ef,则这两个结构是可以转换的(因为此时struc2struc1要短,并且此时struc2现有的fragment片段布局与struc1基本上一样——除最后不一样,但因struc2struc1要短,所以可以忽略尾部对齐大小)

但如果只去掉struc2e字段,还是不能相互转换,因为此时虽然长度一样,但布局还是不一样(struc2d字段后面补了6字节对齐空白,而struc1e字段后面只需补2字节的对齐空白————虽然此时形成 的X类型fragment片段总体长度都是8字节,但从布局上来看还是不一样的)

纵深结构体赋值转换

含有纵深类型的结构也是可以相互转换的,但结构中相邻同类型字段并不会合并为一个fragment,所以如果有纵深类型的组件的两个结构可转换时需要这两个结构中所声明的字段个数、类型、位置要完全一样(包括两个结构体的长度也要一样),否则也是不能转换的,如下面两个结构是可以相互转换:

DATA: BEGINOF struc1,
a(
1) TYPEc
,
b(
1) TYPEc
,
s
TYPE
string,
ENDOF
struc1.
DATA: BEGINOF
struc2,
a(
1) TYPEc
,
b(
1) TYPEc
,
s
TYPE string VALUE'string'
,
ENDOF
struc2.

但下面两个结构是不能相互转换的:

DATA: BEGINOF struc1,
a(
1) TYPEc
,
b(
1) TYPEc
,
s
TYPE
string,
ENDOF
struc1.
DATA: BEGINOF
struc2,
a(
2) TYPEc
,
s
TYPE string VALUE'string'
,
ENDOF
struc2.

MOVE-CORRESPONDING(结构体赋值)

MOVE-CORRESPONDING<struct1>TO<struct2>.

该语句将struct1中与struct2名称相同的组件复制过去

使用MOVE或“=”进行结构体赋值时,不是按照对应的组件名来进行的,它只与声明的顺序与类型有关,如果类型不同会出错,可以进行赋值转换的需要满足结构体相互赋值转换规则(参考上面)

免责声明:文章转载自《内表、结构赋值转换规则》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux服务器,服务管理--systemctl命令详解,设置开机自启动java内存区域下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

openssl 学习之从证书中提取RSA公钥N 和 E

原文链接:http://blog.csdn.net/kkxgx/article/details/19850509 通常数字证书包含很多信息,其中N和E值即我们称为的公钥。如何从PEM 或者DER格式的证书中提出证书呢?下面给出代码实现从PEM和DER编码的证书中提出N、E。 [cpp]view plaincopy #include<open...

1027. 打印沙漏

1027. 打印沙漏(20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印 ***** *** * *** ***** 所谓“沙漏形状”,是指每行输...

usb设备 配置 接口 端点

在USB设备的逻辑组织中,包含设备、配置、接口和端点4个层次。每个USB设备都提供了不同级别的配置信息,可以包含一个或多个配置,不同的配置使设备表现出不同的功能组合(在探测/连接期间需从其中选定一个),配置由多个接口组成。在USB协议中,接口由多个端点组成,代表一个基本的功能,是USB设备驱动程序控制的对象,一个功能复杂的USB设备可以具有多个接口。每个配...

SQL 存储过程入门(变量)

SQL 存储过程入门(变量)(二)上一篇我们讲到了SQL存储过程的基本定义,怎么创建,使用,这篇就来讲一下变量的使用。 变量分文局部变量和全局变量 局部变量是@开头,全局变量是@@开头,这里我们主要讲局部变量,全局变量我们后面再讲。 在c# 语言中,定义一个变量很简单,例如 int i=0; --定义加赋值。 在sql中,定义一个变量需要关键字DECLAR...

27、Windows内核编程,IRP的同步(1)

对设备的任何操作都会转化为IRP请求,而IRP一般都是由操作系统异步发送的。但是有时需要同步来避免逻辑错误。同步方法有:StartIO例程,使用中断服务例程等。 1、应用程序对设备的同步异步操作 1)同步操作原理 大部分IRP是由应用程序的Win32 API发起。这些函数本身就支持同步异步操作。如ReadFile,WriteFile,DeviceIoCon...

双端队列的应用

双端队列是一种特殊队列。它是在线性表的两端对插入和删除操作限制的线性表。双端队列能够在队列的不论什么一端进行插入删除操作。#include <stdio.h> #define QUEUESIZE 8 typedef char ElemType; typedef struct DQueue { ElemType qu...