Подтвердить что ты не робот

Strlen в препроцессоре C?

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

Дано:

#define MYSTRING "bob"

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

#define MYSTRING_LEN X(MYSTRING)
4b9b3361

Ответ 1

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

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

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

Ответ 2

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

#define MYSTRING sizeof("bob")

Это говорит о 4 на моей машине из-за того, что null добавлен в конец.

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


Используя 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.

Ответ 3

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

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

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

Ответ 4

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

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

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