将简单值存储在 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]
的对象(即指向类型为 short
的 dim
元素的数组)。
数组不是指针(尽管在某些情况下数组通常 decay 指向指针)。
修复此问题后,您的编译器现在会在以下行中给您一个错误:
pg[j] = tab;
这是因为不能直接给数组赋值。但是,您可以
- 在循环中一次将一个元素从一个数组复制到另一个数组,直到复制整个数组,或者
- 将一个数组的内存内容复制到另一个数组,使用
memcpy
。
我有一个简单的程序,它一次 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]
的对象(即指向类型为 short
的 dim
元素的数组)。
数组不是指针(尽管在某些情况下数组通常 decay 指向指针)。
修复此问题后,您的编译器现在会在以下行中给您一个错误:
pg[j] = tab;
这是因为不能直接给数组赋值。但是,您可以
- 在循环中一次将一个元素从一个数组复制到另一个数组,直到复制整个数组,或者
- 将一个数组的内存内容复制到另一个数组,使用
memcpy
。