gpt4 book ai didi

C:在另一个函数中初始化动态类型的二维矩阵

转载 作者:太空宇宙 更新时间:2023-11-03 23:40:53 26 4
gpt4 key购买 nike

我正在尝试创建 3 个动态类型的矩阵(int、float、double)以用于矩阵乘法。我已经为主矩阵中的每个矩阵创建了一个 void**“类型化”容器,然后将它们(作为 void***)传递到一个 init 函数中,以便根据用户对类型的选择进行 malloc。下面的代码可以编译,但是在 j 循环的一次迭代后我遇到了段错误,我终究无法弄清楚为什么会发生这种情况。类似地,如果我要在一个单独的 2 层深度循环中进行初始化(从 malloc 循环中取出 j 循环),那么在 i 循环的一次迭代之后仍然会发生段错误。

这甚至是实现我的动态类型矩阵乘法目标的好方法吗?非常感谢您的帮助。

void initMat(int type, int matSize, void ***matA, void ***matB, void ***matC)
{
int i, j, k;

switch(type) {
case 0 :
*matA = malloc(matSize * sizeof(int*));
*matB = malloc(matSize * sizeof(int*));
*matC = malloc(matSize * sizeof(int*));
for (i = 0; i < matSize; i++) {
*matA[i] = malloc(matSize * sizeof(int));
*matB[i] = malloc(matSize * sizeof(int));
*matC[i] = malloc(matSize * sizeof(int));
for (j = 0; j < matSize; j++) {
*(int*)matA[i][j] = rand()/RAND_MAX * 10;
*(int*)matB[i][j] = rand()/RAND_MAX * 10;
*(int*)matC[i][j] = 0;
}
}
break;

case 1 :
// with float, double, etc.
break;

default :
printf("Invalid case.\n" );
}
}

int main()
{
int type = 0;
int size = 0;
void **matA, **matB, **matC;

int sizes[6] = {3, 4, 5};
int matSize = sizes[size];
printf("The selected matrix size is: %d. \n", matSize); //allows user to select matrix size

initMat(type, matSize, &matA, &matB, &matC);

// displayMat(matSize, matA);

}

最佳答案

要使用动态分配的二维数组,应使用正确的指针类型。 (int **) 是一个指向指针的指针,指向指针数组的第一个元素,这些指针本身指向不同的分配。这种代码的结果是一个锯齿状的数组,而不是一个二维数组。分配的内存不保证是连续的(因为数组分配必须是连续的):

size_t num_rows = 3;
size_t num_cols = 5;

int **jagged_arr = malloc(sizeof *jagged_arr * num_rows);

for (size_t i = 0; i < num_rows; i++) {
jagged_arr[i] = malloc(sizeof *jagged_arr[i] * num_cols);
}

一种可能性是简单地为一维数组分配存储空间,并根据二维数组索引计算该数组的偏移量。这工作正常,但结果不是二维数组:

size_t num_elems = num_rows * num_cols;
int *simulated_2d_arr = malloc(sizeof *simulated_2d_arr * num_elems);

这不能作为二维数组索引,但可以根据列数和二维数组索引计算一维索引:

for (size_t i = 0; i < num_rows; i++) {
for (size_t j = 0; j < num_cols; j++) {
simulated_2d_arr[i * num_cols + j] = i * num_cols + j;
}
}

这两种方法都有其用途,但它们都有一个缺点,即生成的数组无法传递给旨在使用二维数组的函数。也就是说,考虑一个打印二维数组的函数,例如:

void print_2d_arr(size_t rows, size_t cols, int arr[][cols])
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
printf("%5d", arr[i][j]);
}
putchar('\n');
}
}

这个函数适用于类似的东西:

int real_2d_arr[2][3] = { { 1, 2, 3 },
{ 4, 5, 6 } };

但它不适用于较早的jagged_arr:

expected ‘int (*)[(sizetype)(cols)]’ but argument is of type ‘int **’

或对于 simulated_2d_arr:

expected ‘int (*)[(sizetype)(cols)]’ but argument is of type ‘int *’

在上面的错误消息中可以看到动态分配二维数组时要使用的正确类型。对于 int 的二维数组,这将是 int (*)[]。这是二维数组在大多数表达式(包括函数调用)中衰减的类型。因此,要动态分配 int 的二维数组,这会起作用:

size_t num_rows = 3;
size_t num_cols = 5;
int (*array_2d)[num_cols] = malloc(sizeof *array_2d * num_rows);

