警告:当将数组分配给 int 指针时,从 'int' 初始化 'int *' 使指针从整数中转换,而不进行强制转换

warning: initialization of 'int *' from ' int' makes pointer from integer without a cast, when assigning array to a int pointer

提问人:tycoon 提问时间:3/13/2022 最后编辑:Vlad from Moscowtycoon 更新时间:3/13/2022 访问量:1574

问:

我正在研究指针,这就是我学到的:-

int a = 23;
int *ptr = &a;

char b = 'b';
char *pnt = &b;

char *str = "string";

分配给指针的值是一个地址。所以我不能做或.但是我可以这样做,因为“字符串”不是字符,而是一些字符值的数组,因为字符和指针彼此非常相似,所以在上面的代码中,如果我打印应该打印保存在 str 中的地址,这应该是字符串起始地址的地址(这是我想知道我是对还是错的第一部分)int *ptr = 7;char *k = 'c';char *str = "string";printf("%p", str);

因此,以另一种方式,我只是创建了一个字符数组,例如.(也许这听起来很愚蠢,但事实就是如此)所以我想为什么不尝试一下,我认为这将再次给出字符串的起始地址,但在获得一些奇怪的值并运行返回的“s”后,我发现它给出的是数组的第一个元素而不是地址。我尝试了与int array相同的方法,并注意到一个警告说char *str = "string";{'s','t','r','i','n','g'}char *str = {'s','t','r','i','n','g'};printf("%p\n", str)printf("%c", str)

int *array = {1,2,3};

警告:从“int”初始化“int *”使指针从整数中转换,而不进行强制转换

根据我对此的理解,编译器将 {1,2,3} 视为 int 而不是数组,我不确定为什么,但如果我显式转换它运行良好,就像 .我不确定为什么我需要明确地告诉,但我认为这就是编译器的看法int *array = (int[]){1,2,3}

  • 执行后,编译器得到一个地址 {1,2,3}。int *array = {1,2,3};
  • 但是当编译器看到该地址有一个 int 时,它只读取该 int
  • 编译器认为它不是int *array = 1int *array = {1,2,3}

我不知道我的理论是否正确。如果没有,我想知道为什么会发生这种情况,以及为什么这样做不需要任何演员。char *str = "string"

数组 C 指针 初始化 复合文字

评论

2赞 Raildex 3/13/2022
{1,2,3}不是数组。 是。int foo[3] = {1,2,3}
0赞 tycoon 3/13/2022
@Raildex我现在觉得自己很愚蠢。
1赞 tycoon 3/13/2022
因此,通过这样做,我不是在强制转换,我只是在声明一个新数组(int[]) {1,2,3}
3赞 Some programmer dude 3/13/2022
是的,是复合文字(int[]) {1,2,3}

答:

2赞 Vlad from Moscow 3/13/2022 #1

在 C 语言中,字符串文字具有字符数组类型。例如,字符串文字作为以下类型的数组存储在内存中:"string"char[7]

{ 's', 't', 'r', 'i', 'n', 'g', '\0' }

您可以使用以下调用来检查这一点

printf( "sizeof( \"string\" ) = %zu\n", sizeof( "string" ) );

在具有极少数例外的表达式中使用的数组将隐式转换为指向其第一个元素的指针。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

3 除非它是 sizeof 运算符的操作数或一元 & 运算符,或者是用于初始化数组的字符串文字,一个 类型为 ''array of type'' 的表达式将转换为 类型为“指向类型”的表达式,指向初始 元素,并且不是左值。如果数组对象 具有寄存器存储类,行为未定义

所以在这个宣言中

char *str = "string";

与编译器存储的字符串文字相对应的数组(通常在字符串文字池中)被转换为指向其第一个元素的指针,并将指针的值分配给标量对象。str

str不是数组。 是一个指针。str

上述声明也可以通过以下方式重写

char *str = &"string"[0];

本声明

char *str = {'s','t','r','i','n','g'};

不正确。标量对象可以由仅包含一个赋值表达式的支撑列表初始化。

从 C 标准(6.7.9 初始化)

11 标量的初始值设定项应为单个表达式, 可选择用大括号封闭。对象的初始值为 表达式(转换后);相同的类型约束和 转换与简单赋值一样适用,采用 标量是其声明类型的非限定版本。

你可以写例如

char *str = { ( 's','t','r','i','n','g' )};

在本例中,大括号内有一个带有逗号运算符的主表达式。实际上,这个声明等价于

char *str = { 'g' };

编译器将发出一条消息,提示您正在尝试使用整数初始化指针。

在本声明中

int *array = (int[]){1,2,3};

没有铸造。该构造表示该类型的复合文字,并且再次将该数组的第一个元素的地址分配给指针。(int[]){1,2,3}int[3]array

您可以这样想象上述声明

int compound_literal[] = { 1, 2, 3 };
int *array = compound_literal;