Насколько легко сделать неопределенные массивы символов в C ++?

Извините, если это разрешимо через Google — я не смог ничего найти.

char foo[4] = "abcd";

недействителен в C ++ (из-за необходимости использования терминатора ‘\ 0’), но IIRC действителен в C — это правильно?

У меня есть набор структур с большим количеством символьных полей «фиксированной длины», которые должны быть заполнены пробелом и не заканчиваться на «\ 0». Я хотел бы быть в состоянии сделать обычную инициализацию структуры — вы знаете,

mystruct bar = {17, "abcd", 0x18, "widget  ", ...

Но я не могу сделать это в C ++. Я думаю, что одним из решений было бы поместить все инициализированные структуры, подобные этой, в их собственный исходный модуль C (не ++). Уродливое, трудоемкое решение, которого я пытаюсь избежать,

mystruct bar = {17, {'a', 'b', 'c', 'd'}, 0x18, {'w', 'i', 'd', 'g', 'e', 't', ' ', ' '}, ...

Есть хорошее решение C ++? Умный макрос, который будет эффективно позволять «abcd» быть char [4] без терминатора ‘\ 0’?

Спасибо,
Чарльз

3

Решение

Вы можете использовать макрос, который сделает эту работу:

#define MACRO_GET_1(str, i) \
(sizeof(str) > (i) ? str[(i)] : 0)

#define MACRO_GET_4(str, i) \
MACRO_GET_1(str, i+0),  \
MACRO_GET_1(str, i+1),  \
MACRO_GET_1(str, i+2),  \
MACRO_GET_1(str, i+3)

#define MACRO_GET_STR(str) MACRO_GET_4(str, 0)

struct mystruct {
char foo[4];
};

int main() {
mystruct obj{ MACRO_GET_STR("abcd") };
const char* str = "abcd";
std::cout << memcmp(obj.foo, str, 4); // 0

return 0;
}

пример

Этот код основан на это решение и это также легко расширяется.

Во всяком случае был предложение некоторое время назад это вероятно никогда не делало это к стандарту. Вокруг есть патчи, которые позволяют преобразовывать строковые литералы в переменные наборы символов.

0

Другие решения

Дайте структуре конструктор, который принимает массивы символов размером 1 больше, чем вам нужно, и игнорируйте завершающий символ при их копировании.

bar::bar(int, char const(&)[5], int, char const(&)[9], ...)

Или вы можете просто сделать параметры char const* и доверяйте пользователю передавать массивы правильного размера в соответствии с вашей документацией. Если вы не хотите или не можете добавить что-либо в структуру, просто создайте функцию с теми же аргументами, которая возвращает один (РВО следует исключить дополнительное копирование).

1

Я думаю, что он будет работать как массив uint8 (или любой другой, поддерживаемый вашим компилятором). Просто никогда не думай, что это строка, потому что это не так. Гораздо безопаснее выделить дополнительный символ и инициализировать его нулем (обычно автоматически). Лучше по-прежнему использовать компоненты STL, если только для этого нет веских причин.

C ++ — это не C. В C ++ компилятор пытается защитить вас. В C это полностью ваш собственный взгляд.

0
По вопросам рекламы [email protected]