如果我有一个字符串:
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个字节,因为它们是相同的字符串?
答案 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位中每个可能的内存位置所需的所有空间地址空间。