将简单值存储在 C 中的矩阵中

Store simple value in a matrix in C

我有一个简单的程序,它一次 scanf 一个值,然后将它存储在一行 (p) 中,然后将它存储在一个矩阵 (pg) 中。

//
// Created by herveDarritchon on 15/01/2022.
//

#include <stdio.h>

int main() {
    int dim = 0;
    printf("dim ?\n");
    scanf("%d", &dim);
    short tab[dim];
    short *p;
    short **pg;
    p = &tab[0];
    short tab_double[dim][dim];
    pg = (short **) &tab_double[0];

    for (int j = 0; j < dim; j++) {
        for (int i = 0; i < dim; i++) {
            printf("value: ");
            scanf("%d", &p[i]);
            printf("value stored : %d\n", p[i]);
        }

        printf("value in tab: ");

        for (int l = 0; l < dim; l++) {
            printf("%d|", tab[l]);
        }

        printf("\n");
        pg[j] = tab;
        printf("value ub pg[%d]: ", j);

        for (int l = 0; l < dim; l++) {
            printf("%d|", pg[j][l]);
        }

        printf("\n");
    }

    for (int k = 0; k < dim; k++) {
        printf("value ub pg[%d]: ", k);

        for (int l = 0; l < dim; l++) {
            printf("%d|", pg[k][l]);
        }

        printf("\n");
    }
}

结果是

dim ?
2
value: 1
value stored : 1
value: 2        
value stored : 2    
value in tab: 1|2|  
value ub pg[0]: 1|2|
value: 3
value stored : 3
value: 4
value stored : 4
value in tab: 3|4|
value ub pg[1]: 3|4|
value ub pg[0]: 3|4|
value ub pg[1]: 3|4|

但最后,矩阵 (pg) 仅存储其所有索引中的最后一行 :(

我想我对指针做错了......但我不明白为什么矩阵只有最后一行。

您混淆了数组和指针,并且似乎认为它们在某种程度上是相同的。事实并非如此。

查看内存布局:

short arr[dim][dim];

在记忆中这看起来像这样(假设 dim==3):

 +---------+---------+---------+---------+---------+---------+---------+---------+---------+
 |    +0   |    +2   |    +4   |    +6   |    +8   |    +A   |    +C   |    +E   |   +10   |
 +---------+---------+---------+---------+---------+---------+---------+---------+---------+
 |arr[0][0]|arr[0][1]|arr[0][2]|arr[1][0]|arr[1][1]|arr[1][2]|arr[2][0]|arr[2][1]|arr[2][2]|
 +---------+---------+---------+---------+---------+---------+---------+---------+---------+
  

这与您的 short tab_double[dim][dim];

相似

另一边看这个:

short **pg;

在内存中看起来像这样(假设 32 位地址):

 +----------+----------+----------+
 |    +0    |    +4    |    +8    |
 +----------+----------+----------+
 |   pg[0]  |   pg[1]  |   pg[2]  |
 +----------+----------+----------+

而且还取决于p[x][0]所在的p[x]的内容。

如你所见,short **pg的内存布局与short tab_double[dim][dim]

有很大不同

通过该赋值 pg = (short **) &tab_double[0];,您告诉编译器将保存数组前几个元素的内存视为指针数组。这会导致内存损坏。

pg = &tab_double[0];

给你一个编译器警告。您似乎通过添加类型转换来抑制此警告:

pg = (short **) &tab_double[0];

但是,像那样抑制编译器警告并不是一个好主意。编译器指出出了点问题。

随行

short tab_double[dim][dim];

您正在声明一个二维 (2D) 数组。

二维数组只不过是数组的数组。内部数组是 short[dim] 类型(dim 元素的数组,其中每个元素都是 short 类型),外部数组是 short[dim][dim] 类型(dim 个元素,其中每个元素的类型为 short[dim]).

如果您希望 pg 指向外部数组的第一个元素,那么您应该使其类型反映这一点。您希望它指向 short[dim] 类型的元素。因此,指针的类型应该是 short (*)[dim](括号是必需的,否则类型将是指向类型 short 的对象的指针数组)。所以你应该像这样声明指针:

short (*pg)[dim];

但是,您是这样声明指针的:

short **pg;

这告诉编译器 pg 将指向指向 short 的指针。但是,此信息不正确。如上所述,您希望它指向类型为 short[dim] 的对象(即指向类型为 shortdim 元素的数组)。

数组不是指针(尽管在某些情况下数组通常 decay 指向指针)。

修复此问题后,您的编译器现在会在以下行中给您一个错误:

pg[j] = tab;

这是因为不能直接给数组赋值。但是,您可以

  • 在循环中一次将一个元素从一个数组复制到另一个数组,直到复制整个数组,或者
  • 将一个数组的内存内容复制到另一个数组,使用memcpy