如果字符串中间出现空字符怎么办?
What if a null character is present in the middle of a string?
我知道字符串的结尾由空字符表示,但我无法理解以下代码的输出。
#include <stdio.h>
#include <string.h>
int
main(void)
{
char s[] = "Hello[=10=]Hi";
printf("%d %d", strlen(s), sizeof(s));
}
输出:5 9
如果strlen()
检测到字符串在o结尾处结束,那么为什么sizeof()
不做同样的事情?即使它不做同样的事情,'\0' 不是一个 空字符(即只有一个字符),所以答案不应该是 8 吗?
sizeof
运算符不提供字符串的长度,而是提供其操作数类型的大小。由于在您的代码中操作数是一个数组,因此 sizeof
为您提供了包含两个 null
个字符的数组大小。
如果是这样的话
const char *string = "This is a large text[=10=]This is another string";
printf("%zu %zu\n", strlen(string), sizeof(string));
结果会很不一样,因为 string
是指针而不是数组。
注意:对 size_t
使用 "%zu"
说明符,这就是 strlen()
returns,并且是 sizeof
给出的值的类型。
If strlen() detects the end of the string at the end of o, then why doesn't sizeof() do the same thing?
strlen
仅适用于字符串(字符数组),而 sizeof
适用于所有数据类型。 sizeof
计算任何给定数据类型的确切内存空间;而 strlen
提供字符串的长度(不包括 NULL 终止符 [=16=]
)。所以在正常情况下,对于典型的字符数组 s
:
是这样的
char s[] = "Hello";
strlen( s ) + 1 = sizeof( s ); // +1 for the [=10=]
在你的情况下它是不同的,因为你在字符数组的中间有一个 NULL 终止符 s
:
char s[] = "Hello[=11=]Hi";
这里,strlen
会检测到第一个[=16=]
并给出长度为5。但是sizeof
会计算总空格数来保存字符数组,包括两个 [=16=]
,所以这就是它给出 9 作为第二个输出的原因。
strlen()
不关心字符串的 实际 大小。它查找空字节并在看到第一个空字节时停止。
但是 sizeof()
运算符知道总大小。它不关心你在字符串文字中的字节数。您也可以在字符串中包含所有空字节,并且 sizeof()
仍会给出正确的数组大小(在这种情况下,strlen() 会重新运行 0
)。
它们没有可比性;他们做不同的事情。
C 中的字符数组和指向字符数组的指针不是一回事。虽然您可以打印地址并获得相同的价值。
C 中的数组由以下内容组成。
- 数组大小
- 它的地址/指针
- 同质元素类型
指针仅由以下部分组成:
- 地址
类型信息
char s[] = "Hello[=10=]Hi";
printf("%d %d", strlen(s), sizeof(s));
此处您使用 sizeof() 计算数组的大小(即 s 变量),即 9。
但是,如果您将此字符数组视为字符串,那么 array(string now) 会丢失其大小信息,并成为指向字符的指针。当您尝试使用 %s
打印字符数组时,也会发生同样的事情。
所以strlen()
和%s
将字符数组视为字符串,它只使用它的地址信息。你可以猜到,strlen() 不断递增指针来计算长度 up-to 第一个空字符。当它遇到一个空字符时你得到一个长度up-to那个点。
所以 strlen()
给你 5 并且不计算 null
个字符。
因此 sizeof()
运算符仅告知其操作数的大小。如果你给它数组变量而不是它利用数组大小信息并告诉大小而不考虑空字符位置。
但是,如果你给 sizeof()
pointer to array of characters
,它会找到没有大小信息的指针并打印指针的大小,在 64 位系统上通常为 64 位/8 字节,在 32 位系统上通常为 32 位/4 字节.
如果你使用像 "Hello"
这样的双引号初始化你的字符数组,那么还有一件事比 C 添加一个空字符,否则它不会在 {'H','e','l','l','o'}
.
的情况下
使用 gcc 编译器。希望对理解有所帮助。
strlen()
计算字符串的长度。这是通过 returning 之前(不包括)'[=14=]'
字符的字符数来完成的。 (请参阅下面的手册页。)
sizeof()
returns 给定变量的字节数(或 data-type)。请注意,您的示例 "Hello[=16=]Hi"
有 9 个字符。但是您似乎不明白问题中字符 9 的来源。让我先解释给定的字符串。您的示例字符串是:
"Hello[=10=]Hi"
这可以写成下面的数组:
['H', 'e', 'l', 'l', 'o', '[=11=]', 'H', 'i', '[=11=]']
注意最后一个 '[=14=]'
字符。当使用字符串引号时,编译器以 '[=14=]'
字符结束字符串。这意味着 ""
也是 ['[=20=]']
,因此有 1 个元素。
注意 sizeof()
NOT return 数组中的元素数。它 returns 字节数。 char
是 1 个字节,因此 sizeof()
是 return 元素的数量。但是,如果您使用任何其他数据类型,例如,如果您在 [1, 2, 3, 4]
上调用 sizeof()
,它将 return 16。因为 int
是 4 个字节,并且数组有 4 个元素。
注意 将数组作为参数传递只会传递指针。如果您将 s
传递给另一个函数并调用 sizeof()
,它将 return 指针的大小,这与 sizeof(void *)
相同。这是一个独立于数组的固定长度。
STRLEN(3) BSD Library Functions Manual STRLEN(3)
NAME
strlen, strnlen -- find length of string
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <string.h>
size_t
strlen(const char *s);
size_t
strnlen(const char *s, size_t maxlen);
DESCRIPTION
The strlen() function computes the length of the string s. The strnlen()
function attempts to compute the length of s, but never scans beyond the
first maxlen bytes of s.
RETURN VALUES
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
SEE ALSO
string(3), wcslen(3), wcswidth(3)
STANDARDS
The strlen() function conforms to ISO/IEC 9899:1990 (``ISO C90'').
The strnlen() function conforms to IEEE Std 1003.1-2008 (``POSIX.1'').
BSD February 28, 2009 BSD
As name literal 本身暗示字符串文字是用双引号括起来的字符序列。这个字符序列隐含地附加了一个终止零。
所以双引号中的任何字符都是字符串文字的一部分。
当字符串文字用于初始化字符数组时,其所有字符(包括终止零)用作字符数组相应元素的初始值设定项。
每个字符串文字依次具有字符数组类型。
例如,C 中的这个字符串文字 "Hello[=15=]Hi"
具有类型 char[9]
:引号中包含的 8 个字符加上隐式终止零。
所以在内存中,这个字符串字面量存储为
{ 'H', 'e', 'l', 'l', 'o', '[=10=]', 'H', 'i', '[=10=]' }
运算符 sizeof
returns 对象占用的字节数。所以对于运算符sizeof
上面的字符串字面量会return取值9
——就是字面量在内存中占用的字节数
如果你写了 "Hello[=15=]Hi"
那么编译器可能不会自己从文字中删除这部分 Hi
。它必须将它与用引号括起来的文字的其他字符一起存储在内存中。
sizeof
运算符 return 是 C 中任何对象的字节大小,而不仅仅是字符数组。
一般而言,字符数组可以存储任何原始数据,例如从二进制文件中读取的一些二进制数据。在这种情况下,用户和程序不会像字符串那样考虑此数据,结果处理方式与字符串不同。
标准C函数strlen
是专门为字符数组编写的,用于查找字符数组中存储的字符串的长度。它不知道什么数据存储在数组中以及它们是如何写入其中的。它所做的只是搜索字符数组中的第一个零字符,然后 returns 字符数组中零字符之前的字符数。
您可以在一个字符数组中依次存储多个字符串。例如
char s[12];
strcpy( s, "Hello" );
strcpy( s + sizeof( "Hello" ), "World" );
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
如果你要像这样定义一个二维数组
char t[2][6] = { "Hello", "World" };
然后在内存中它会像上面的one-dimensional数组一样被存储。所以你可以写
char *s = ( char * )t;
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
再举个例子。标准 C 函数 strtok
可以将存储在字符数组中的一个字符串拆分为多个字符串,用零字节替换用户指定的分隔符。结果,字符数组将包含多个字符串。
例如
char s[] = "Hello World";
printf( "%zu\n", sizeof( s ) ); // outputs 12
strtok( s, " " );
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
printf( "%zu\n", sizeof( s ) ); // outputs 12
最后的printf 语句将输出相同的值,等于12,因为数组占用相同的字节数。分配给数组的内存中只有一个字节从 ' '
更改为 '[=26=]'
.
我知道字符串的结尾由空字符表示,但我无法理解以下代码的输出。
#include <stdio.h>
#include <string.h>
int
main(void)
{
char s[] = "Hello[=10=]Hi";
printf("%d %d", strlen(s), sizeof(s));
}
输出:5 9
如果strlen()
检测到字符串在o结尾处结束,那么为什么sizeof()
不做同样的事情?即使它不做同样的事情,'\0' 不是一个 空字符(即只有一个字符),所以答案不应该是 8 吗?
sizeof
运算符不提供字符串的长度,而是提供其操作数类型的大小。由于在您的代码中操作数是一个数组,因此 sizeof
为您提供了包含两个 null
个字符的数组大小。
如果是这样的话
const char *string = "This is a large text[=10=]This is another string";
printf("%zu %zu\n", strlen(string), sizeof(string));
结果会很不一样,因为 string
是指针而不是数组。
注意:对 size_t
使用 "%zu"
说明符,这就是 strlen()
returns,并且是 sizeof
给出的值的类型。
If strlen() detects the end of the string at the end of o, then why doesn't sizeof() do the same thing?
strlen
仅适用于字符串(字符数组),而 sizeof
适用于所有数据类型。 sizeof
计算任何给定数据类型的确切内存空间;而 strlen
提供字符串的长度(不包括 NULL 终止符 [=16=]
)。所以在正常情况下,对于典型的字符数组 s
:
char s[] = "Hello";
strlen( s ) + 1 = sizeof( s ); // +1 for the [=10=]
在你的情况下它是不同的,因为你在字符数组的中间有一个 NULL 终止符 s
:
char s[] = "Hello[=11=]Hi";
这里,strlen
会检测到第一个[=16=]
并给出长度为5。但是sizeof
会计算总空格数来保存字符数组,包括两个 [=16=]
,所以这就是它给出 9 作为第二个输出的原因。
strlen()
不关心字符串的 实际 大小。它查找空字节并在看到第一个空字节时停止。
但是 sizeof()
运算符知道总大小。它不关心你在字符串文字中的字节数。您也可以在字符串中包含所有空字节,并且 sizeof()
仍会给出正确的数组大小(在这种情况下,strlen() 会重新运行 0
)。
它们没有可比性;他们做不同的事情。
C 中的字符数组和指向字符数组的指针不是一回事。虽然您可以打印地址并获得相同的价值。 C 中的数组由以下内容组成。
- 数组大小
- 它的地址/指针
- 同质元素类型
指针仅由以下部分组成:
- 地址
类型信息
char s[] = "Hello[=10=]Hi"; printf("%d %d", strlen(s), sizeof(s));
此处您使用 sizeof() 计算数组的大小(即 s 变量),即 9。
但是,如果您将此字符数组视为字符串,那么 array(string now) 会丢失其大小信息,并成为指向字符的指针。当您尝试使用 %s
打印字符数组时,也会发生同样的事情。
所以strlen()
和%s
将字符数组视为字符串,它只使用它的地址信息。你可以猜到,strlen() 不断递增指针来计算长度 up-to 第一个空字符。当它遇到一个空字符时你得到一个长度up-to那个点。
所以 strlen()
给你 5 并且不计算 null
个字符。
因此 sizeof()
运算符仅告知其操作数的大小。如果你给它数组变量而不是它利用数组大小信息并告诉大小而不考虑空字符位置。
但是,如果你给 sizeof()
pointer to array of characters
,它会找到没有大小信息的指针并打印指针的大小,在 64 位系统上通常为 64 位/8 字节,在 32 位系统上通常为 32 位/4 字节.
如果你使用像 "Hello"
这样的双引号初始化你的字符数组,那么还有一件事比 C 添加一个空字符,否则它不会在 {'H','e','l','l','o'}
.
使用 gcc 编译器。希望对理解有所帮助。
strlen()
计算字符串的长度。这是通过 returning 之前(不包括)'[=14=]'
字符的字符数来完成的。 (请参阅下面的手册页。)
sizeof()
returns 给定变量的字节数(或 data-type)。请注意,您的示例 "Hello[=16=]Hi"
有 9 个字符。但是您似乎不明白问题中字符 9 的来源。让我先解释给定的字符串。您的示例字符串是:
"Hello[=10=]Hi"
这可以写成下面的数组:
['H', 'e', 'l', 'l', 'o', '[=11=]', 'H', 'i', '[=11=]']
注意最后一个 '[=14=]'
字符。当使用字符串引号时,编译器以 '[=14=]'
字符结束字符串。这意味着 ""
也是 ['[=20=]']
,因此有 1 个元素。
注意 sizeof()
NOT return 数组中的元素数。它 returns 字节数。 char
是 1 个字节,因此 sizeof()
是 return 元素的数量。但是,如果您使用任何其他数据类型,例如,如果您在 [1, 2, 3, 4]
上调用 sizeof()
,它将 return 16。因为 int
是 4 个字节,并且数组有 4 个元素。
注意 将数组作为参数传递只会传递指针。如果您将 s
传递给另一个函数并调用 sizeof()
,它将 return 指针的大小,这与 sizeof(void *)
相同。这是一个独立于数组的固定长度。
STRLEN(3) BSD Library Functions Manual STRLEN(3) NAME strlen, strnlen -- find length of string LIBRARY Standard C Library (libc, -lc) SYNOPSIS #include <string.h> size_t strlen(const char *s); size_t strnlen(const char *s, size_t maxlen); DESCRIPTION The strlen() function computes the length of the string s. The strnlen() function attempts to compute the length of s, but never scans beyond the first maxlen bytes of s. RETURN VALUES The strlen() function returns the number of characters that precede the terminating NUL character. The strnlen() function returns either the same result as strlen() or maxlen, whichever is smaller. SEE ALSO string(3), wcslen(3), wcswidth(3) STANDARDS The strlen() function conforms to ISO/IEC 9899:1990 (``ISO C90''). The strnlen() function conforms to IEEE Std 1003.1-2008 (``POSIX.1''). BSD February 28, 2009 BSD
As name literal 本身暗示字符串文字是用双引号括起来的字符序列。这个字符序列隐含地附加了一个终止零。
所以双引号中的任何字符都是字符串文字的一部分。
当字符串文字用于初始化字符数组时,其所有字符(包括终止零)用作字符数组相应元素的初始值设定项。
每个字符串文字依次具有字符数组类型。
例如,C 中的这个字符串文字 "Hello[=15=]Hi"
具有类型 char[9]
:引号中包含的 8 个字符加上隐式终止零。
所以在内存中,这个字符串字面量存储为
{ 'H', 'e', 'l', 'l', 'o', '[=10=]', 'H', 'i', '[=10=]' }
运算符 sizeof
returns 对象占用的字节数。所以对于运算符sizeof
上面的字符串字面量会return取值9
——就是字面量在内存中占用的字节数
如果你写了 "Hello[=15=]Hi"
那么编译器可能不会自己从文字中删除这部分 Hi
。它必须将它与用引号括起来的文字的其他字符一起存储在内存中。
sizeof
运算符 return 是 C 中任何对象的字节大小,而不仅仅是字符数组。
一般而言,字符数组可以存储任何原始数据,例如从二进制文件中读取的一些二进制数据。在这种情况下,用户和程序不会像字符串那样考虑此数据,结果处理方式与字符串不同。
标准C函数strlen
是专门为字符数组编写的,用于查找字符数组中存储的字符串的长度。它不知道什么数据存储在数组中以及它们是如何写入其中的。它所做的只是搜索字符数组中的第一个零字符,然后 returns 字符数组中零字符之前的字符数。
您可以在一个字符数组中依次存储多个字符串。例如
char s[12];
strcpy( s, "Hello" );
strcpy( s + sizeof( "Hello" ), "World" );
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
如果你要像这样定义一个二维数组
char t[2][6] = { "Hello", "World" };
然后在内存中它会像上面的one-dimensional数组一样被存储。所以你可以写
char *s = ( char * )t;
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
再举个例子。标准 C 函数 strtok
可以将存储在字符数组中的一个字符串拆分为多个字符串,用零字节替换用户指定的分隔符。结果,字符数组将包含多个字符串。
例如
char s[] = "Hello World";
printf( "%zu\n", sizeof( s ) ); // outputs 12
strtok( s, " " );
puts( s ); // outputs "Hello"
puts( s + sizeof( "Hello" ) ); // outputs "World"
printf( "%zu\n", sizeof( s ) ); // outputs 12
最后的printf 语句将输出相同的值,等于12,因为数组占用相同的字节数。分配给数组的内存中只有一个字节从 ' '
更改为 '[=26=]'
.