инициализация массивов символов способом, аналогичным инициализации строковых литералов - PullRequest
5 голосов
/ 10 июля 2010

Предположим, у меня следующая инициализация массива символов:

char charArray[]={'h','e','l','l','o',' ','w','o','r','l','d'};

и у меня также есть следующая инициализация строкового литерала:

char stringLiteral[]="hello world";

Единственное различие между содержимым первого массива и второй строки состоит в том, что вторая строка имеет нулевой символ в конце.

Когда речь идет об инициализации массива char, есть ли макрос или что-то такое, что позволяет нам помещать наш инициализирующий текст между двумя двойными кавычками, но где массив не получает лишнего завершающего нулевого символа?

Мне просто не имеет смысла, что, когда завершающий нулевой символ не нужен, мы должны использовать синтаксис первой упомянутой инициализации и писать две одинарные кавычки для каждого символа в тексте инициализатора, а также знаки виргула для отдельные персонажи.

Я должен добавить, что когда я хочу иметь массив char, также должно быть очевидно, что я не хочу использовать его с функциями, которые полагаются на строковые литералы, наряду с тем фактом, что ни одна из функций, в которых используются строковые литералы результаты, на мой взгляд.

Я благодарен за ваши ответы.

Ответы [ 5 ]

6 голосов
/ 10 июля 2010

В C разрешено объявлять массив следующим образом, что будет инициализировать его без копирования завершающего '\0'

char c[3] = "foo";

Но это недопустимо в C ++.Я не знаю об уловке, которая позволила бы это для C ++.Стандарт C ++ далее гласит:

Обоснование : Когда этими незавершенными массивами управляют стандартные строковые процедуры, существует вероятность крупной катастрофы.
Влияние на исходную функцию : удаление семантически четко определенного признака.
Сложность преобразования : Семантическое преобразование.Массивы должны быть объявлены на один элемент больше, чтобы содержать строку, заканчивающуюся '\ 0'.
Насколько широко используется : Редко.Этот стиль инициализации массива считается плохим стилем кодирования.

3 голосов
/ 10 июля 2010

Нет способа делать то, что вы хотите. Первый способ инициализации массива определяет отдельные инициализаторы для каждого символа, что позволяет явно пропустить '\ 0'. Второй - инициализация массива символов из символьной строки, которая в C / C ++ всегда заканчивается нулевым символом.

РЕДАКТИРОВАТЬ: исправлено: «указатель символов» -> «массив символов»

1 голос
/ 10 июля 2010

Литб имеет технически правильный ответ .

Что касается мнения - я говорю, просто живите с «отходами» лишних «\ 0». Столько ошибок является результатом того, что код ожидает завершающего нулевого значения, если его нет (этот совет может показаться прямо противоречащим другому совету, который я дал один или два дня назад о том, что не надо обнулять весь буфер. Я утверждаю, что нет противоречие - я все еще выступал за нулевое завершение строки в буфере).

Если вы действительно не можете жить с терминатором '\ 0' из-за некоторой семантики в структуре данных, с которой вы имеете дело, например, это может быть частью какой-то более крупной упакованной структуры, вы всегда можете инициировать массив самостоятельно (что, я думаю, должно быть не менее эффективным, чем то, что компилятор мог бы сделать для вас):

#define MY_STRING_LITERAL "hello world"

char stringLiteral[sizeof(MY_STRING_LITERAL) - 1];

memcpy( stringLiteral, MY_STRING_LITERAL, sizeof(stringLiteral));
0 голосов
/ 11 июля 2010

Я мог бы найти способ сделать то, что я хочу, хотя это не совсем то, что я хотел, но он, вероятно, имеет тот же эффект.
Сначала рассмотрим два следующих класса:

template <size_t size>
class Cont{
 public:
  char charArray[size];
};
template <size_t size>
class ArrayToUse{
 public:
  Cont<size> container;
  inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){}
};

Прежде чем продолжить, вы можете перейти к здесь и взглянуть на конструкторы константных выражений и типы инициализации.
Теперь посмотрите на следующий код:

const Cont<12> container={"hello world"};
ArrayToUse<11> temp(container);
char (&charArray)[11]=temp.container.charArray;

Наконец, текст инициализатора пишется между двумя двойными кавычками.

0 голосов
/ 10 июля 2010

Основной ответ заключается в том, что подавляющее большинство символьных массивов являются строками - в C строки заканчиваются нулем.C ++ унаследовал это соглашение.Даже если этот нуль не нужен, в большинстве случаев это не проблема, просто оставить его там.

Макросы недостаточно мощны, чтобы делать то, что вы хотите.Шаблоны были бы, за исключением того, что они не имеют никакой обработки строк во время компиляции.

Обычно, когда люди хотят смешивать числовые байты и строковые литералы в одной и той же последовательности символов массива, они используют строковый литерал, но используютэкранирование шестнадцатеричных символов, например \xFF.

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