【问题标题】:C Aligning string literals for a specific use caseC 为特定用例对齐字符串文字
【发布时间】:2016-04-20 04:35:20
【问题描述】:

我正在尝试以特定方式对齐字符串文字,因为我在代码中使用它的方式非常具体。我不想将它分配给变量,例如我的许多函数都将它用作直接参数。而且我希望它在本地范围或全局范围内都可以工作。

使用示例:

char *str = ALIGNED_STRING("blah"); //what I want
foo(ALIGNED_STRING("blah")); //what I want

_Alignas(16) char str[] = "blah"; //not what I want (but would correctly align the string)

理想的解决方案是 (_Alignas(16) char[]){ "blah" } 或更糟糕的情况,使用 GCC/Clang 编译器扩展来对齐 (__attribute__((alignment(16))) char[]){ "blah" },但两者都不起作用(它们被忽略并使用该类型的默认对齐方式)。

所以我的下一个想法是自己对齐它,然后我使用字符串的函数可以正确修复它。例如#define ALIGNED_STRING(str) (char*)(((uintptr_t)(char[]){ "xxxxxxxxxxxxxxx" str } + 16 - 1) & ~(16 - 1))(其中包含“x”的字符串表示需要了解在哪里可以找到真实字符串的数据,这很容易,但仅作为示例假设“x”很好)。现在这在本地范围内工作正常,但在全局范围内失败。由于编译器抱怨它不是编译时常量(错误:初始化元素不是编译时常量);我原以为它会起作用,但似乎只有加法和减法才是编译时指针上的有效操作。

所以我想知道是否有办法实现我想做的事情?目前我只是使用后一个示例(填充和手动对齐)并避免在全局范围内使用它(但我真的很想这样做)。最好的解决方案是避免需要进行运行时调整(比如使用对齐限定符),但这似乎是不可能的,除非我将它应用于变量(但如上所述,这不是我想要做的)。

【问题讨论】:

  • 为什么是 16 而不是 sizeof(max_align_t)
  • @chux 16 只是一个示例,但我确实需要一个特定的固定大小,因为我将空闲位用于其他信息(标记指针)。

标签: c string gcc alignment clang


【解决方案1】:

能够使用复合文字接近 OP 的需求。 (C99)

#include <stdio.h>
#include <stddef.h>

void bar(const char *s) {
  printf("%p %s\n", (void*)s, s);
}

//                         v-- compound literal --------------------------v
#define ALIGNED_STRING(S)  (struct { _Alignas(16) char s[sizeof S]; }){ S }.s

int main() {
  char s[] = "12";
  bar(s);
  char t[] = "34";
  bar(t);
  bar(ALIGNED_STRING("asdfas"));
  char *u = ALIGNED_STRING("agsdas");
  bar(u);
}

输出

0x28cc2d 12
0x28cc2a 34
0x28cc30 asdfas  // 16 Aligned
0x28cc20 agsdas  // 16 Aligned

【讨论】:

  • 注意:用_Alignas(16) 尝试了同样的方法,没有struct,但失败了。
  • 谢谢,这是一个很棒的解决方案。并且完全符合我的需求(在本地和全球范围内工作)。
  • @ScrimpyCat 一个月后回到这里评论让我知道编码是如何进行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多