问题:为什么这两种数组声明的sizeof()的输出有差异?
回答:这条语句声明一个名为q的变量,类型为char [],指向一个内存位置,该位置包含“Hello”。
char q[] = "Hello";
的sizeof(q)是6,因为字符串 “Hello” 是由 'H', 'E', 'L', 'L',的 'O', '\ 0',它包括计数中的空字符。
该语句声明一个名为p的变量,其类型为char [],指向保留5个字符的内存位置。
char p[5];
注意,这取决于内存对齐标志的编译器,你实际上可能有6个,8个或更多字符的在预留给p位置保留。如果你引用或赋值p [5](这是p []数组中的序数第六个字符),C将不会投诉。
sizeof(p)是5,因为编译器记录了你为p声明的内存位置有多大。所以sizeof(p)和sizeof(q)返回不同的值,因为p和q被声明为不同的值并引用不同的实体。
问题:printf()如何知道何时停止,在声明两个数组时没有添加空字符。
答案:strlen()函数调用都会计算非NULL char的个数。所以这两个strlen函数都会调用char的直到找到NULL终止符。至少在p + 5的存储位置被赋予另一个值之前,p和q都有。这是因为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的值(用'\ 0'替换'X')。
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文本字符串如“你好”或“世界”是由NULL炭终止,并且包括炭在字符串的大小。 strcpy()函数复制整个字符串,包括最后的NULL字符。
您应该使用strncpy或检查目标字符串大小。请注意,当您使用strcpy(p,q)时,您复制了比p []分配的更多的字符(NULL终止符)。这是你想避免的。 C不对数组进行边界检查,所以它会让你执行strcpy。虽然lint会检测到这个错误。
当你明白0x0或'\ 0'或空字符的重要性时......你将不再需要这个问题了...... –