【问题标题】:Determining the Length of a String Literal确定字符串文字的长度
【发布时间】:2012-09-14 12:54:37
【问题描述】:

给定一个指向字符串字面量的指针数组:

char *textMessages[] = {
    "Small text message",
    "Slightly larger text message",
    "A really large text message that "
    "is spread over multiple lines"
}

如何确定特定字符串文字的长度 - 比如说第三个?我尝试使用 sizeof 命令如下:

int size = sizeof(textMessages[2]);

但结果似乎是数组中指针的数量,而不是字符串字面量的长度。

【问题讨论】:

  • sizeof(textMessages[2]) 将产生char* 类型的大小。 sizeof(char*) 在您的系统上恰好是 4,这纯属巧合,与您数组中的元素数量无关。
  • 您应该考虑为您的阵列使用定义static const char textMesssages[][4]
  • @MichaelFoukarakis 数组中只有 三个 指针(注意字符串连接)。
  • @Jens:哦,好吧,我的观点并不在于数字的选择,尽管我主张有一个哨兵值。

标签: c arrays string literals


【解决方案1】:

如果您希望在编译时(而不是在运行时使用strlen)计算数字,那么使用类似

的表达式是完全可以的
sizeof "A really large text message that "
       "is spread over multiple lines";

不过,您可能希望使用宏来避免重复长文字:

#define LONGLITERAL "A really large text message that " \
                    "is spread over multiple lines"

请注意,sizeof 返回的值包括终止 NUL,因此比 strlen 多一。

【讨论】:

  • 我希望确定每个字符串的长度,以便我可以索引长度并将它们传递给函数。是否可以在编译时计算出这样的长度数组?
  • 我的方法是声明和初始化一个struct { char *ptr; size_t len; } x[] 的数组。然后您可以拨打foo(x[i].ptr, x[i].len)。由于 C 不保留字符串长度,因此除了在代码中跟踪字符串长度之外别无他法。
【解决方案2】:

我的建议是使用 strlen 并打开编译器优化。

例如,在 x86 上使用 gcc 4.7:

#include <string.h>
static const char *textMessages[3] = {
    "Small text message",
    "Slightly larger text message",
    "A really large text message that "
    "is spread over multiple lines"
};

size_t longmessagelen(void)
{
  return strlen(textMessages[2]);
}

运行后make CFLAGS="-ggdb -O3" example.o:

$ gdb example.o
(gdb) disassemble longmessagelen
   0x00000000 <+0>: mov    $0x3e,%eax
   0x00000005 <+5>: ret

即编译器已用常量值 0x3e = 62 替换了对 strlen 的调用。

不要浪费时间执行编译器可以为您做的优化!

【讨论】:

    【解决方案3】:

    strlen 为您提供字符串的长度,而 sizeof 将返回您作为参数输入的以字节为单位的 数据类型 的大小。

    strlen

    sizeof

    【讨论】:

      【解决方案4】:

      strlen 可能吗?

      size_t size = strlen(textMessages[2]);
      

      【讨论】:

      • 这个数字可以在编译时确定,为什么还要在运行时计算?
      • @Jens:除非你在编译时也知道字符串。
      • @Tudor,是的 - 你确实知道编译时的长度(问题是“字符串文字”)
      【解决方案5】:

      您应该使用strlen() 库方法来获取字符串的长度。 sizeof 将为您提供 textMessages[2] 的大小,一个指针,取决于机器(4 字节或 8 字节)。

      【讨论】:

        【解决方案6】:

        您可以利用数组中的值是连续的这一事实:

        const char *messages[] = {
            "footer",
            "barter",
            "banger"
        };
        
        size_t sizeOfMessage1 = (messages[1] - messages[0]) / sizeof(char); // 7   (6 chars + '\0')
        

        大小是通过使用元素的边界来确定的。第一个元素的开头和第二个元素的开头之间的空间是第一个元素的大小。

        这包括终止 \0。当然,该解决方案仅适用于常量字符串。如果字符串是指针,你会得到指针的大小而不是字符串的长度。

        这不保证有效。如果字段对齐,这可能会产生错误的大小,并且编译器可能会引入其他警告,例如合并相同的字符串。 此外,您的数组中至少需要两个元素。

        【讨论】:

        • 这不能保证有效。虽然数组中的指针必须是连续的,但字符串文字不需要。想想对齐等等。或者对相同的字符串文字使用相同的指针。
        • 你说得对,对齐会破坏这一点(但这是可控的)。 char 的不同尺寸也会破坏这一点。我会将我的答案标记为不可靠。
        • 合并相同的字符串,一种常见的优化,也会破坏它。
        【解决方案7】:

        我会告诉你一些事情,根据我的 Knowledge 数组,当你使用 sizeof 时,指针是一样的除了

        当你在指针上使用sizeof 时,无论指针指向什么,它都会返回4 BYTE,但如果它用在数组上,它将返回数组的长度大字节?

        在您的示例中,*textMessage[] 是指针数组,因此当您使用 sizeof(textMessage[2]) 时,它将返回 4 BYTE,因为 textMessage[2] 是指针。

        希望对你有用。

        【讨论】:

        • 我不明白你想要什么
        • 我的目的是告诉您通过阅读所有c-faq.com/aryptr/index.html 来提高您对数组和指针的差异的了解@ 数组不是指针,它们通常是 2 或 8而不是 4 个字节,它们的大小甚至可能取决于它们指向的类型。所以,你写的大部分内容在技术上都是不正确的。
        • 指针并不总是 4 个字节。
        猜你喜欢
        • 2012-07-06
        • 1970-01-01
        • 1970-01-01
        • 2011-05-04
        • 1970-01-01
        • 2021-12-27
        • 2021-02-18
        • 2011-09-08
        • 2021-04-20
        相关资源
        最近更新 更多