#include <stdio.h>
int main()
{
char *str1 = "Abcde";
char str2[] = "Abcde";
printf("sizeof(str1) = %d, sizeof(str2) = %d sizeof(*str1) = %d",
sizeof(str1), sizeof(str2),sizeof(*str1));
return 0;
}
以上代码给出了sizeof(*str1) =1
的输出。有人可以解释为什么我期望它在取消引用时成为sizeof("Abcde")
。
答案 0 :(得分:2)
sizeof(*str1)
之所以是1
,因为:
str1
是char *
*str1
是char
根据定义,char
的大小为1
。
将"Abcde"
分配给char *
后,您将失去该原始字符串的所有上下文,包括其大小。
答案 1 :(得分:2)
其他答案正确地说明了sizeof (*str) == 1
的原因,但是它们并不能解决您可以理解的困惑。
C数组在某种意义上是二等公民。数组对象是实际对象,就像任何其他类型的对象(整数,结构等)一样,但是该语言提供的操作很少,可以直接对数组进行操作。
相反,数组对象通常通过指向其元素的指针进行操作。
在您的示例中,您有:
char *str1 = "Abcde";
字符串文字"Abcde"
对应于类型char[6]
的匿名数组对象(字符串的长度为5,结尾的'\0'
空字符为1)。因此sizeof "Abcde" == 6
。
但是str1
不是指向该数组对象的指针;它只是指向其初始元素的指针,该初始元素包含字符'A'
。如果要访问数组的其他元素(字符'b'
,'c'
等),则需要执行 pointer算术来使指针通过数组对象的元素。
所以最初是*str1 == 'A'
,但是在++str1
之后是`* str1 =='b'。
如果要打印字符串的值,可以执行以下操作:
printf("%s\n", str1);
和printf
函数将在内部执行前进到字符串字符所需的指针算法。
这就是sizeof (*str) == 1
的原因。它仅指向数组对象的单个元素。我们可以使用它来访问其他元素,但是指针值本身不包含有关数组大小的任何信息。 (这就是终止'\0'
的作用,因此我们无需事先知道字符串的大小就可以识别字符串的结尾。)
请注意,您可以具有指向整个数组对象的指针:
char (*array_ptr)[6] = &"Abcde";
和sizeof *array_ptr == 6
-但这没有您预期的有用。 array_ptr
只能指向一个由6个元素组成的数组,并且由于printf
和strlen
之类的函数需要char*
指针,因此您不能直接使用{{ 1}}。 (在处理多维数组时,确实会显示数组对象的指针-数组数组。)
与整个数组对象相反,指向数组元素的指针更加灵活,标准库广泛使用它们。缺点是您必须自己跟踪数组的大小,例如通过将其作为额外的参数传递或使用诸如array_ptr
之类的前哨值来标记数组的结尾。
答案 2 :(得分:1)
因为*str1
是char
。
char
是一个字节。
一个字节的大小为一个。
答案 3 :(得分:0)
sizeof
有两种语法形式:
sizeof (TYPE)
,其中TYPE是一种类型(例如int
,char
等)sizeof expr
,其中expr
是任何表达式(例如1
或*ptr
等)请注意,第二种形式中没有()
!无论如何,TYPE
或expr
都不会被评估(正如标准所说:only for its size
)
注意:存在第三种(隐藏的)形式:
sizeof object
;对象是一些标识符在以下情况下:
char buff[123];
size_t sz = sizeof buff;
,sz
将是123
,因此buff
不会被提升/降级为指针。
注意:sizeof
运算符的优先级很高(请检查表!),因此
sz = sizeof 1+2;
sz将等于sizeof(int) + 2
在您的情况下,*str
将是一个字符,其值为'A':其大小将为一个:字符的大小。
仅此而已。