Извините, если это разрешимо через 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’?
Спасибо,
Чарльз
Вы можете использовать макрос, который сделает эту работу:
#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;
}
Этот код основан на это решение и это также легко расширяется.
Во всяком случае был предложение некоторое время назад это вероятно никогда не делало это к стандарту. Вокруг есть патчи, которые позволяют преобразовывать строковые литералы в переменные наборы символов.
Дайте структуре конструктор, который принимает массивы символов размером 1 больше, чем вам нужно, и игнорируйте завершающий символ при их копировании.
bar::bar(int, char const(&)[5], int, char const(&)[9], ...)
Или вы можете просто сделать параметры char const*
и доверяйте пользователю передавать массивы правильного размера в соответствии с вашей документацией. Если вы не хотите или не можете добавить что-либо в структуру, просто создайте функцию с теми же аргументами, которая возвращает один (РВО следует исключить дополнительное копирование).
Я думаю, что он будет работать как массив uint8 (или любой другой, поддерживаемый вашим компилятором). Просто никогда не думай, что это строка, потому что это не так. Гораздо безопаснее выделить дополнительный символ и инициализировать его нулем (обычно автоматически). Лучше по-прежнему использовать компоненты STL, если только для этого нет веских причин.
C ++ — это не C. В C ++ компилятор пытается защитить вас. В C это полностью ваш собственный взгляд.