【问题标题】:Is the following a 2D array?以下是二维数组吗?
【发布时间】:2018-09-27 20:47:22
【问题描述】:

我想使用指针动态分配二维数组。

int *arr = (int *)malloc(rows * cols * sizeof(int));

这可行,但这个单指针数组在技术上是二维数组吗?

谢谢!

【问题讨论】:

  • 如果大小正确,任何数组都可以是 n 维的。如果您不介意语法,则 16 个整数的数组在技术上可以视为 4x4 二维数组
  • 从技术上讲,C 没有二维数组,所以这一点没有实际意义。

标签: c arrays pointers malloc


【解决方案1】:

从技术上讲,它只是一个一维数组。但它可以用作二维数组,通过基于行优先排序计算索引:

int index = row * cols + col;
int val = arr[index];

当你声明一个二维数组时,这就是幕后发生的事情:

int arr[rows][cols]
int val = arr[row][col];

【讨论】:

    【解决方案2】:

    下面是二维数组吗?

    int *arr = (int *)malloc(rows * cols * sizeof(int));
    

    没有。 arr 是一个指针。该指针使用适合存储二维数组的内存地址进行初始化。


    我想使用指针动态分配二维数组。

    这取决于“2D”的种类

    “2D 数组”的概念经常被松散地使用。让我们探索一些可能的解释。

    要分配指向二维数组的指针,请使用以下命令。如果rows,cols 是常量或者代码是C99,或者带有可变长度数组的C11:

    int (*arr_true)[rows][cols] = malloc(sizeof *arr_true);
    (*arr_true)[0][0] = this;
    (*arr_true)[0][1] = that;
    // etc.
    

    为具有cols 宽度的二维数组分配内存。如果cols 是常量或者代码是C99,或者带有可变长度数组的C11:

    int *arr_mem[cols] = malloc(sizeof *arr_mem * rows);
    arr_mem[0][0] = this;
    arr_mem[0][1] = that;
    // etc.
    

    为具有row*cols 元素的数组分配内存。

    int *arr_flat = malloc(sizeof *arr_flat *rows * cols);
    arr_flat[0 *cols + 0] = this;
    arr_flat[0 *cols + 1] = that;
    // etc.
    

    分配一个指向int的指针数组

    int *arr_classic = malloc(sizeof *arr_classic *rows);
    for (size_t r = 0; r<rows; r++) {
      arr_classic[r] = malloc(sizeof *arr_classic[r] *cols);
    }
    arr_classic[0][0] = this;
    arr_classic[0][1] = this;
    // etc.
    

    尺寸计算的改进思路。

    考虑用于计算大小的数学。如果rows,colsintrows * cols 可能会溢出int 范围,导致未定义的行为。使用size_t 完成的相同计算可能不会在数学上溢出,应该是首选。

    最后,malloc(size_t sz) 期望 size_t

    int *arrA = malloc(rows * cols * sizeof(int)); // possible int*int overflow
    int *arrB = malloc(sizeof(int) * rows * cols); // preferred
    

    【讨论】:

      【解决方案3】:
      int *arr = (int *)malloc(rows * cols * sizeof(int));
      

      arr 是指向分配有rows * cols * sizeof(int) 字节的内存位置的指针。
      您将内存位置解释为何种语言并不重要,这取决于您。一维数组、二维数组、字符串等。在 C 语义中,它可能是一维数组,但这仍然不是全部事实,因为您可以根据自己的需要来解释和管理内存。

      【讨论】:

        【解决方案4】:

        不,指针从不数组。请参阅comp.lang.c FAQ 的第 6 节。

        您可以使用此技术分配一块内存,然后您可以将其视为二维数组,指针arr 指向其初始元素。一个更简单更好的写法是:

        int *arr = malloc(rows * cols * sizeof (*arr));
        

        这会分配一个由rows*cols int 元素组成的一维数组。你不能使用arr[i][j] 符号来索引它;您需要自己计算索引:arr[i * rows + j]

        如果你想分配一个动态二维数组(或者,更准确地说,一个行为类似的数据结构),你需要创建一个int**指针数组,并初始化每个元素指向一个新分配的int 元素数组。 (然后您需要在完成后将其全部清理干净。)例如:

        #include <stdio.h>
        #include <stdlib.h>
        
        int main(void) {
            int cols = 20;
            int rows = 10;
        
            // Allocate memory for an array of pointers to rows
            int **arr_2d = malloc(rows * sizeof *arr_2d);
            if (arr_2d == NULL) {
                abort(); // horribly crude error handling
            }
        
            // Allocate memory for each row
            for (int row = 0; row < rows; row ++) {
                int *arr_1d = malloc(cols * sizeof *arr_1d);
                if (arr_1d == NULL) {
                    abort(); // horribly crude error handling
                }
                arr_2d[row] = arr_1d;
            }
        
            // Assign data 
            for (int row = 0; row < rows; row ++) {
                for (int col = 0; col < cols; col ++) {
                    arr_2d[row][col] = row*col;
                }
            }
        
            // Dump data
            for (int row = 0; row < rows; row ++) {
                printf("Row %2d:", row);
                for (int col = 0; col < cols; col ++) {
                    printf(" %3d", arr_2d[row][col]);
                }
                putchar('\n');
            }
        
            // Deallocate each row
            for (int row = 0; row < rows; row ++) {
                free(arr_2d[row]);
            }
        
            // Deallocate the array of row pointers
            free(arr_2d);
        }
        

        【讨论】:

        • 猜 DV 不想发表评论,所以我会给你 +1 以平衡事情。因为我在这个答案中没有看到任何错误。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-22
        • 2011-11-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多