我有两个问题:
sizeof
我正在尝试理解以下C代码的输出。
printf("a: %ld\n", sizeof("a")); // 2
printf("abc: %ld\n", sizeof("abc")); // 4
它似乎总是大于指定的实际字符数。
文档建议返回的值表示对象的大小(在本例中为字符串),以字节为单位。因此,如果a
的大小为我们提供了2
个字节,那么我很好奇a
如何代表16位信息。
如果我查看ASCII字符a
的二进制表示,我可以看到它是01100001
。但是这只显示了1个字节中的3个比特。
另外,大字符串如何存储到C中的变量中?我是否正确地认为它们必须存储在数组中,如下所示:
char my_string[5] = "hello";
有趣的是,当我有一些代码时:
char my_string = "hello";
printf("my_string: %s\n", my_string);
我遇到两个编译器错误:
- incompatible pointer to integer conversion initializing 'char' with an expression of type 'char [6]'
- format specifies type 'char *' but the argument has type 'char'
......我不明白。首先,它声明当只有5个字符时,类型被假定为[6]
的大小。其次,这里提到一个指针对我来说似乎很奇怪?为什么printf
期望一个指针,为什么不在指向整数错误的指针中指定变量/数组的长度?
顺便说一下,我似乎可以将变量/数组的长度设置为5而不是6,它将按照我预期的char my_string[5] = "hello";
工作。
我可能只是遗漏了一些关于比特和字符串如何在C中工作的基本/基本的东西。
理解这一点的任何帮助都将受到赞赏。
答案 0 :(得分:1)
问题的第一部分是由于字符串存储在C中的方式.C中的字符串只不过是一系列字符(char
),最后添加了\0
,这就是你在做sizeof时看到+1的原因。请注意,如果您要说char my_string[4] = "hello";
,您还会收到编译错误,说明此字符串的大小不够。这也与此有关。
现在进入第二部分,字符串本身就是一系列字符。但是,您不能将每个字符自己存储在变量中。您可以使用指针来访问这些系列字符,以便从内存的某些部分访问它们。有关C中指针和字符串的更多信息,请访问:Pointer to a String in C
答案 1 :(得分:1)
在C中,字符串是一系列字符值,后跟零值终结符。例如,字符串"hello"
是字符值{'h', 'e', 'l', 'l', 'o', 0 }
1 的序列。字符串(包括字符串文字)存储为char
(或wchar_t
的数组,用于宽字符字符串)。要考虑终结符,数组的大小必须始终大于字符串中的字符数:
char greeting[6] = "hello";
greeting
的存储空间如下所示
+---+
greeting: |'h'| greeting[0]
+---+
|'e'| greeting[1]
+---+
|'l'| greeting[2]
+---+
|'l'| greeting[3]
+---+
|'o'| greeting[4]
+---+
| 0 | greeting[5]
+---+
字符串文字的存储大致相同 2 :
+---+
"hello": |'h'| "hello"[0]
+---+
|'e'| "hello"[1]
+---+
|'l'| "hello"[2]
+---+
|'l'| "hello"[3]
+---+
|'o'| "hello"[4]
+---+
| 0 | "hello"[5]
+---+
是的,您可以将下标运算符[]
应用于字符串文字,就像任何其他数组表达式一样。
除非它是sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,表达式为类型“N
- T
的元素”将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组的第一个元素。因此,字符串文字"hello"
是“char
的6元素数组”类型的表达式。如果我将该文字作为参数传递给像
printf( "%s\n", "hello" );
然后两个字符串文字表达式 "%s"
和"hello"
都从“{4}元素char
” 3 和“char
的6元素数组”指向“char
”的指针,因此printf
接收的是指针值,而不是数组值。
您已经看到转换规则有两个例外。当您使用sizeof
运算符并且得到的值比您预期的多一个时,您在代码中看到了它。 sizeof
计算存储操作数所需的字节数。由于零终结符,它需要N + 1个字节来存储一个N字符串。
第二个例外是上面greeting
数组的声明;因为我使用字符串文字来初始化数组,所以文字不会首先转换为指针值。请注意,您可以将该声明写为
char greeting[] = "hello";
在这种情况下,数组的大小取自初始化程序的大小。
当数组表达式是一元&
运算符的操作数时,会发生第三个异常。表达式char
不是评估指向char **
(&greeting
)的指针,而是求值为“指向 6元素数组的指针 {{ 1}}“,或char
。
字符串的长度是零终止符之前的字符数。处理字符串的所有标准库函数都希望看到终结符。存储该字符串的数组的 size 必须至少大于您要存储的字符串的最大长度。
<小时/>
char (*)[6]
而不是裸'\0'
来表示字符串终止符;他们的意思是一样的。
0
算作单个字符。