хранить ненулевую концевую строковую константу C в переполнении стека

Прежде чем кто-то скажет: «НЕ ДЕЛАЙТЕ ЭТОГО, так как это действительно плохо».

  1. Я понимаю причины наличия строки, заканчивающейся NUL.
  2. Я знаю, что можно сказать что-то вроде
    char mystr [] = {'m', 'y', '', 's', 't', 'r', 'i', 'n', 'g'};

    Однако удобство представления c-string слишком велико.

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

Я пробовал шаблоны, которые принимают <size_t N, символ * A> а также <size_t N, char (&А) [Н]> в качестве параметров, чтобы обойти массив и сохранить его содержимое в статическом массиве, но я не могу понять, что это правильно. Я думаю, что стандарт может фактически запретить это, что понятно в общем случае, но неудачно в конкретных случаях (в частности, в этом;;) :()

Если бы я мог переназначить строку как что-то вроде повышение :: MPL :: vector_c<символ, …> шаблон, это было бы лучше, так как у меня есть другой код, который будет правильно его хранить, но разыменование массива из шаблона, который будет использоваться в качестве параметра шаблона const, тоже не разрешено.

Есть идеи?

РЕДАКТИРОВАТЬ:

Пример псевдокода (это немного надумано, так как реальный код намного больше, также я бы, наверное, не читал побайтно, как этот, и не буду использовать литерал для итерации до конца строки. Это будет встроено в данные тоже где то.)

// this stores bytes in an array
template<typename X, typename T, T ...numbers>
struct x
{
static PROGMEM volatile const T data[];
};
template<typename X, typename T, T ...numbers>
PROGMEM volatile const T x<X, T, numbers...>::data[] = { numbers... };

void main()
{
// this will not work, but the idea is you have byte 0 as 1,
// byte 1 as 2 byte 2 as 3 byte 3 as 's', byte 4 as 'o'...
// byte 22 as 'g', byte 23 as 4, byte 24 as 5, byte 25 as 6.
typedef x<int, char, 1,2,3,"some embedded string",4,5,6> xx;
for(i=0; i<20; ++i)
Serial.print(pgm_read_byte_near(&xx::data[0] + 3));
}

Также обратите внимание, что я не использую C ++ 11, это C ++ 0x и, возможно, расширение.

6

Решение

Третья попытка

магия и обман

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

template <char... RAW>
inline constexpr std::array<char, sizeof...(RAW)> operator "" _fixed() {
return std::array<char, sizeof...(RAW)>{RAW...};
}

было бы неплохо, если бы это сработало:

const std::array<char, 7> goodbye = goodbye_fixed;

… но, к сожалению, это не так (литерал должен быть числовым, по-видимому, для разбора). С помощью "goodbye"_fixed тоже не работает, так как это требует operator "" _fixed(const char *s, int length) перегрузка и массив времени компиляции снова распался на указатель.

В конце концов мы дошли до вызова этого:

const auto goodbye = operator "" _FS <'g','o','o','d','b','y','e'>();

и это не лучше, чем уродливая первая версия. Есть другие идеи?


Вторая попытка

автоматически генерировать уродство

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

Например, вы печатаете

fixed_string hello = "hello";

или что-то подобное в выделенном файле, и система сборки генерирует заголовок

const std::array<char, 5> hello;

и CPP с уродливой инициализацией из выше ниже.


Первая попытка

пропустил требование «выглядит как строковый литерал»

Я пробовал шаблоны …

как это?

#include <array>
const std::array<char, 5> hello = { 'h', 'e', 'l', 'l', 'o' };

#include <cstdio>
int main()
{
return std::printf("%.*s\n", hello.size(), &hello.front());
}

Если у вас нет C ++ 11, Boost.Array будет работать, или вы можете свернуть свой собственный.
Обратите внимание, что это просто оболочка типа const char[5], так что должно быть нормально, чтобы перейти в сегмент данных (я подтвердил, что идет в .rodata с моим местным gcc).

3

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

Других решений пока нет …

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