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

如果我有一个字符串:

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

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

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

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

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

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

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

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

请记住,数组不是指针; 在一种情况下,您获得数组的大小,在另一种情况下,您获得指向它的指针的大小。

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

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

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

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

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

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

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

忽略在第二种情况下没有分配足够内存的事实(它应该是malloc(+1) ),这两个s2不是同一个东西。

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

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

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