2014-10-28 2 views
3

Извините, если это разрешено через Google - я ничего не нашел.Как легко уничтожить массивы char на C++?

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', ' ', ' '}, ... 

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

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

+2

@juanchopanza [C++ является более строгим на этом] (http://stackoverflow.com/a/20694830/1708801) –

+1

Почему бы не 'std :: string'? –

+0

Не должно быть char foo [5] = "abcd"; в вашем примере? –

ответ

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

Example

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

Во всяком случае, был proposal some time ago, который, вероятно, никогда не доходил до стандарта. Существуют патчи, которые позволяют преобразовывать струнные литералы в пакеты Variadic Char.

+0

Спасибо! Это должно сделать это. Большинство проблемных массивов имеют 8 символов в длину или несколько других «стандартных» размеров, поэтому мне понадобятся 3 или 4 таких макроса, а остальное я могу сделать уродливым способом. – Charles

+0

Вы уверены, что sizeof() будет работать так, как вы планировали в первом макросе? Я хотел использовать пустую панель, а не нулевой результат, поэтому я изменил ее на sizeof (str)> = (i)? str [(i)]: '' и несколько его вариантов. Независимо от того, что я делаю, результирующий массив равен нулю. Моя ментальная модель заключается в том, что выражение всегда истинно, а str [(i)] оценивает '\ 0' для всех i <длины str. Ваше занятие? – Charles

+0

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

1

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

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

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

0

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

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

+0

Мне нравится STL, и я люблю C++. Нет проблем. В этой конкретной ситуации у меня есть большое количество внешних фиксированных форматов записи, наложенных на меня, и они полны такого рода массива char. Мне нужно собрать несколько из них в коде для тестирования. Я ищу аккуратный способ сделать это. – Charles

+0

Моя песочница, но не моя последняя платформа - это MS VS C++. По крайней мере, UINT8 - это просто макрос для unsigned char и не имеет никакого значения. Компилятор, похоже, имеет собственный тип __int8, но это не улучшает. – Charles

+0

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

Смежные вопросы