警告:在将数组分配给 int 指针时,从“int”初始化 'int *' 会在不强制转换的情况下从整数生成指针

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

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

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

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

char *str = "string";

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

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

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

warning: initialization of 'int *' from ' int' makes pointer from integer without a cast

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

不知道我的理论对不对。如果不是,我想知道为什么会这样,为什么 char *str = "string" 不需要任何转换。

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

{ 's', 't', 'r', 'i', 'n', 'g', '[=10=]' }

您可以使用以下调用进行检查

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

在极少数情况下,表达式中使用的数组会隐式转换为指向其第一个元素的指针。

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

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined

所以在这个声明中

char *str = "string";

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

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

上面的声明也可以改写成下面的方式

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

这个声明

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

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

来自C标准(6.7.9初始化)

11 The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type.

你可以这样写

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;