在C预处理器中strlen?

Job*_*fey 30 c strlen c-preprocessor

是否可以strlen()C预处理器中实现?

鉴于:

#define MYSTRING "bob"
Run Code Online (Sandbox Code Playgroud)

是否有一些预处理器宏,X让我说:

#define MYSTRING_LEN X(MYSTRING)
Run Code Online (Sandbox Code Playgroud)

nmi*_*els 36

它不使用预处理器,但sizeof在编译时解析.如果您的字符串在数组中,您可以使用它来确定编译时的长度:

static const char string[] = "bob";
#define STRLEN(s) (sizeof(s)/sizeof(s[0]))
Run Code Online (Sandbox Code Playgroud)

请记住,STRLEN上面的事实将包括null终止符,不像strlen().

  • 一个问题是你真的要求数组的大小,而不是C样式字符串.例如``static const char string [] ="bob\0and\0mary"`报告的长度大于`"bob"`. (8认同)
  • 是的,所以为了使它表现为`strlen`,你不能只做`#define STRLEN(s)((sizeof(s)/ sizeof(s [0])) - sizeof(s [0]))`? (5认同)
  • @Edwin:我认为`#define BOB_LEN 3`比我描述的更容易流泪,但你的观点是有效的.用C编写代码经常意味着诱惑bug命运.这个决定实际上归结为你愿意做出的权衡取舍. (2认同)
  • 实用程序头文件中的常见定义是“元素数量”的“#define NELS(array) (sizeof(array)/sizeof(array[0]))”。这适用于任何数组,并且比 STRLEN 的误导性要小得多。 (2认同)

Sku*_*del 6

你可以做:

#define MYSTRING sizeof("bob")
Run Code Online (Sandbox Code Playgroud)

在我的机器上说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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Size: 11
Run Code Online (Sandbox Code Playgroud)

字符串的大小加上NUL字符.

  • 这不是MS扩展,它是标准C.字符串文字(当不用作数组的初始化器时)是`char`数组,`sizeof`与数据一样适用于任何其他类型. (3认同)

Jim*_*ter 5

是: #define MYSTRING_LEN(s) strlen(s)

在大多数编译器中,这将为常量参数生成编译时常量...并且你不能做得更好.

换句话说:你不需要宏,只需使用strlen; 编译器足够聪明,可以为您完成工作.

  • "大多数编译器"?Gcc,是的,MSVC 10,没有. (5认同)
  • sizeof运算符可用于常量表达式(可变长度数组除外)中。`strlen` **不可能**。可以假定使用预处理器意味着需要一个常量表达式,否则就不能使用预处理器来完成。因此,是的,您可以做得比`strlen`好,并使用`sizeof(“ foo”)`产生一个常量表达式。它可以用于比编译器已优化为编译时常数的表达式更多的上下文中。这样的优化不会改变程序的含义,也不会将表达式变成常量表达式。 (3认同)
  • 还有`int f() {char XYZ[strlen(s)]; ...}` 不是有效的 C89 程序,而 `int f() {char XYZ[sizeof(s)]; ...}` 会。 (2认同)
  • @JimBalter:“计算机科学中有两个难题:缓存验证、变量替换和一对一错误。” - 是的,我应该将 `-1` 或 `+1` 添加到其中之一,但我的观点仍然成立 - 即使编译器可能对其进行优化,但这并不意味着它适用于所有情况。 (2认同)