Как 8-байтовое выравнивание каждой строки в статическом массиве? - PullRequest
4 голосов
/ 04 июня 2019

Представьте, что у вас есть статический массив литеральных строк в программе на C (не на C ++), длина которых может варьироваться в широких пределах. Все, что вас волнует, это то, что каждый начинается с 8-байтовой границы. Есть ли способ убедиться, что GCC или CLANG выровняют каждую строку таким образом? Вы также хотите сэкономить место, поэтому заполнение строк, чтобы они все были одинакового размера, не вариант.

static char* const strings[] = {
    "a", "longer string", "bcd", "wow a really long string", "foo", ...
};

Цель здесь - сделать что-то вроде этого:

uint64_t value = *(uint64_t*) strings[i];

таким образом, что чтение не охватывает два четырехсловых слова в сгенерированном асм-коде, т. Е. Первые 8 байтов строки поступают в регистр с использованием выровненного чтения.

1 Ответ

7 голосов
/ 04 июня 2019

Предполагая, что вы хотите, чтобы строковые литералы были выровнены; это невозможно. Но вы можете получить аналогичный эффект, создавая массивы с пользовательским выравниванием, например ::10000

_Alignas(8) static char const s1[] = {"a"};
_Alignas(8) static char const s2[] = {"longer string"};
_Alignas(8) static char const s3[] = {"bcd"};
_Alignas(8) static char const s4[] = {"wow a really long string"};
_Alignas(8) static char const s5[] = {"foo"};

char const *const strings[] = { s1, s2, s3, s4, s5 };

Вы можете сохранить набор текста, используя макрос препроцессора для каждой записи.

См. Также этот вопрос .


В соответствии со стандартом C17 вы также можете использовать составные литералы со спецификатором выравнивания:

char const *const strings[] = 
{
    (_Alignas(8) char const[]){"a"},
    (_Alignas(8) char const[]){"longer string"},
};

хотя некоторые компиляторы пока не поддерживают это.

...