Возможно ли реализовать strlen()
в препроцессоре C?
Дано:
#define MYSTRING "bob"
Есть ли какой-то препроцессорный макрос, X
, который позволит мне сказать:
#define MYSTRING_LEN X(MYSTRING)
Возможно ли реализовать strlen()
в препроцессоре C?
Дано:
#define MYSTRING "bob"
Есть ли какой-то препроцессорный макрос, X
, который позволит мне сказать:
#define MYSTRING_LEN X(MYSTRING)
Он не использует препроцессор, но sizeof разрешается во время компиляции. Если ваша строка находится в массиве, вы можете использовать ее для определения ее длины во время компиляции:
static const char string[] = "bob";
#define STRLEN(s) (sizeof(s)/sizeof(s[0]))
Имейте в виду, что STRLEN
выше будет включать нулевой ограничитель, в отличие от strlen()
.
Вы можете сделать:
#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.
Да:
#define MYSTRING_LEN(s) strlen(s)
В большинстве компиляторов это создаст константу времени компиляции для постоянного аргумента... и вы не можете сделать лучше этого.
Другими словами: вам не нужен макрос, просто используйте strlen; компилятор достаточно умен, чтобы выполнить вашу работу.
Как правило, предварительный процессор C фактически не преобразует никаких данных, он только заменяет его. Это означает, что вы могли бы выполнить такую операцию при условии, что вы загрязняете пространство имен препроцессора C с реализацией (функциональными) стойкими структурами данных.
Тем не менее, вы действительно не хотите этого делать, потому что вся "добавленная" функциональность будет неэффективной, если вы передадите что-то другое, кроме строки. Препроцессор C не имеет понятия типа данных и не имеет концепции де-ссылки памяти (полезно, если вы хотите, чтобы длина строки хранилась в переменной). В принципе, было бы забавно "посмотреть, как далеко вы можете это осуществить", но в конце концов у вас будет MYSTRING_LEN, который займет у вас только небольшое расстояние до цели.
Кроме того, недостаток пространства имен для предварительного процессора C означает, что такая система расширения макросов не будет сдерживаема. Нужно позаботиться о том, чтобы сгенерированные имена мешали другим полезным макросам. В конце концов, вы, вероятно, исчерпаете память в препроцессе для любого значительного использования, поскольку препроцессор на самом деле не построен для хранения имени для каждого символа, который преобразуется в токен "unit", и имя для каждого токена "единицы", сжимаемого в его окончательную десятичную нотацию.