如何获取字符串的字节大小?

34
作为标题所示,我的问题是如何在C语言中获取字符串的大小。如果我在一个没有使用malloc的函数中声明了它(字符串),使用sizeof是否好?或者,如果我将其声明为指针呢?如果我使用malloc进行初始化会怎样?我希望得到详尽的回答。
6个回答

53
你可以使用strlen。大小由结束的空字符确定,因此传递的字符串应该是有效的。
如果你想获取包含字符串的内存缓冲区的大小,并且你有指向它的指针:
- 如果它是动态数组(使用malloc创建),那是不可能的,因为编译器不知道指针指向什么。(check this) - 如果它是静态数组,你可以使用sizeof来获取它的大小。
如果你对动态数组和静态数组之间的区别感到困惑,请查看this

17
实际上,大小为strlen()+1(1代表终止字符)。 - Agnius Vasiliauskas
7
“字符串”的大小通常是不包括空终止符的。 - Bernhard Barker
3
这句话的含义是——无法直接从动态数组中获取其大小。当然,你可以存储大小,但这不是重点。 - Bernhard Barker
4
C语言规定char占1个字节,但它没有定义一个字节是8个比特。因此,虽然对于C语言来说,“char”始终是一个字节,但它不一定是一个八位字节,而且在C标准之外的很多地方,“字节”意味着“八位字节”。虽然在char大于8位的C实现中是少数,但其中包括许多DSP。出于各种原因,许多“可移植”的代码无论如何都不能在DSP上运行,因此你需要决定是否假定一个字节是8个比特。用值CHAR_BIT可以确定这一点。 - Steve Jessop
2
@Dukeling 嗯...然后使用memcpystrlen()字节复制到另一个(非空)缓冲区并打印它。你会看到的是你的新字符串+垃圾。这对我来说是字符串大小为strlen()+1的论据。(但是字符串的长度是strlen())。 - Agnius Vasiliauskas
显示剩余5条评论

20
使用strlen获取以null结尾的字符串的长度。 sizeof返回的是数组的长度,而不是字符串的长度。如果它是一个指针(char *s),而不是一个数组(char s[]),它将不起作用,因为它将返回指针的大小(在32位系统上通常为4个字节)。我相信数组将作为指针传递或返回,因此您将失去使用sizeof检查数组大小的能力。
因此,仅当字符串跨越整个数组时(例如char s[] =“stuff”),使用sizeof来获取静态定义数组将返回您想要的内容(并且会更快,因为它不需要循环查找null终止符)(如果最后一个字符是null终止符,则需要减去1)。如果它没有跨越整个数组,它将无法返回您想要的内容。
所有这些的替代方法实际上是存储字符串的大小。

3
请注意,sizeof并不能真正给你字符串的长度。对于字符串字面值,sizeof 包括空终止符。对于一个 char 类型的数组,sizeof 给出数组中元素的数量(这个数量比数组内容字符串的长度大得不可预测)。 - simonc
1
指出strlensizeof返回两个根本不同的东西可能是有意义的。 - alk
指针的大小在32位系统上并不总是4字节。考虑CHAR_BIT为32位的情况。此外,考虑一个16位操作系统和编译器运行在32位系统上的情况。CHAR_BIT可能仍然是32位的,即使在16位操作系统和硬件上。指针的大小是由编译器决定的,而不是操作系统或硬件决定的。如果编译器选择使用和操作系统或硬件相同的大小,则这是编译器的选择。此外,不同的指针可能有不同的大小。 - autistic
@modifiablelvalue 已将“always”更改为“usually”。 - Bernhard Barker

12

虽然 sizeof 可以用于这种特定类型的字符串:

char str[] = "content";
int charcount = sizeof str - 1; // -1 to exclude terminating '\0'

如果str是指针(sizeof返回指针的大小,通常为4或8),或者是具有指定长度的数组( sizeof 将返回与指定长度相匹配的字节数,对于char类型来说是相同的),那么它不起作用。
只需使用strlen()即可。

在你的例子中,因为str是一个类型名称,所以它不应该被加括号吗? - ramrunner
@ramrunner str是变量名。它是一个数组,因此sizeof str将以字节为单位返回整个数组的大小。当像上面那样声明数组时,数组大小正好是包括终止符'\0'在内的字符串文字的大小。而sizeof-的优先级更高,因此sizeof str不需要任何括号,尽管在这里添加括号以增加清晰度并不是一件坏事,我承认。 - hyde

5
如果您使用 sizeof(),那么 char * str char str [] 将返回不同的答案。 char str [] 将返回字符串的长度(包括字符串终止符),而 char * str 将返回指针的大小(根据编译器而异)。

2

我喜欢使用:

(strlen(string) + 1 ) * sizeof(char)

这将为您提供以字节为单位的缓冲区大小。您可以将其与snprintf()一起使用,这可能会有所帮助:
const char* message = "%s, World!";
char* string = (char*)malloc((strlen(message)+1))*sizeof(char));
snprintf(string, (strlen(message)+1))*sizeof(char), message, "Hello");

干杯!函数:size_t strlen (const char *s)


(1) strlen() 总是返回字节长度,乘以1不会增加任何东西; (2) 缓冲区的大小与其包含的字符串长度之间可能没有关系; (3) 你尝试编译过这些代码吗? - Crowman
(1) 没有乘以一 (2) 我正在为指针分配字节,所以我使用字符串长度 * sizeof a char (inbytes) (3) 我经常使用它。 - A.Clymer
如果你想建立声誉,就需要通过提供好的答案来实现。最新的编辑至少消除了之前的错误,但现在它甚至不是一个答案,而是一个评论。所有其他答案都涉及到strlen()并给出了一些有意义的解释,而这个答案并不值得点赞。 - Crowman
如果您留下一个合适的答案,我将很高兴地取消对您的负评。如果您留下一个好的答案,我将很高兴地给您点赞。您原始的代码无法在任何C编译器上编译,无论是嵌入式还是其他。 - Crowman
它不包含您原始答案中的有问题的代码,因此与重点无关。1/2始终为零。请停止浪费我的时间。 - Crowman
@PaulGriffiths 好了吗? - A.Clymer

0

找到字符串大小字节有两种方法:

第一种解决方案:

# include <iostream>
# include <cctype>
# include <cstring>
using namespace std;

int main()
{
    char str[] = {"A lonely day."};
    cout<<"The string bytes for str[] is: "<<strlen(str);
    return 0;
}

第二种解决方案:

# include <iostream>
# include <cstring>
using namespace std;

int main()
{
    char str[] = {"A lonely day."};
    cout<<"The string bytes for str[] is: "<<sizeof(str);
    return 0;
}

两个解决方案产生了不同的输出。阅读后我会给你解释。
第一个解决方案使用strlen,基于cplusplus.com,

C字符串的长度由终止空字符决定: 一个C字符串的长度是从字符串开头到终止空字符的字符数(不包括终止空字符本身)。

这可以解释为什么第一个解决方案输出正确的字符串大小字节,而第二个解决方案输出错误的字符串大小字节。但如果您还是不明白,请继续阅读。
第二个解决方案使用sizeof来查找字符串大小字节。根据this SO答案,它说(进行修改):

sizeof("f") 必须返回 2 个字符串大小字节,一个用于 'f',另一个用于终止符 '\0' (终止空字符)。

这就是为什么输出的字符串大小是14个字节。一个是整个字符串,另一个是'\0'。
结论:
为了得到第二种解决方案的正确答案,您必须执行sizeof(str)-1

参考文献:

  1. 字符串字面量的大小
  2. https://cplusplus.com/reference/cstring/strlen/?kw=strlen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接