问题:为什么两种数组声明类型的 sizeof() 输出存在差异?
回答:该语句声明了一个名为 q 的变量,类型为 char[],指向保存“Hello”的内存位置。
char q[] = "Hello";
sizeof(q) 是 6,因为字符串 "Hello" 由 'H','e','l','l','o','\0' 组成,其中包括计数中的 NULL 字符。
该语句声明了一个名为 p 的变量,类型为 char[],指向保留 5 个字符的内存位置。
char p[5];
请注意,根据编译器的内存对齐标志,您实际上可能在保留给 p 的位置保留了 6、8 或更多 char。如果您引用或分配 p[5] (这是 p[] 数组中的序数第六个字符),C 不会抱怨。
sizeof(p) 是 5,因为编译器记录了您为 p 声明的内存位置有多大。所以 sizeof(p) 和 sizeof(q) 返回不同的值,因为 p 和 q 的声明不同并且引用不同的实体。
问题:strlen() & printf() 如何知道何时停止,声明两个数组时没有添加空字符。
答案:两个 strlen() 函数调用都计算非 NULL 字符的数量。因此,两个 strlen 函数都调用 count char,直到它们找到 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;
}
观察 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]=
诸如“Hello”或“World”之类的 AC 文字字符串以 NULL 字符结尾,并将该字符包含在字符串的大小中。strcpy() 函数复制整个字符串,包括末尾的 NULL 字符。
您应该使用 strncpy,或检查目标字符串大小。请注意,当您使用 strcpy(p,q) 时,您复制的字符(NULL 终止符)比 p[] 分配的要多。这是你想要避免的事情。C 不对数组进行边界检查,所以它会让你执行 strcpy。虽然 lint 会检测到这个错误。