Structures, unions, enumerations, and bitfields in ARM C and C++

Non-Confidential   ARM DUI0375E
ARM Compiler v5.04 for µVision armcc User Guide Version 5
Home > C and C++ Implementation Details > Structures, unions, enumerations, and bitfields in ARM C and C++

10.4 Structures, unions, enumerations, and bitfields in ARM C and C++

Describes the implementation of the structured data types union, enum, and struct. It also discusses structure padding and bitfield implementation.

Unions

When a member of a union is accessed using a member of a different type, the resulting value can be predicted from the representation of the original type. No error is given.

Enumerations

An object of type enum is implemented in the smallest integral type that contains the range of the enum.
In C mode, and in C++ mode without --enum_is_int, if an enum contains only positive enumerator values, the storage type of the enum is the first unsigned type from the following list, according to the range of the enumerators in the enum. In other modes, and in cases where an enum contains any negative enumerator values, the storage type of the enum is the first of the following, according to the range of the enumerators in the enum:
  • unsigned char if not using --enum_is_int
  • signed char if not using --enum_is_int
  • unsigned short if not using --enum_is_int
  • signed short if not using --enum_is_int
  • signed int
  • unsigned int except C with --strict
  • signed long long except C with --strict
  • unsigned long long except C with --strict.

Note

In ARM Compiler 4.1 and later, the storage type of the enum being the first unsigned type from the list applies irrespective of mode.

Implementing enum in this way can reduce data size. The command-line option --enum_is_int forces the underlying type of enum to at least as wide as int.
See the description of C language mappings in the Procedure Call Standard for the ARM Architecture specification for more information.

Note

Care must be taken when mixing translation units that have been compiled with and without the --enum_is_int option, and that share interfaces or data structures.
In strict C, enumerator values must be representable as ints. That is, they must be in the range -2147483648 to +2147483647, inclusive. A warning is issued for out-of-range enumerator values:
#66: enumeration value is out of "int" range
Such values are treated the same way as in C++, that is, they are treated as unsigned int, long long, or unsigned long long.
To ensure that out-of-range Warnings are reported, use the following command to change them into Errors:
armcc --diag_error=66 ...

Structures

The following points apply to:
  • all C structures
  • all C++ structures and classes not using virtual functions or base classes.
Structures can contain padding to ensure that fields are correctly aligned and that the structure itself is correctly aligned. The following diagram shows an example of a conventional, nonpacked structure. Bytes 1, 2, and 3 are padded to ensure correct field alignment. Bytes 11 and 12 are padded to ensure correct structure alignment. The sizeof() function returns the size of the structure including padding.
Figure 10-1 Conventional nonpacked structure example

The compiler pads structures in one of the following ways,
according to how the structure is defined:
  • Structures that are defined as static or extern are padded with zeros.
  • Structures on the stack or heap, such as those defined with
    malloc() or auto, are
    padded with whatever is previously stored in those memory locations. You cannot
    use memcmp() to compare padded structures defined in this
    way.
Use the --remarks option to view the messages that are
generated when the compiler inserts padding in a struct.
Structures with empty initializers are permitted in C++:
struct
{
int x;
} X = { };
However, if you are compiling C, or compiling C++ with the --cpp and--c90 options, an error is generated.

Packed structures

A packed structure is one where the alignment of the structure, and of the fields within it, is always 1.
You can pack specific structures with the __packed qualifier. Alternatively, you can use #pragma pack(n) to make sure that any structures with unaligned data are packed. There is no command-line option to change the default packing of structures.

Bitfields

In nonpacked structures, the ARM compiler allocates bitfields in containers. A container is a correctly aligned object of a declared type.
Bitfields are allocated so that the first field specified occupies the lowest-addressed bits of the word, depending on configuration:
Little-endian
Lowest addressed means least significant.
Big-endian
Lowest addressed means most significant.
A bitfield container can be any of the integral types.

Note

In strict 1990 ISO Standard C, the only types permitted for a bit field are int, signed int, and unsigned int. For non-int bitfields, the compiler displays an error.
A plain bitfield, declared without either signed or unsigned qualifiers, is treated as unsigned. For example, int x:10 allocates an unsigned integer of 10 bits.
A bitfield is allocated to the first container of the correct type that has a sufficient number of unallocated bits, for example:
struct X
{
int x:10;
int y:20;
};
The first declaration creates an integer container and allocates 10 bits to x. At the second declaration, the compiler finds the existing integer container with a sufficient number of unallocated bits, and allocates y in the same container as x.
A bitfield is wholly contained within its container. A bitfield that does not fit in a container is placed in the next container of the same type. For example, the declaration of z overflows the container if an additional bitfield is declared for the structure:
struct X
{
int x:10;
int y:20;
int z:5;
};
The compiler pads the remaining two bits for the first container and assigns a new integer container for z.
Bitfield containers can overlap each other, for example:
struct X
{
int x:10;
char y:2;
};
The first declaration creates an integer container and allocates 10 bits to x. These 10 bits occupy the first byte and two bits of the second byte of the integer container. At the second declaration, the compiler checks for a container of type char. There is no suitable container, so the compiler allocates a new correctly aligned char container.
Because the natural alignment of char is 1, the compiler searches for the first byte that contains a sufficient number of unallocated bits to completely contain the bitfield. In the example structure, the second byte of the int container has two bits allocated to x, and six bits unallocated. The compiler allocates a char container starting at the second byte of the previous int container, skips the first two bits that are allocated to x, and allocates two bits to y.
If y is declared char y:8, the compiler pads the second byte and allocates a new char container to the third byte, because the bitfield cannot overflow its container. The following figure shows the bitfield allocation for the following example structure:
struct X
{
int x:10;
char y:8;
};
Figure 10-2 Bitfield allocation 1

