How can I align a string literal to an address which is multiple of 4?

核能气质少年 提交于 2019-12-24 14:59:19

问题


I'd like to ensure that a given string literal ends up at an address that is a multiple of 2, or even better, 4.

Is there any way to achieve that, preferably without using any compiler-specific extensions? Or is it impossible?

I'd like to do this so the lowermost bits of the string address are 0 and can be (ab)used as tag bits.


回答1:


In C99 you can do this using a union, for example

#define ALIGNED_STR_UNION(N, S) const union { char s[sizeof S]; int align; } N = { S }
ALIGNED_STR_UNION(sssu, "XYZABC");

Adjust the type int as necessary.

With that, sssu.s refers to the characters.

The .s can be avoided like

#define ALIGNED_STR(S) ((const union { char s[sizeof S]; int align; }){ S }.s)
const char *sss = ALIGNED_STR("XYZABC");

However, this version wastes space on the pointer (including a relative relocation for position independent code) and does not allow declaring static literals in functions.

It is probably better to use the non-standard alignment attributes instead of this.




回答2:


You can do this using C11 (but not C99). For statically allocated buffers you can use alignas to do this:

#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);
}

The trick above is that the string literal is actually being use to initialize a char array of the same size, which lets you use alignas in the type.

For dynamically allocated ones you use aligned_alloc(size_t alignment, size_t size) instead of malloc.

There are other older non-standard ways of doing this which work with GCC/Clang/Intel compilers going back quite some way too, so if you don't have C11 available always you can dress this up with some extra pre-processor work, e.g.:

#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!

Which favours the C11 solution, but uses a GCC specific extension or MSVC one where nothing else suitable exists.



来源:https://stackoverflow.com/questions/36529491/how-can-i-align-a-string-literal-to-an-address-which-is-multiple-of-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!