C11标准保证将一种阵列类型转换为另一种阵列类型

时间:2015-04-15 22:06:00

标签: c arrays types c11

所以我有一个应用程序,我使用很多chars,short,int和long longs的数组,都是无符号的。我不是为每个人分配空间并解除分配,而是要有一个无符号长long的静态数组。然后我会根据需要将其转换为适当类型的数组。有没有办法证明这符合标准?

我静态断言char,short,int和long long的大小分别为1,2,4和8,并且它们的对齐要求不超过它们的大小。我想知道我是否可以证明我的方法的有效性而没有进一步的静态断言。

编辑:我想我添加标准将对象表示定义为对象的副本作为unsigned char数组。似乎这证明使用无符号长long数组作为或无符号字符数组是合理的,尽管我不能完全排除与在对象本身的上下文中使用对象表示相关的问题而不是在副本中(这是6.2的方式)。 6.1.4讨论了对象表示)。但是,这是我能找到的所有内容,并且它对两个中间整数大小没有任何帮助。

1 个答案:

答案 0 :(得分:3)

首先,您不是在谈论投射数组。您正在谈论投射指针

该标准并不保证您所做的事情是安全的。您可以将unsigned long long数组视为unsigned char数组,但不能保证您可以将其视为unsigned int数组。

考虑使用CHAR_BIT==8sizeof (unsigned int) == 4sizeof (unsigned long long) == 8的假设实施。假设unsigned int需要严格的4字节对齐。但底层机器没有直接支持64位数量,因此unsigned long long上的所有操作都是用软件完成的。因此,unsigned long long所需的对齐方式是2个字节。

因此,unsigned long long数组可能从一个不是4个字节的倍数的地址开始,因此您无法安全地将其视为unsigned int的数组。

我不建议这是似是而非的实施。即使在软件中实现64位整数,它们也可能至少具有32位对齐。但我所描述的内容并没有违反标准;假设的实施可能是符合的。

如果您正在使用C11编译器(如问题中的标记所示),您可以静态断言

_Alignof (unsigned long long) > _Alignof (unsigned int)

等等。

或者您可以在启动期间使用malloc来分配您的阵列,确保它适合任何类型。

从评论中窃取一个想法,你可以定义一个数组类型的联合,如:

#define BYTE_COUNT some_big_number
union arrays {
    unsigned char      ca[BYTE_COUNT];
    unsigned short     sa[BYTE_COUNT  / sizeof (unsigned short)];
    unsigned int       ia[BYTE_COUNT  / sizeof (unsigned int)];
    unsigned long      la[BYTE_COUNT  / sizeof (unsigned long)];
    unsigned long long lla[BYTE_COUNT / sizeof (unsigned long long)];
};

或者您可以为要存储在其中的数据类型定义数组。