Компиляция строкового литерала размера переменной времени в C - PullRequest
1 голос
/ 26 августа 2011

Что нужно сделать для ДД ?

если

#define HEADING_TITLE_PROJECT_NAME  "<= Version Maintenance Based On Compiled DateTime =>"
#define SIZE_OF_HEADER_FOR_DECORATION_PURPOSE sizeof(HEADING_TITLE_PROJECT_NAME)
#define DD ????
#define HEADING "\r\n"DD"\r\n"HEADING_TITLE_PROJECT_NAME"\r\n"DD"\r\n"

Я хочу получить HEADING строковый литерал следующим образом:

<==================================================>
<= Version Maintenance Based On Compiled DateTime =>
<==================================================>

Знак = или что-нибудь, что я однажды поставлю, будет повторяться в <== ... ==>, чтобы заполнить HEADING_TITLE_PROJECT_NAME пробел.

Можно ли это сделать так или иначе. Я хочу изменить только HEADING_TITLE_PROJECT_NAME во время кодирования и ничего больше. ТОЛЬКО МЫСЛИ, ЕСЛИ ЭТО МОЖЕТ БЫТЬ СДЕЛАНО :)

<== Редактировать начало ==> Что-то вроде

#define DD\
 char * get()\
{\
    char arr[100] = '\0';\
    for (int i=0; i < SIZE_OF_HEADER_FOR_DECORATION_PURPOSE - 1; i++)\
    {\
        arr[i] = "=";\
    }\  
    return arr;\
}

<== Редактирование заканчивается ==>

Ответы [ 3 ]

3 голосов
/ 26 августа 2011

К сожалению, в стандартном препроцессоре C нет автоматического способа генерации DD, если вы хотите использовать его так, как вы используете в определении макроса HEADING.

Пока вы настаиваете на том, чтобы HEADING было определено так, как оно определено в настоящее время, я могу предложить только полуавтоматический подход :). Определите DD вручную, явно.

#define HEADING_TITLE_PROJECT_NAME "<= Version Maintenance Based On Compiled DateTime =>"
#define DD                         "<==================================================>"

А потом просто добавьте

STATIC_ASSERT(sizeof HEADING_TITLE_PROJECT_NAME == sizeof DD);

прямо под ним (с вашей любимой реализацией STATIC_ASSERT). Таким образом, любое несоответствие длины DD немедленно вызовет ошибку и заставит разработчика обновить DD.

0 голосов
/ 27 августа 2011

Это невозможно, потому что sizeof вычисляется после препроцессора, а не до.

Если бы вы заранее знали длину строки, это было бы.

Поскольку у пропроцессора нет циклических конструкций, вы создаете их. Boost делает это примерно так

#define REPEAT_TIMES(macro, n) REPEAT##n(macro)
#define REPEAT1(macro) MACRO
#define REPEAT2(macro) REPEAT1(macro)MACRO
#define REPEAT3(macro) REPEAT2(macro)MACRO
....

Тогда вы просто:

#define FILLER "="
#define DD "<"REPEAT_TIMES(FILLER, 34)">"
0 голосов
/ 26 августа 2011

Ваша реализация DD неплохая идея, хотя она страдает от некоторого плохого синтаксиса и неопределенного поведения.

const char *DDD(void)
{
    static char arr[] = HEADING_TITLE_PROJECT_NAME;
    if(arr[2] == ' ')
        for(size_t i = 2; i + 3 < sizeof arr; i++)
            arr[i] = '=';
    return arr;
}
#define DD DDD()

Вы не можете вернуть указатель на данные стека, поэтому вы должны использовать массив static. Мы можем убедиться, что это правильный размер, автоматически установив строку #define d, а затем проверив, заполнен ли он еще '=' и, если нет, заполните его. Затем мы возвращаем const указатель на него, чтобы никто не пытался его изменить.

Ваш макрос определяет функцию get с неопределенными аргументами и возвращающую модифицируемую char * для суммирования данных. К сожалению, эта функция будет определяться везде, где вы используете макрос, что приведет к множественным ошибкам определения.

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

...