我想确保给定的字符串文字最终位于2的倍数,甚至更好的是4的地址。
有没有任何方法可以实现这一点,最好不使用任何编译器特定的扩展?还是不可能?
我想这样做,使字符串地址的最低位为0,并且可以(ab)用作标记位。
您可以使用C11(但不能使用C99)来完成此操作。对于静态分配的缓冲区,您可以使用alignas
来执行以下操作:
#include <stdio.h>
#include <stdalign.h>
alignas(4) char str[] = "this is aligned to at least 4 bytes";
int main() {
char a;
alignas(4) char str2[] = "and again";
printf("%pn", &a);
printf("%pn", str);
printf("%pn", str2);
}
上面的技巧是,字符串文字实际上是用来初始化相同大小的char数组的,这使您可以在类型中使用alignas
。
对于动态分配的,可以使用aligned_alloc(size_t alignment, size_t size)
而不是malloc
。
还有其他较老的非标准方法可以实现这一点,这些方法与GCC/Clang/Intel编译器一起使用,也可以追溯到很久以前,所以如果你没有C11,你可以用一些额外的预处理器工作来装扮它,例如:
#if __STDC_VERSION__ >= 201112L
# include <stdalign.h>
# define force_align(x) alignas(x)
#elif defined __GNUC__
# define force_align(x) __attribute__((aligned(x)))
#elif defined __MSC_VER
# define force_align(x) __declspec(align(x))
#else
# error Who are you?
#endif
force_align(128) int x; // Note: maybe your linker doesn't actually support 128 anyway!
这有利于C11解决方案,但使用GCC特定的扩展或MSVC扩展,而不存在其他合适的扩展。
在C99中,您可以使用并集来完成此操作,例如
#define ALIGNED_STR_UNION(N, S) const union { char s[sizeof S]; int align; } N = { S }
ALIGNED_STR_UNION(sssu, "XYZABC");
根据需要调整类型int
。
因此,sssu.s
指的是字符。
.s
可以像一样避免
#define ALIGNED_STR(S) ((const union { char s[sizeof S]; int align; }){ S }.s)
const char *sss = ALIGNED_STR("XYZABC");
然而,这个版本浪费了指针上的空间(包括位置无关代码的相对重定位),并且不允许在函数中声明静态文字。
使用非标准对齐属性可能比使用此属性更好。