char*
和int*
之间有什么区别?当然,它们的类型不同,但我怎么写呢
char* s1="hello world";
作为
"hello world"
它不是一个字符,它是一个字符数组,我不能写
*s1
作为
char* s1 = {'h','e','l','l','o',' ','w','o','r','l','d'};
和
int* a = {2,3,1,45,6};
有什么区别?
答案 0 :(得分:8)
这非常简单:字符串文字,即"foobar"
被编译为一个字符数组,存储在程序的静态部分(即存储所有常量的地方)并且以空值终止。然后,将此赋值给变量只需将指向此内存的指针赋给变量。例如,const char* a = "foo";
会将存储"foo"
的地址指定给a
。
简而言之,字符串常量已经将内存存储在其中。
相反,没有为指针定义用初始化列表初始化指针(即花括号内的元素列表)。非正式地,初始化列表的问题 - 与字符串文字形成对比 - 是没有"带来自己的内存" 。因此,我们必须提供初始化列表可以存储其字符的内存。这是通过声明一个数组而不是一个指针来完成的。编译好了:
char s1[11]={'h','e','l','l','o',' ','w','o','r','l','d'}
现在,我们通过将s1
声明为数组来提供存储字符的空间。
请注意,您可以使用指针的大括号初始化,例如:
char* c2 = {nullptr};
然而,虽然语法似乎相同,但这种情况完全不同,称为统一初始化,只需使用c2
初始化nullptr
。
答案 1 :(得分:3)
在第一种情况下,字符串文字会衰减为指向 const char 的指针。虽然s1
确实应该是const char *
,但是一些编译器允许另一种形式作为扩展:
const char* s1 = "hello world" ;
sting文字是const char
的数组,我们可以从draft C++ standard部分2.14.5
字符串文字中看到这一点说(强调我的前进):
也引用普通的字符串文字和UTF-8字符串文字 作为窄字符串文字。窄字符串文字具有类型“数组 of n
const char
“,其中 n 是下面定义的字符串大小, 并具有静态存储时间(3.7)。
将数组转换为指针的内容将在4.2
数组到指针转换部分中介绍:
[...]具有类型''数组类型''的表达式转换为 带有''指向类型'的指针的表达式,指向初始值 数组对象的元素,而不是左值。[...]
您的其他情况不起作用,因为标量可以是算术类型,枚举类型或指针类型只能使用括号内的单个元素进行初始化,这将在草案C ++标准部分 {{1 分配和复合赋值运算符 5.17
列表初始化段 3 ,其中说:
对象或类型T的引用的列表初始化定义为 如下:
然后列举不同的案例,对于这种情况,唯一适用于右侧的案例是以下子弹:
否则,如果初始化列表具有E和E类型的单个元素 T不是引用类型或引用类型 与E相关的引用,对象或引用从中初始化 那个元素;如果要求缩小转换(见下文) 将元素转换为T,程序格式不正确。
要求列表包含单个元素,否则最终的子弹应用:
否则,该程序格式不正确。
在您的两种情况下,即使将初始化程序缩减为一个变量,类型也是不正确的
8.5.1
是一个字符,h
是2
,不会转换为指针。
通过将结果分配给数组,可以使分配工作:
int
这将在 char s1[] = { 'h', 'e', 'l', 'l', 'o',' ', 'w', 'o', 'r', 'l', 'd' } ;
int a[] = { 2, 3, 1, 45, 6 } ;
聚合部分中介绍:
使用大括号括起来初始化的未知大小的数组 初始化列表包含n个初始化子句,其中n应为 大于零,定义为具有n个元素(8.3.4)。 [例如:
8.5.1
将x声明并初始化为具有三个的一维数组 因为没有指定大小,并且有三个初始值设定项。 -end example]空的初始化列表{}不得用作 初始化子句用于未知bound.104的数组
注意:
说没有为指针定义一个brace-init-list是不正确的,它完全可用于指针:
int x[] = { 1, 3, 5 };