这为num_cols intnum_rows 数组分配了空间。请注意,这不会创建 VLA,但会使用 VLA type。当然,VLA 早在 C99 中就引入了,但在 C11 中成为可选的(尽管仍得到广泛支持)。

至于你问题的动态类型部分,一个选择是创建一个 enum 来保存类型标识符,并将这些枚举常量之一传递给任何需要它们的函数。这些函数将需要接受 (void *) 参数,这些参数将根据类型枚举常量进行适当转换。这有点复杂,但这是一个示例程序。请注意,print_array() 函数适用于动态分配的数组和静态大小的数组。另请注意,不需要三重甚至双重间接寻址!

#include <stdio.h>
#include <stdlib.h>

enum Type { CHAR,
INT,
FLOAT,
DOUBLE };

void * get_array(enum Type type, size_t rows, size_t cols);
void init_array(enum Type type, size_t rows, size_t cols, void *arr);
void print_array(enum Type type, size_t rows, size_t cols, void *arr);

int main(void)
{
char (*arr_char)[5] = get_array(CHAR, 4, 5);
int (*arr_int)[5] = get_array(INT, 4, 5);
double (*arr_double)[5] = get_array(DOUBLE, 4, 5);

int arr_static[][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };

if (arr_char) { // check for null pointer
init_array(CHAR, 4, 5, arr_char);
puts("4x5 array of char");
print_array(CHAR, 4, 5, arr_char);
putchar('\n');
}

if (arr_int) { // check for null pointer
init_array(INT, 4, 5, arr_int);
puts("4x5 array of int");
print_array(INT, 4, 5, arr_int);
putchar('\n');
}

if (arr_double) { // check for null pointer
init_array(DOUBLE, 4, 5, arr_double);
puts("4x5 array of double");
print_array(DOUBLE, 4, 5, arr_double);
putchar('\n');
}

puts("Statically sized 3x3 array of int");
print_array(INT, 3, 3, arr_static);
putchar('\n');

/* Cleanup */
free(arr_char);
free(arr_int);
free(arr_double);

return 0;
}

/* Returns null pointer on allocation failure */
void *get_array(enum Type type, size_t rows, size_t cols)
{
size_t array_sz = 0;
void *ret = NULL;

switch (type) {
case CHAR:
array_sz = sizeof (char) * rows * cols;
break;
case INT:
array_sz = sizeof (int) * rows * cols;
break;
case FLOAT:
array_sz = sizeof (float) * rows * cols;
break;
case DOUBLE:
array_sz = sizeof (double) * rows * cols;
break;
default:
fprintf(stderr, "Unrecognized type in get_array()");
}

if (array_sz) {
ret = malloc(array_sz);
}

return ret;
}

void init_array(enum Type type, size_t rows, size_t cols, void *arr)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
int offset = i * cols + j;
switch (type) {
case CHAR:
{
char (*array_char)[cols] = arr;
array_char[i][j] = 'a' + offset;
break;
}
case INT:
{
int (*array_int)[cols] = arr;
array_int[i][j] = 0 + offset;
break;
}
case FLOAT:
{
float (*array_float)[cols] = arr;
array_float[i][j] = 0.0 + offset;
break;
}
case DOUBLE:
{
double (*array_double)[cols] = arr;
array_double[i][j] = 0.0 + offset;
break;
}
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
}
}
}

void print_array(enum Type type, size_t rows, size_t cols, void *arr)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
switch (type) {
case CHAR:
{
char (*array_char)[cols] = arr;
printf("%3c", array_char[i][j]);
break;
}
case INT:
{
int (*array_int)[cols] = arr;
printf("%5d", array_int[i][j]);
break;
}
case FLOAT:
{
float (*array_float)[cols] = arr;
printf("%8.2f", array_float[i][j]);
break;
}
case DOUBLE:
{
double (*array_double)[cols] = arr;
printf("%8.2f", array_double[i][j]);
break;
}
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
}
putchar('\n');
}
}

程序输出:

4x5 array of char
a b c d e
f g h i j
k l m n o
p q r s t

4x5 array of int
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19

4x5 array of double
0.00 1.00 2.00 3.00 4.00
5.00 6.00 7.00 8.00 9.00
10.00 11.00 12.00 13.00 14.00
15.00 16.00 17.00 18.00 19.00

Statically sized 3x3 array of int
1 2 3
4 5 6
7 8 9

关于C:在另一个函数中初始化动态类型的二维矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46355693/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com