如何将字符串文字与 4 的倍数的地址对齐?
How can I align a string literal to an address which is multiple of 4?
我想确保给定的字符串文字以 2 的倍数或更好的 4 的倍数结束。
有什么办法可以做到这一点,最好是不使用任何特定于编译器的扩展吗?还是不可能?
我想这样做,以便字符串地址的最低位为 0,并且可以(滥用)用作标记位。
您可以使用 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("%p\n", &a);
printf("%p\n", str);
printf("%p\n", str2);
}
上面的技巧是字符串文字实际上被用来初始化一个相同大小的字符数组,这让你可以在类型中使用 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 解决方案,但在没有其他合适方案的情况下使用 a GCC specific extension or MSVC one。
在 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");
但是,此版本在指针上浪费了 space(包括位置无关代码的相对重定位)并且不允许在函数中声明静态文字。
最好使用非标准对齐属性而不是这个。
我想确保给定的字符串文字以 2 的倍数或更好的 4 的倍数结束。
有什么办法可以做到这一点,最好是不使用任何特定于编译器的扩展吗?还是不可能?
我想这样做,以便字符串地址的最低位为 0,并且可以(滥用)用作标记位。
您可以使用 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("%p\n", &a);
printf("%p\n", str);
printf("%p\n", str2);
}
上面的技巧是字符串文字实际上被用来初始化一个相同大小的字符数组,这让你可以在类型中使用 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 解决方案,但在没有其他合适方案的情况下使用 a GCC specific extension or MSVC one。
在 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");
但是,此版本在指针上浪费了 space(包括位置无关代码的相对重定位)并且不允许在函数中声明静态文字。
最好使用非标准对齐属性而不是这个。