Note

The same basic rules apply to bitfield declarations with different
container types. For example, adding an int bitfield to the example structure gives:
struct X
{
int x:10;
char y:8;
int z:5;
}
The compiler allocates an int container starting at the same location as the int x:10 container and allocates a byte-aligned char and 5-bit bitfield, as follows:
Figure 10-3 Bitfield allocation 2

You can explicitly pad a bitfield container by declaring an unnamed
bitfield of size zero. A bitfield of zero size fills the container up to the end
if the container is not empty. A subsequent bitfield declaration starts a new
empty container.

Note

As an optimization, the compiler might overwrite padding bits in a
container with unspecified values when a bitfield is written. This does not
affect normal usage of bitfields.

Bitfields in packed structures

Packed bitfield containers, including all bitfield containers in
packed structures, have an alignment of 1. Therefore the maximum bit padding
inserted to align a packed bitfield container is 7 bits.
For an unpacked bitfield container, the maximum bit padding is
8*sizeof(container-type)-1 bits.
Tail-padding is always inserted into the structure as necessary to
ensure arrays of the structure will have their elements correctly aligned.
A packed bitfield container is only large enough (in bytes) to hold
the bitfield that declared it. Non-packed bitfield containers are the size of
their type.
The following examples illustrate these interactions.
struct A {          int z:17; }; // sizeof(A) = 4, alignment = 4
struct A { __packed int z:17; }; // sizeof(A) = 3, alignment = 1
__packed struct A { int z:17; }; // sizeof(A) = 3, alignment = 1
struct A { char y:1;          int z:31; }; // sizeof(A) = 4, alignment = 4
struct A { char y:1; __packed int z:31; }; // sizeof(A) = 4, alignment = 1
__packed struct A { char y:1; int z:31; }; // sizeof(A) = 4, alignment = 1
struct A { char y:1;          int z:32; }; // sizeof(A) = 8, alignment = 4
struct A { char y:1; __packed int z:32; }; // sizeof(A) = 5, alignment = 1
__packed struct A { char y:1; int z:32; }; // sizeof(A) = 5, alignment = 1
struct A { int x; char y:1;          int z:31; };  // sizeof(A) = 8, alignment = 4
struct A { int x; char y:1; __packed int z:31; }; // sizeof(A) = 8, alignment = 4
__packed struct A { int x; char y:1; int z:31; }; // sizeof(A) = 8, alignment = 1
struct A { int x; char y:1;          int z:32; };  // sizeof(A) = 12, alignment = 4 [1]
struct A { int x; char y:1; __packed int z:32; }; // sizeof(A) = 12, alignment = 4 [2]
__packed struct A { int x; char y:1; int z:32; }; // sizeof(A) = 9, alignment = 1
Note that [1] and [2] are not identical; the location of z within the structure and the tail-padding differ.
struct example1
{
int a : 8; /* 4-byte container at offset 0 */
__packed int b : 8; /* 1-byte container at offset 1 */
__packed int c : 24; /* 3-byte container at offset 2 */
}; /* Total size 8 (3 bytes tail padding) */;
struct example2
{
__packed int a : 8; /* 1-byte container at offset 0 */
__packed int b : 8; /* 1-byte container at offset 1 */
int c : 8; /* 4-byte container at offset 0 */
}; /* Total size 4 (No tail padding) */
struct example3
{
int a : 8; /* 4-byte container at offset 0 */
__packed int b : 32; /* 4-byte container at offset 1 */
__packed int c : 32; /* 4-byte container at offset 5 */
int d : 16; /* 4-byte container at offset 8 */
int e : 16; /* 4-byte container at offset 12 */
int f : 16; /* In previous container */
}; /* Total size 16 (No tail padding) */
Non-Confidential   ARM DUI0375E
Copyright 2007, 2008, 2011, 2012, 2014 ARM. All rights reserved.    
Home > C and C++ Implementation Details > Structures, unions, enumerations, and bitfields in ARM C and C++
struct X
{
int x:10;
char y:8;
int z:5;
}

