2013-05-01 1 views
1

Я ищу, чтобы найти длину литерала 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?

В этом вопросе Determining the Length of a String Literal есть комментарий, чтобы объявить массив как header_left[][4]. Я предпочитаю не использовать этот вид декларации, так как существует тенденция к изменению количества строк без изменения константы количества. Мне нравится, когда компилятор вычисляет количество строк (см. Определение rows_in_header) и длину каждой строки.

Это для встроенной системы, а строки - блок, написанный для последовательного порта. Функция последовательного порта принимает указатель на данные и длину данных в качестве параметров. Код последовательного порта оптимизирован для записи блоков. Предпочтение - не использовать strlen, поскольку это отнимает время исполнения.

Я использую C99 с встроенной мастерской IAR на платформе ARM7TDMI.
Я включил тег c++, потому что это также связано с C++, и мы будем переносить код на C++ после первого запуска продукта.

+0

Таким образом, вы не можете изменить определение вообще? Например. макро магия или магия C++ .. – dyp

+0

Для 'static const char * const header_left []' длина не имеет значения, так как это массив указателей. Возможно, вам понадобилось бы 'static const char header_left [] [sizeof" Interval # | Duration | Point | Point | "] = {...};'? –

+0

@ DanielFischer: Нужно ли дублировать текст в вашем случае, один раз для 'sizeof' и другого времени между' 'и' ''? –

ответ

1

На самом деле совет в связанном ответе неверен. так как он изменил индексы. Декларация должна быть больше вдоль линий этого:

static const char header_left[][40] = 
{ 
    "   |   | Raw | Raw |", 
    "   |   | Start | End |", 
    "Interval#| Duration | Point | Point |", 
    "---------+----------+-------+-------+", 
}; 

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

В любом случае вы не можете заставить компилятор вывести оба размера для вас - как массивов, так и массивы с зубцами не поддерживаются в C++.

+0

Если каждый элемент массива имеет фиксированную длину, он все еще считается массивом * jagged *? –

+0

Нет - массив с зубцами - это массив массивов с вложенными массивами переменной величины. В C++ у вас действительно есть только одномерные массивы, элементы которых должны быть фиксированным размером (время компиляции). Они могут быть вложены, чтобы обеспечить приближение многомерных массивов. Но только самый значительный (внешний) массив может иметь свой размер. –

0

Вы можете извлечь 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; 
1

Macro волшебство! (> = 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[] = {...};
+0

http://coliru.stacked-crooked.com/view?id=7be12a566c06274fc6df138fd614e1bd-50d9cfc8a1d350e7409e81e87c2653ba работает лучше, чем я ожидал. –

+0

@MooingDuck То есть, '-1' для' \ 0' Я предполагаю? – dyp

+0

Нет, я думал, что ваш ответ был неправильным, поэтому закодировал его, и это было правильно. Поэтому я опубликовал код для будущих сомневающихся. –

4

Класс stringref может справиться с этим, если вы желаете. Это кажется проще, чем большинство других ответов, и обрабатывает situtations где строки являются различными длинами:

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

http://coliru.stacked-crooked.com/view?id=e244267379f84e21409db9ec39da5765-50d9cfc8a1d350e7409e81e87c2653ba

+0

О, ТЕПЕРЬ Я замечаю строку, в которой говорится: «Я использую C99» ... –