当'sizeof'应用于字符串时,为什么它会返回其大小(作为strlen)?

时间:2012-01-21 13:26:14

标签: c

如果我有一个字符串:

char s1[]="hello, how are you?";
printf("%d\n",sizeof(s1));

它打印确切的,正确的字符数,20。但是如果我有一个由指针初始化的字符串:

char *s2;
s2=(char*)malloc(sizeof(char));
strcpy(s2,s1);
printf("%d\n",sizeof(s2));

它打印指针的大小,这取决于机器(在我的机器上,8)。 那么为什么s2为8个字节,s1为20个字节,因为它们是相同的字符串?

6 个答案:

答案 0 :(得分:10)

它们不是相同的字符串,甚至是相同的类型。 char s2[]是一个数组,它的大小是其元素大小的总和。 char *s2指针,它的大小为指针。

sizeof()是(在C89中)编译时运算符,它必须在编译时知道它的参数大小。由于指针可以来自任何地方,sizeof()无法知道已分配内存的大小,但数组总是在编译时给出一个大小(除了C99的VLA之外,sizeof()可以返回该内存的大小。

答案 1 :(得分:3)

请记住,数组不是指针;在一种情况下,你得到一个数组的大小,在另一种情况下你得到指针的大小。

应用于字符串的sizeof运算符会产生字符串的字符数,包括尾随空字符。

在第二种情况下,您不是计算字符串的大小,而是计算字符串指针的大小,因此它会产生指针类型的大小。

char *s2;
s2=(char*)malloc(sizeof(char));
strcpy(s2,s1);

这段代码错了;你只为一个char分配空间。您需要为整个字符串分配空间:

char *s2;
s2 = malloc(sizeof s1);
strcpy(s2, s1);

最后,关于strlen函数(因为你提到过它):字符串的长度与字符串的大小不同。字符串的长度是尾随,终止空字符前面的字符数,而字符串的大小是包含空字符的字符串的字符数。

答案 2 :(得分:3)

char s2[]是一个静态分配的数组,它全部在堆栈上,运算符sizeof有一个重载版本,可以测量静态分配的数组的大小,正如delnan所评论的那样。

char* s2是一个指针,分配的字符串(malloc)在堆上。

答案 3 :(得分:1)

sizeof返回您传入的数据类型的大小。当您传入char[20]时,数据类型占用20个字节,但是当您传入char*时需要机器字

答案 4 :(得分:1)

这是定义。当sizeof运算符应用于数组时,它将被编译器替换为数组的长度(在编译阶段)。当它应用于指针时,编译器将其替换为指针的大小。

答案 5 :(得分:1)

忽略在第二种情况下你没有分配足够内存的事实(它应该是malloc(<number of characters to be stored>+1)),这两个s2不是一回事。

在第一种情况下,你有一个数组;您正在使用特殊的字符串初始化语法,该语法将导致已初始化为该字符串的正确大小的数组。数组上sizeof的大小正确(以char为单位)。

在第二种情况下,你有一个指针,它不知道它指向的有多大。指针上的sizeof返回指针的大小,在32位机器上,它是4个字节= 32位,因为32位是存储指向32位中每个可能的内存位置所需的所有空间地址空间。