Joh*_*uay 5 c arrays string pointers
可能重复:
C中的char s []和char*s有什么区别?
char*str ="..."和char str [N] ="......"之间的区别?
我有一些令我困惑的代码.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char* string1 = "this is a test";
char string2[] = "this is a test";
printf("%i, %i\n", sizeof(string1), sizeof(string2));
system("PAUSE");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当它输出string1的大小时,它打印4,这是预期的,因为指针的大小是4个字节.但是当它打印string2时,它输出15.我认为数组是一个指针,所以string2的大小应该与string1相同吗?那么为什么它为相同类型的数据(指针)打印出两种不同的大小呢?
Chr*_*utz 13
数组不是指针.在某些情况下,数组名称会衰减到指向数组第一个元素的指针:当你将它传递给函数时,将它分配给指针等等.但是否则数组是数组 - 它们存在于堆栈中,具有编译时可以确定的尺寸sizeof,以及所有其他好东西.
数组和指针是完全不同的动物.在大多数情况下,指定数组的表达式被视为指针.
首先,一点标准语言(n1256):
6.3.2.1左值,数组和函数指示符
...
3除非它是运算sizeof符或一元运算&符的操作数,或者是用于初始化数组的字符串文字,否则类型为"数组类型 " 的表达式是转换为表达式,类型为"指针输入指向该阵列对象的初始元素,不是左值".如果数组对象具有寄存器存储类,则行为未定义.
字符串文字"这是一个测试"是一个15元素的数组char.在宣言中
char *string1 = "this is a test";
Run Code Online (Sandbox Code Playgroud)string1被声明为指向char.根据上面的语言,表达式 "this is a test"的类型将转换char [15]为char *,并将结果指针值赋值给string1.
char string2[] = "this is a test";
Run Code Online (Sandbox Code Playgroud)
发生了不同的事情 更标准的语言:
6.7.8初始化
...
14字符类型数组可以用字符串文字初始化,可选择用大括号括起来.字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素.
...
22如果初始化未知大小的数组,则其大小由具有显式初始值设定项的最大索引元素确定.在其初始化列表的末尾,该数组不再具有不完整的类型.
在这种情况下,string2声明为数组char,其大小是从初始化程序的长度计算的,字符串文字的内容被复制到数组中.
这是一个假设的记忆图来说明正在发生的事情:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
no name 0x08001230 't' 'h' 'i' 's'
0x08001234 ' ' 'i' 's' ' '
0x08001238 'a' ' ' 't' 'e'
0x0800123C 's' 't' 0
...
string1 0x12340000 0x08 0x00 0x12 0x30
string2 0x12340004 't' 'h' 'i' 's'
0x12340008 ' ' 'i' 's' ' '
0x1234000C 'a' ' ' 't' 'e'
0x1234000F 's' 't' 0
字符串文字具有静态范围; 也就是说,它们的存储器在程序启动时被搁置并保持到程序终止.试图修改字符串文字的内容会调用未定义的行为; 底层平台可能允许也可能不允许,标准对编译器没有限制.最好表现为文字总是不可写的.
在我上面的内存映射中,字符串文字的地址在某种程度上与地址相关,string1并string2用来说明这一点.
无论如何,你可以看到string1,有一个指针类型,包含字符串文字的地址. string2作为数组类型,包含字符串文字内容的副本.
由于string2在编译时已知大小,因此sizeof返回数组中的大小(字节数).
该%i转换操作符不使用类型的表达式是正确的size_t.如果你在C99工作,请使用%zu.在C89中,您将使用%lu并将表达式转换为unsigned long:
C89: printf("%lu, %lu\n", (unsigned long) sizeof string1, (unsigned long) sizeof string2);
C99: printf("%zu, %zu\n", sizeof string1, sizeof string2);
Run Code Online (Sandbox Code Playgroud)
注意,这sizeof是一个操作符,而不是函数调用; 当操作数是表示对象的表达式时,括号不是必需的(尽管它们不会受到伤害).