Я ищу, чтобы найти длину литерала C-строки во время компиляции.
Учитывая определения:
static const char * const header_left[] =
{
" | | Raw | Raw |",
" | | Start | End |",
"Interval#| Duration | Point | Point |",
"---------+----------+-------+-------+",
};
const unsigned int rows_in_header = sizeof(header_left) / sizeof(header_left[0]);
Как мне найти длину строкового литерала header_left[2]
без использования strlen
?
В этом вопросе Определение длины строкового литерала, есть комментарий, чтобы объявить массив как header_left[][4]
, Я предпочитаю не использовать такого рода декларации, так как существует тенденция изменения количества строк без изменения количественной постоянной. Мне нравится, когда компилятор вычисляет количество строк (см. rows_in_header
определение) и длина каждой строки.
Это для встроенной системы и строки блок написано к последовательному порту. Функция последовательного порта принимает указатель на данные и длину данных в качестве параметров. Код последовательного порта оптимизирован для блочной записи. Предпочтение не использовать strlen
потому что это тратит время производительности.
Я использую C99 с IAR Embedded Workshop на платформе ARM7TDMI.
Я включил c++
тег, потому что это также включает в себя C ++, и мы будем мигрировать код в C ++ после первого запуска продукта.
На самом деле совет в связанном ответе неверен. поскольку это имеет обратные индексы. Декларация должна быть примерно такой:
static const char header_left[][40] =
{
" | | Raw | Raw |",
" | | Start | End |",
"Interval#| Duration | Point | Point |",
"---------+----------+-------+-------+",
};
Самый левый индекс все еще может быть предоставлен компилятором и указывает количество строк. Сами строки должны быть фиксированным массивом символов, для которого вы можете указать верхнюю границу (в нашем примере 40). Вы получите ошибку компиляции, если какая-либо строка превышает эту длину (включая нулевой терминатор). Потенциальным недостатком для ваших целей является потраченное впустую пространство.
В любом случае, вы не можете заставить компилятор выводить для вас оба размера — размер обоих массивов — и зубчатые массивы не поддерживаются в C ++.
Класс stringref может обработать это, если хотите. Это кажется проще, чем большинство других ответов, и обрабатывает ситуации, когда строки имеют различную длину:
struct stringref {
//this is for convenience, but isn't used in this sample
stringref(const char* p, size_t l=0) :ptr(p), len(l?l:strlen(p)) {}
//construct from string literals
template<size_t l> stringref(const char(&p)[l]) :ptr(p), len(l) {}
//convert to const char*
operator const char*() const {return ptr;}
const char* get() const {return ptr;}
//retrieve the length
size_t length() const {return len;}
private:
const char* ptr;
size_t len;
};
stringref header_left[] =
{
" | | Raw | Raw | ",
" | | Start | End | ",
"Interval#| Duration | Point | Point | ",
"---------+----------+-------+-------+",
};
int main()
{
const char* ptr = header_left[0]; //conversion possible
printf("%d\n", header_left[0].length());
printf("%d\n", header_left[1].length());
printf("%d\n", header_left[2].length());
printf("%d\n", header_left[3].length());
}
Макро магия! (> = C99)
Требуется минимум 2 ряда.
Обратите внимание, я не использую char const*
но char const[...]
здесь, то есть массивы, потому что это возможно и гарантирует, что все строки имеют одинаковую длину.
Изменить: вычесть -1 из length_of_row
избавиться от '\0'
,
#include<cstddef>
#define CREATE_HEADER(X, ...) \
static const size_t length_of_row = sizeof(X)/sizeof(X[0]) - 1; \
static const char header_left[][length_of_row+1] = { X, __VA_ARGS__ }; \
static const size_t rows_in_header = sizeof(header_left) / sizeof(header_left[0]); \
CREATE_HEADER(
" | | Raw | Raw |",
" | | Start | End |",
"Interval#| Duration | Point | Point |",
"---------+----------+-------+-------+",
);
sizeof(X)/sizeof(X[0])
выдает длину первой строки (строки)static const char header_left[][length_of_row]
является неограниченным массивом массивов length_of_row
обугливается; такой же как typedef char const row[length_of_row]; row header_left[] = {...};
Вы можете извлечь header_left[2]
строка и использование sizeof(...) - 1
static const char header_left_2[] = "Interval#| Duration | Point | Point |";
static const char * const header_left[] =
{
" | | Raw | Raw |",
" | | Start | End |",
header_left_2,
"---------+----------+-------+-------+",
};
const unsigned int rows_in_header = sizeof(header_left) / sizeof(header_left[0]);
const size_t header_left_2_len = sizeof(header_left_2) - 1;