Стрлен в препроцессоре C? - PullRequest
30 голосов
/ 17 февраля 2011

Возможно ли реализовать strlen() в препроцессоре C ?

Дано:

#define MYSTRING "bob"

Есть ли какой-то макрос препроцессора, X,позвольте мне сказать:

#define MYSTRING_LEN X(MYSTRING)

Ответы [ 4 ]

36 голосов
/ 17 февраля 2011

Он не использует препроцессор, но sizeof разрешается во время компиляции. Если ваша строка находится в массиве, вы можете использовать ее для определения ее длины во время компиляции:

static const char string[] = "bob";
#define STRLEN(s) (sizeof(s)/sizeof(s[0]))

Имейте в виду, что STRLEN выше будет включать нулевой терминатор, в отличие от strlen().

5 голосов
/ 17 февраля 2011

Да: #define MYSTRING_LEN(s) strlen(s)

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

Другими словами: вам не нужен макрос, просто используйте strlen;компилятор достаточно умен, чтобы сделать всю работу за вас.

5 голосов
/ 17 февраля 2011

Вы можете сделать:

#define MYSTRING sizeof("bob")

На моей машине написано 4, потому что в конце добавлен ноль.

Конечно, это работает только для строковой константы.


Использование MSVC 16 (cl.exe -Wall /TC file.c) это:

#include "stdio.h"
#define LEN_CONST(x) sizeof(x)

int main(void)
{
    printf("Size: %d\n", LEN_CONST("Hej mannen"));

    return 0;
}

выходы:

Size: 11

Размер строки плюс символ NUL.

0 голосов
/ 17 февраля 2011

Обычно препроцессор C фактически не преобразует никаких данных, он только заменяет их. Это означает, что вы можете выполнить такую ​​операцию при условии, что вы загрязните пространство имен препроцессора C данными, реализующими (функциональные) постоянные структуры данных.

Тем не менее, вы действительно не хотите этого делать, так как вся "добавленная" функциональность будет впечатляюще терпеть неудачу, когда вы передадите что-то кроме строки. Препроцессор C не имеет понятия типа данных, а также понятия разыменования памяти (полезно, если вы хотите, чтобы длина строки хранилась в переменной). По сути, это было бы забавным упражнением «посмотри, как далеко ты сможешь это сделать», но в конце концов у тебя будет MYSTRING_LEN, который приведет тебя лишь на короткое расстояние к цели.

Кроме того, отсутствие пространства имен для препроцессора C означает, что такая система расширения макрокоманд не будет содержать. Нужно позаботиться о том, чтобы сгенерированные имена не мешали другим полезным макросам. В конце концов, вам, вероятно, не хватило бы памяти в препроцессоре для какого-либо значительного использования, поскольку препроцессор на самом деле не создан для хранения имени для каждого символа, преобразуемого в маркер «единицы», и имени для каждого "единичного" токена, сжимаемого в окончательную десятичную запись.

...