C语言 字符数组的 strlen 和大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19148940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
strlen and size of for character arrays
提问by brokenfoot
I have the following code:
我有以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char p[5];
char q[]="Hello";
int i=0;
strcpy(p,"Hello");
printf("strlen(p)=%d\n",strlen(p));
printf("sizeof(p)=%d\n",sizeof(p));
printf("strlen(q)=%d\n",strlen(q));
printf("sizeof(q)=%d\n",sizeof(q));
for(i=0;i<6;i++)
{
printf("p[%d]=%c\tq[%d]=%c\n",i,p[i],i,q[i]);
}
return 0;
}
The output that I get is:
我得到的输出是:
strlen(p)=5
sizeof(p)=5
strlen(q)=5
sizeof(q)=6
p[0]=H q[0]=H
p[1]=e q[1]=e
p[2]=l q[2]=l
p[3]=l q[3]=l
p[4]=o q[4]=o
p[5]= q[5]=
- I know declaring array like q[]="some string" sets the size of the array equal to the number of characters in the string const, but why is there a difference in the output of sizeof() for both the types of array declaration?
- How does the strlen() & the printf() know when to stop, there was no null character added while declaring the two arrays.
- 我知道像 q[]="some string" 这样的声明数组会将数组的大小设置为等于字符串 const 中的字符数,但是为什么两种类型的数组声明的 sizeof() 输出存在差异?
- strlen() 和 printf() 如何知道何时停止,在声明两个数组时没有添加空字符。
回答by cnicutar
There are multiple questions in your question.
您的问题中有多个问题。
strcpy(p,"Hello");
strcpy(p,"Hello");
This is illegal since
pis only 5 chars long, so there's no room left for the terminating 0added bystrcpy. Consequently it is either not 0-terminated or the 0 byte was added outside the available space - callingstrlenon it is also undefined behavior or fishy at leastCalling
sizeofonpis okay and yields the correct value of 5.Calling
strlen(q)yields 5 because q indeed contains a 0 terminator - implicitly added by initializing with a string literal- and there are 5 chars before the 0Since it contains a 0 terminator,
qis really an array of 6 characterssosizeofyields 6.
这是非法的,因为
p只有5个字符长,所以就没有空间留给终端0被添加strcpy。因此,它要么不是 0 终止的,要么是在可用空间之外添加了 0 字节 - 调用strlen它也是未定义的行为或至少是可疑的调用没有问题
sizeof,p并产生正确的值 5。调用
strlen(q)产生 5 因为 q 确实包含一个 0 终止符 -通过用字符串文字初始化隐式添加- 并且在 0 之前有 5 个字符由于它包含一个 0 终止符,
q它实际上是一个包含 6 个字符的数组,因此sizeof产生 6。
回答by LihO
char p[5];
strcpy(p,"Hello");
copies 5 characters into pand writes the terminating null-character ('\0') at 6th position, i.e. out of the bounds of this array, which yields undefined behavior.
将 5 个字符复制到第 6 个位置p并写入终止空字符 ( '\0'),即超出此数组的边界,这会产生未定义的行为。
From manual page of strcpy:
从手册页strcpy:
"If the destination string of a strcpy() is not large enough, then anything might happen. Any time a program reads or copies data into a buffer, the program first needs to check that there's enough space."
“如果 strcpy() 的目标字符串不够大,那么任何事情都可能发生。任何时候程序读取或复制数据到缓冲区中,程序首先需要检查是否有足够的空间。”
回答by ChuckCottrill
Question: why is there a difference in the output of sizeof() for both the types of array declaration?
问题:为什么两种类型的数组声明的 sizeof() 输出有差异?
Answer: This statement declares a variable named q, with type char[], pointing at a memory location that holds "Hello".
答案:该语句声明了一个名为 q 的变量,其类型为 char[],指向保存“Hello”的内存位置。
char q[] = "Hello";
sizeof(q) is 6 because the string "Hello" is comprised of 'H','e','l','l','o','\0', which includes the NULL char in the count.
sizeof(q) 是 6,因为字符串“Hello”由 'H','e','l','l','o','\0' 组成,其中包括计数中的 NULL 字符。
This statement declares a variable named p, with type char[], pointing to a memory location where 5 char's are reserved.
该语句声明了一个名为 p 的变量,其类型为 char[],指向保留 5 个字符的内存位置。
char p[5];
Note that depending upon memory alignment flags to the compiler, you may actually have 6, 8, or more char's reserved at the location reserved to p. And C won't complain if you reference or assign p[5] (which is the ordinal sixth char in the p[] array).
请注意,根据编译器的内存对齐标志,您实际上可能在保留给 p 的位置保留了 6、8 或更多字符。如果您引用或分配 p[5](这是 p[] 数组中的第 6 个字符),C 不会抱怨。
sizeof(p) is 5 because the compiler has recorded how big the memory location you declared for p. So sizeof(p) and sizeof(q) return different values because p and q are declared differently and refer to different entities.
sizeof(p) 是 5,因为编译器已经记录了你为 p 声明的内存位置有多大。所以 sizeof(p) 和 sizeof(q) 返回不同的值,因为 p 和 q 的声明不同并且引用不同的实体。
Question: How does the strlen() & the printf() know when to stop, there was no null character added while declaring the two arrays.
问题: strlen() 和 printf() 如何知道何时停止,声明两个数组时没有添加空字符。
Answer: Both strlen() function calls count the number of non-NULL char's. So both strlen function calls count char's until they locate the NULL terminator. Which both p and q have, at least until the memory location at p+5 is assigned another value. This is because p and q are both allocated on the stack. Look at the addresses of p, q, and the integer i. Here is your function with additional variables added to help illustrate where p and q are located,
答案:两个 strlen() 函数调用都计算非 NULL 字符的数量。所以两个 strlen 函数调用 count char's 直到它们找到 NULL 终止符。p 和 q 都有,至少在 p+5 处的内存位置被分配另一个值之前。这是因为 p 和 q 都分配在堆栈上。查看 p、q 和整数 i 的地址。这是您添加了附加变量的函数,以帮助说明 p 和 q 的位置,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)<(b))?(b):(a))
int main()
{
char m0 = 'X';
char p[5];
char m1 = 'Y';
char q[]="Hello";
char m2 = 'Z';
int i=0;
strcpy(p,"World");
printf("strlen(p)=%d\n",strlen(p));
printf("sizeof(p)=%d\n",sizeof(p));
printf("strlen(q)=%d\n",strlen(q));
printf("sizeof(q)=%d\n",sizeof(q));
for(i=0;i<6;i++)
{
printf("p[%d]=%c\tq[%d]=%c\n",i,p[i],i,q[i]);
}
printf("m0=%x, %c\n",&m0,m0);
printf(" p=%x\n",p);
printf("m1=%x, %c\n",&m1,m1);
printf(" q=%x\n",q);
printf("m2=%x, %c\n",&m2,m2);
char *x;
for(x=min(&m0,&m2);x<max(&m0,&m2);x++)
{
printf("x[%x]=%c\n",x,*x);
}
return 0;
}
Observe that m0, m1, and m2 are adjacent to the arrays p[] and q[]. When run on my Linux system, we observe that the strcpy of "World" modifies the value of m0 (replaces the 'X' with '\0').
观察到 m0、m1 和 m2 与数组 p[] 和 q[] 相邻。在我的 Linux 系统上运行时,我们观察到“World”的 strcpy 修改了 m0 的值(将 'X' 替换为 '\0')。
strlen(p)=5
sizeof(p)=5
strlen(q)=5
sizeof(q)=6
p[0]=W q[0]=H
p[1]=o q[1]=e
p[2]=r q[2]=l
p[3]=l q[3]=l
p[4]=d q[4]=o
p[5]= q[5]=
m0=bfbea6a7,
p=bfbea6a2
m1=bfbea6a1, Y
q=bfbea69b
m2=bfbea69a, Z
x[bfbea69a]=Z
x[bfbea69b]=H
x[bfbea69c]=e
x[bfbea69d]=l
x[bfbea69e]=l
x[bfbea69f]=o
x[bfbea6a0]=
x[bfbea6a1]=Y
x[bfbea6a2]=W
x[bfbea6a3]=o
x[bfbea6a4]=r
x[bfbea6a5]=l
x[bfbea6a6]=d
x[bfbea6a7]=
A C literal string such as "Hello" or "World" is terminated by the NULL char, and includes that char in the size of the string. The strcpy() function copies the entire string, including the NULL char at the end.
诸如“Hello”或“World”之类的 AC 文字字符串以 NULL 字符结尾,并在字符串的大小中包含该字符。strcpy() 函数复制整个字符串,包括末尾的 NULL 字符。
You should use strncpy, or check the destination string size. Note that when you used strcpy(p,q), you copied more characters (the NULL terminator) than p[] had allocated. That is something you want to avoid. C does not do boundary checking on arrays, so it will let you perform the strcpy. Though lint would detect this error.
您应该使用 strncpy,或检查目标字符串大小。请注意,当您使用 strcpy(p,q) 时,您复制了比 p[] 分配的更多字符(NULL 终止符)。这是你想要避免的事情。C 不对数组进行边界检查,因此它可以让您执行 strcpy。虽然 lint 会检测到这个错误。
回答by goji
Strings in C are terminated by a NULcharacter '\0';
C 中的字符串以NUL字符 '\0'结尾;
This is why sizeof(q)returns 6, it has enough space to store the '\0'at the end.
You've sized p yourself to be able to hold 5 characters, not enough for the trailing '\0'.
这就是为什么sizeof(q)返回 6,它有足够的空间来存储'\0'最后的。您已经将 p 的大小设置为能够容纳 5 个字符,不足以容纳尾随的'\0'.
So, this code is undefined behaviour:
所以,这段代码是未定义的行为:
strcpy(p, "Hello");
strcpy(p, "Hello");
This is copying the '\0'into p[5], which is out-of-bounds.
这是复制'\0'into p[5],这是越界的。
回答by Charlie Burns
char p[5];
strcpy(p,"Hello");
This strcpy writes a 0 into p[5]. So it's out of bounds. The sizeof(p) is still 5 though. You have written over the end of p. It's incorrect and results in undefined behavior. In this case nothing bad happened and it went unnoticed.
这个 strcpy 将 0 写入 p[5]。所以越界了。不过 sizeof(p) 仍然是 5。你已经写在 p 的末尾了。这是不正确的并导致未定义的行为。在这种情况下,没有发生任何不好的事情并且没有引起注意。
The other string you have, has a length of 5 and a sizeof 6.
您拥有的另一个字符串的长度为 5,大小为 6。
回答by Shoe
The qchar array also contains the null terminating character. While the fixed size of pdoesn't allow the null character to be copied in. Notice that strlenwill check for the null character to count the amount of characters of a string, therefore not having one will probably cause undefined behavior.
的q字符数组还包含空终止字符。虽然固定大小的p不允许复制空字符。请注意,strlen将检查空字符以计算字符串的字符数,因此没有一个可能会导致未定义的行为。
回答by Johan Kotlinski
sizeof(q) is 6, since it contains null terminator.
sizeof(q) 是 6,因为它包含空终止符。
p does not hold enough space for the null terminator - so strlen(p) can be any random value. This is called undefined behavior.
p 没有为空终止符保留足够的空间 - 因此 strlen(p) 可以是任何随机值。这称为未定义行为。

