找回密码
 立即注册
搜索
热搜: 活动 通知
查看: 1244|回复: 8

const char* arr[]={"china"} 字面串为什么会转为指针?

[复制链接]

4

主题

12

回帖

105

积分

注册会员

积分
105
发表于 2023-12-27 18:12:44 | 显示全部楼层 |阅读模式
C语言规范说:如果以字面串形式出现在初始化器中的数组类型,不会转为会指向首元素的指针。
那么 const char* arr[]={"china"} 为什么会转为指针?这是否矛盾?


344

主题

255

回帖

2666

积分

管理员

积分
2666
发表于 2023-12-27 20:49:52 | 显示全部楼层

const char* arr[]={"china"}
这里,本身就是个字面串以初始化器的形式初始化数组,符合要求啊,怎么会矛盾呢?

点评

但是这里转换成指针了啊,按规范字面串初始化数组,不会转换啊  发表于 2023-12-27 21:33

344

主题

255

回帖

2666

积分

管理员

积分
2666
发表于 2023-12-27 22:06:50 | 显示全部楼层
站长 发表于 2023-12-27 20:49

const char* arr[]={"china"}
这里,本身就是个字面串以初始化器的形式初始化数组,符合要求啊,怎么会 ...

好吧,我没有仔细审题。
标准里说的是“用于初始化数组的字面串”(is a string literal used to initialize an array),应该是初始化一个字符数组,你这里实际上被初始化的是数组的元素(指针),不是数组。不符合标准的原意。

is a string literal used to initialize an array


using a string literal as the initializer of an array
不一样。

4

主题

12

回帖

105

积分

注册会员

积分
105
 楼主| 发表于 2023-12-27 22:18:02 | 显示全部楼层
本帖最后由 xiaocai 于 2023-12-27 22:23 编辑
站长 发表于 2023-12-27 22:06
好吧,我没有仔细审题。
标准里说的是“用于初始化数组的字面串”(is a string literal used to initiali ...

初始化数组元素?初始化数组?有点不好理解,脑子不够了,感觉都是在初始化数组啊。初始化了数组,不也是数组元素也初始化了。
char arr[]={"hello"} 这为什么就能解释为初始化数组,不也可以说初始化了数组的元素,第一个元素初始化为'h'…

344

主题

255

回帖

2666

积分

管理员

积分
2666
发表于 2023-12-27 22:29:38 | 显示全部楼层
xiaocai 发表于 2023-12-27 22:18
初始化数组元素?初始化数组?有点不好理解,脑子不够了,感觉都是在初始化数组啊。初始化了数组,不也是 ...

这确实不太好理解。
它所说的“初始化一个数组”不能理解为“是数组的初始化器”,否则不单单是
const char * arr [] = "hello";
符合它的说法,就连
int arr [] = "hello";
都符合它的说法。
所以你只能理解为“初始化一个元素类型为char、wchar_t、char16_t或者char32_t的数组”。

344

主题

255

回帖

2666

积分

管理员

积分
2666
发表于 2023-12-27 22:33:45 | 显示全部楼层
你想得比较细,我从来没想过这种情形。
标准也不是没有一点问题,我倾向于认为标准的措辞不够清晰。但也许是语言的问题。在英语里,“作为数组的初始化器”和“初始化数组”应该是有差别的。

4

主题

12

回帖

105

积分

注册会员

积分
105
 楼主| 发表于 2023-12-28 00:59:59 | 显示全部楼层
本帖最后由 xiaocai 于 2023-12-29 11:58 编辑
站长 发表于 2023-12-27 22:33
你想得比较细,我从来没想过这种情形。
标准也不是没有一点问题,我倾向于认为标准的措辞不够清晰。但也许 ...

向你学习,你严谨的态度,令人敬佩。所以有时候看到一些代码,我也尝试去想对应哪些语言规范,但是因为小白,有时候就想偏了。
本来需要写成 char arr[]={'a','b','c','\0'} 这样,但是为了方便弄个语法糖,直接可以写成 char arr[]={"abc"} 或者char arr[]="abc",所以所谓的字面串初始化数组就特指这种语法糖形式的初始化字符 数组类型


0

主题

3

回帖

82

积分

至尊会员

积分
82

至尊会员

发表于 2024-1-4 09:29:18 | 显示全部楼层
本帖最后由 zhaokg 于 2024-1-4 09:48 编辑

很好的讨论。 这里是C语言标准说的 (https://en.cppreference.com/w/c/language/array_initialization):

String literal (optionally enclosed in braces) may be used as the initializer for an array of matching type

据此,  
(1) const char arr[]= "abc";
(2) const char arr[]= {"abc"};
这2者是一样的, the braces 可有可无。 像你说的一样,就是一种syntactic sugar,等同于
const char arr[]= {'a','b', 'c', '\0'};

但是const char * arr[]={"abc"}完全不一样, 这里不涉及到字符数组的初始化, 因为arr是一个数组,每个元素不是char,而是一个指针。 而在C语言中(除了上面(1) and (2)二中情况), a string literal (e.g., “abc",存在与程序的read-only constant段)可以认为是一个const char *类型  (比如printf(”%s", pchar) 和 printf(“%s", "abc")中)。

在const char * arr[]={"abc"}总,  arr是一个只有1个元素的数组,它的第一个元素内容是一个指向“abc"的指针。

可以理解为这样:
const char * pchar ="abc";
const char * arr[] ={pchar};

另外一个例子

const char arr[]={"abc","xyz"}; 这就错了, 因为这个不能转化为 const char arr[]="abc""xyz", 所以试图把2个指针(总共8+8 bytes)赋给二个字符(1+1 bytes), 肯定会出错, 为了理解, 它类似于  const void  * arr[]={"abc",  "xyz"};


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|鼠侠网 ( 吉ICP备19001332号 )

GMT+8, 2024-7-27 12:31 , Processed in 0.224870 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表