能否在C预处理器中实现strlen()
函数?
已知:
#define MYSTRING "bob"
是否有一些预处理宏,X
,可以让我这样说:
#define MYSTRING_LEN X(MYSTRING)
能否在C预处理器中实现strlen()
函数?
已知:
#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
上面的代码将包括空终止符。
strlen
一样工作,你能不能只是这样做:#define STRLEN(s) ( (sizeof(s)/sizeof(s[0])) - sizeof(s[0]) )
? - Jamesstatic const char string[] = "bob\0and\0mary"
会报告一个比 "bob"
更长的长度。 - Edwin Buck#define BOB_LEN 3
更容易导致问题,但你的观点是正确的。在C中编写代码通常意味着冒险引发错误。决策实际上取决于你愿意做出什么样的权衡。 - nmichaels#define NELS(array) (sizeof(array)/sizeof(array[0]))
,表示“元素数量”。这适用于任何数组,并且比STRLEN更少误导性。 - Jim Balter你可以这样做:
#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 字符。char
数组,而sizeof
对于数组和其他类型一样有效。 - caf是的:
#define MYSTRING_LEN(s) strlen(s)
在大多数编译器中,这将为常量参数产生一个编译时常量……你不能做得比这更好。
换句话说:你不需要一个宏,只需使用strlen;编译器足够聪明,可以为你完成工作。
int f() {char XYZ[strlen(s)]; ...}
不是一个有效的 C89 程序,而 int f() {char XYZ[sizeof(s)]; ...}
则是一个有效的程序。 - Maciej Piechotka-1
或+1
,但我的观点仍然成立 - 即使编译器可能会优化它,这并不意味着它适用于所有情况。 - Maciej Piechotkasizeof
运算符可以用于常量表达式(变长数组除外),而 strlen
则不能。可以假定使用预处理器意味着需要一个常量表达式,否则不会使用预处理器。因此,您可以比使用 strlen
更好地使用 sizeof("foo")
,这将产生一个常量表达式。它可以在比编译器优化为编译时常量更多的上下文中使用。这样的优化不会改变程序的含义,并且不会将表达式转换为常量表达式。 - Kuba hasn't forgotten Monica#if 1+2
中,1+2
根据常量表达式的规则进行评估。 Note: The translation is in Simplified Chinese. - pmor
#define MYSTRING_LEN 3
有什么问题吗?虽然我能看出它很有用,因为你只需要更改MYSTRING
而不必担心MYSTRING_LEN
... - Jamesstatic const char* strings[] = { "foo", "hello" }
?下面这个方便的宏似乎在这种情况下会出现问题,例如enum string_names { S_FOO = 0, S_HELLO }; static const size_t const string_lengths[] = { STRLEN(strings[S_FOO]), STRLEN(strings[S_HELLO]) }
在这里,所有的string_lengths
成员都是 8(指针的大小),而不是字符串的长度。也许我需要放弃,在运行时使用strlen
:/ - jacobq