【问题标题】:C treating array as pointerC将数组视为指针
【发布时间】:2020-11-04 21:37:59
【问题描述】:

在C中我了解到数组的名称是指向第一个索引的指针,但是为什么我不能写如下:

int mat[5][4];
*mat=1;

【问题讨论】:

标签: arrays c pointers implicit-conversion dereference


【解决方案1】:

在 C 中我了解到数组的名称是指向第一个索引的指针

事实并非如此。

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

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

此声明

int mat[5][4];

声明一个二维数组。因此,表达式中使用的数组指示符(除了引号中列出的极少数例外)被隐式转换为指向其第一个元素的指针,即指向 int ( * )[4] 类型的指针。

像在这个语句中那样取消引用指针

*mat=1;

您将获得int[4] 类型的数组左值。因此,您试图用标量整数值 1 分配一维数组。但数组没有赋值运算符。它们是不可修改的左值。

相反,你可以写例如

**mat = 1;

在这种情况下,表达式**mat 产生int 类型的标量左值(数组m 的第一个“行”/元素的int 类型的第一个标量元素)。

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    int mat[5][4];
    **mat = 1;
    
    printf( "**mat is equal to %d and equivalent to mat[0][0] that is also equal to %d\n",
            **mat, mat[0][0] );
}           

它的输出是

**mat is equal to 1 and equivalent to mat[0][0] that is also equal to 1

实际上所有这些表达式都在 printf 调用中使用

printf( "%d\n", **mat );            
printf( "%d\n", ( *mat )[0] );
printf( "%d\n", *mat[0] );          
printf( "%d\n", mat[0][0] );

产生相同的数组元素。

【讨论】:

    【解决方案2】:

    二维数组本质上是一维数组的一维数组。 *mat 等效于 mat[0] 并为您提供数组的第一个元素,它本身就是一个一维数组 (int[4])。

    您不能将数字分配给数组。


    数组名是指向第一个索引的指针

    我经常看到这种解释,但是“数组”和“数组名称”之间的区别是没有意义的。

    更好的解释是数组可以自动转换为其第一个元素的指针。

    【讨论】:

    • 为了清楚起见,c中的矩阵是数组数组还是一块内存(就像一行)?
    • @BigSur 这里没有矛盾。它们是数组的数组,子数组在内存中是连续的。
    • @HolyBlackCat 我明白我的回答可能会被误解。我已经把它删了。接受我的投票。
    【解决方案3】:

    您可以使用数组名称作为指向数组第一个元素的指针(即使有更优雅的解决方案)。

    在您的情况下,数组的第一个元素是另一个数组,因此 *mat 的类型为 int[4](具有 4 个元素的 int 数组),您不能将 1(整数)分配给它。

    如果要设置二维数组的第一个整数,可以使用

    **mat = 1;
    

    但我强烈建议使用显式索引,例如

    mat[0][0] = 1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2012-09-22
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多