Structures, unions, enumerations, and bitfields in ARM C and C++的更多相关文章

  1. delphi 保存网页MHT

    delphi 保存网页MHT   uses ADODB_TLB, CDO_TLB, ComObj,MSHTML;{$R *.dfm}{能把网页如 WWW.QQ.COM保存为一个单文件 .MHT但不能把 ...

  2. Python C/C++ 拓展使用接口库(build-in) ctypes 使用手册

    Python C/C++ 拓展使用接口库(build-in) ctypes 使用手册 ctypes 是一个Python 标准库中的一个库.为了实现调用 DLL,或者共享库等C数据类型而设计.它可以把这 ...

  3. [转]Keyword Reference (F#)

    Visual F# Development Portal http://msdn.microsoft.com/en-us/library/vstudio/ff730280.aspx 本文转自:http ...

  4. c++学习书籍推荐《The C++ Programming Language第四版》下载

    百度云及其他网盘下载地址:点我 作者简介 Bjarne Stroustrup is the designer and original implementer of C++, the author o ...

  5. Delphi 如何在程序中执行动态生成的Delphi代码

    如何在程序中执行动态生成的Delphi代码 经常发现有人提这类问题,或者提问内容最后归结成这种问题 前些阵子有位高手写了一个“执行动态生成的代码”,这是真正的高手,我没那种功力,我只会投机取巧. 这里 ...

  6. Swift声明参考

    一条声明可以在你的程序里引入新的名字和构造.举例来说,你可以使用声明来引入函数和方法,变量和常量,或者来定义 新的命名好的枚举,结构,类和协议类型.你也可以使用一条声明来延长一个已经存在的命名好的类型 ...

  7. Core Java Volume I — 1.2. The Java "White Paper" Buzzwords

    1.2. The Java "White Paper" BuzzwordsThe authors of Java have written an influential White ...

  8. The Swift Programming Language-官方教程精译Swift(4)字符串和字符

    String 是一个有序的字符集合,例如 "hello, world", "albatross".Swift 字符串通过 String 类型来表示,也可以表示为 ...

  9. LibVLC video controls

    原文 http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__video.html VLC  3.0.0-git ...

  10. 《C++程序设计语言(英文第四版)》【PDF】下载

    <C++程序设计语言(英文第四版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382177 内容简介 本书是C++领域经典的参 ...

随机推荐

  1. 02-Python基础

    文件编码 Python2中 在Python2中:默认文件编码是ASC II,所以无法正常输出中文,会报错. 解决办法 在文件的开头添加# -- coding: UTF-8 -- 或者 # coding ...

  2. C# SM2算法 加密,解密,签名,验签

    最近时间在整SM2算法,在网上看到不少代码,基本都是使用BouncyCastle库,现在这个版本算比较好的拿来分享给大家. 首先引入包 Portable.BouncyCastle 完整代码见Gitee ...

  3. NXP i.MX 6ULL工业开发板硬件说明书( ARM Cortex-A7,主频792MHz)

    前  言 本文档主要介绍TLIMX6U-EVM评估板硬件接口资源以及设计注意事项等内容. 创龙科技TLIMX6U-EVM是一款基于NXP i.MX 6ULL的ARM Cortex-A7高性能低功耗处理 ...

  4. 【经验分享】Docker容器部署方法说明

    前  言 本案例适用开发环境: Windows开发环境:Windows 7 64bit.Windows 10 64bit Linux开发环境:Ubuntu 18.04.4 64bit 虚拟机:VMwa ...

  5. VUE商城项目 -登录功能 - 手稿

    用户列表功能开发

  6. 小产品,快变现,Solo社区共建者 James 专访

    采访人:徐小夕. 本次受邀采访的嘉宾是Solo社区计划负责人&Solo社区联合创建者 James Pan(老潘). 专访内容 1. Solo社区创建的背景 随着国内软件市场内卷加剧,加上大环境 ...

  7. 从DDPM到DDIM

    从DDPM到DDIM (一) 现在网络上关于DDPM和DDIM的讲解有很多,但无论什么样的讲解,都不如自己推到一边来的痛快.笔者希望就这篇文章,从头到尾对扩散模型做一次完整的推导. DDPM是一个双向 ...

  8. leetcode简单(数组,字符串,链表):[168, 171, 190, 205, 228, 448, 461, 876, 836, 844]

    目录 168. Excel表列名称 171. Excel 表列序号 190. 颠倒二进制位 205. 同构字符串 228. 汇总区间 448. 找到所有数组中消失的数字 461. 汉明距离 876. ...

  9. [oeasy]python0067_ESC键进化历史_键盘演化过程_ANSI_控制序列_转义序列_CSI

    光标位置 回忆上次内容 上次了解了 新的转义模式 \33 逃逸控制字符 esc 这个字符让输出退出标准输出流 进行控制信息的设置 可以设置光标输出的位置 ASR33中的ALT MODE 是 今天的ES ...

  10. Nuxt.js 中使用 useHydration 实现数据水合与同步

    title: Nuxt.js 中使用 useHydration 实现数据水合与同步 date: 2024/7/18 updated: 2024/7/18 author: cmdragon excerp ...