如何在函数内初始化可变长度矩阵,然后 return 在不使用 C 中的 malloc 或 calloc 的情况下初始化相同的矩阵

How to initialize a variable length matrix inside a function and then return the same matrix without the use of malloc or calloc in C

我想问的问题是如何不仅在函数内初始化可变长度矩阵,而且如何从同一个函数 return 它。

我找到了可行的解决方案,但它们并不是我想要的。

为了更直观地展示我所要求的是展示我的解决方案或解决问题的尝试。

我的第一个想法是,如果我创建一个指针数组会怎样

#include <stdio.h>


int main(){
  int value = 12;
  int value1 = 32;
  int *mat[2] = 
  {
    &value,
    &value1
  };
  printf("%d",mat[0][1]);
}

这可行,但非常有限,显然甚至不是矩阵;因为里面的指针只是指向一个值而不是它们是一个数组,它更像是一个值数组,只是有额外的步骤

所以我想如果我做类似的事情但通过使每个索引本身成为数组来解决数组问题会怎么样。

#include <stdio.h>

int **mfoo(int x, int y){
  int **matrix;
    int *arry[y];
    int arry1[x];
      for(int i=y;i<y;i++){
        
        arry[i] = arry1;
      }
  matrix = arry;
return matrix;
}
int main(){
  int **mat = mfoo(5,5);
  mat[0][3] = 5;
  printf("%d",mat[0][3]);
  return 0;
}

这显然行不通,因为 arry[x] 的第一个索引的地址被分配给矩阵中的每个索引,因此矩阵的每个索引都是完全相同的数组。

正如预测的那样,它适用于 mat 的第一个索引,如 mat[0][3] 但是如果我尝试索引 mat 的第二个索引 mat[1][3],它将结束分段错误,这对我来说似乎很奇怪,因为它应该只引用同一个数组,因为 mat[0] 和 mat[1] 应该是相同的地址,因为它们都指向 &arry1[0]?

我的下一个想法是我唯一开始工作的想法,现在我将在我将字符串解析为参数的函数中展示它

char * pipe_arguments(char *str, int j){
  int _j=0; 
  int _i=0;
  char *argument_ptr;
  char arr[20][200];
  for(int i=0; i<j; i++){
    if(str[i] > 32 && str[i] < 127){
      arr[_i][_j] = str[i];
      _j++;
    }
    else if(str[i] == 32){
      _i++;
    }
  }
argument_ptr = arr[0];
//"echo -o A_String" -- should see three parameters 
return argument_ptr;
}

int main(){
  char str[] = "echo -f filename.txt -o stdout";
  char *ptr;
  ptr = pipe_arguments(str, sizeof(str));
  for(int j=0;j<20;j++){
    for(int i=0;i<200;i++){  
      printf("%c",*ptr++);
    }
  printf("\n");
  }
}

这完全可以正常工作,除了一些非常随机的字符外,几乎可以打印出我想要的内容

此函数的输出示例为

echo
-f
filename.txt
-o
stdout�y�~���
�Pk�y�~p`j`jp>�>`�>�
?p
p�y�~�y�~`�p`�
A�y�~�p�y�~/�j�Unnert/usr/li���y�~�y�~��Gļy�~��h�y�~�J�y�~Z�~y�~=�y�~�
��F7@�y�~p�y�~�j�U�P�F7�P��qZ�_qZ�_%�aD��
�j�Up�y�~`�y�~��y�~�
p�y�~ ���p�y�~�
@�h�y�~�y�~�y�~�y�~@8
@IH�V�y�~�
s~y�~�}y�~8S�y�~�~��h�y�~��y�~�y�~�y�~�y�~
�V�y�~��t~y�~x}y�~8S�y�~�~�~��~��y�~�y�~�ﵽ��y�~(�@�y�~�y�~��y�~@�y�~
�y�~�t~y�~���y�~���SP�y�~�U�y�~�y�~(U�y�~`�jɽy�~��y�~0�y�~
�j�U�SP�y�~|�c;̸U�y�~�jɽy�~�y�~`�y�~0N�y�~��~}y�~��y�~�h�y�~�p�y�~���
////////////////�����usr/lib/i386-lin��y�~��y�~@�y�~@�y�~}~�0�y�~0�y�~
� �y�~ �y�~
��T�y�~�y���y�~��y�~�Ѣ�y�~@�y�~P�y�~Y�y�~�y�~H�y�~0@j�Up
�Z�y�~�'P�#�y�~@�y�~�y�~�@p�y%2@j�U0�A@
|wn]@�y�~��j�U��y�~ �?8�y�~�"�y�~b`�!�
�`2@j�U!�y�~`�y�~`�y�~�f-`�y�~h
�j�U���y�~`�y�~�

您可以看到它解析字符串并将每个字符串放入其中一个索引中,但紧接着开始吐出随机的乱码。

这与手头的问题无关,但如果能回答为什么它也这样做,我们将不胜感激?

无论如何,此解决方案使用线性指针并使用指针算法对数组进行索引。

感觉还是有什么问题没有解决,不是我想要的,我觉得应该有一个不使用malloc或calloc的解决方案。我不是说自己制作这些函数然后使用它们我的意思是感觉有一种方法可以得到双指针,例如使用 mat[4][10] 索引矩阵。

你不能这样做(参见 https://en.cppreference.com/w/c/language/scope):

char* func()
{
    char arr[1][2]; //local scope
    return &arr[0]; //error, the array will no longer exist (out of scope)
}

如果您不想在函数内分配内存,那么您必须提供另一个存储作为参数,例如:

char** func(char **matrix, size_t rows, size_t cols /* ,other args */)
{
    /* do something */
    return matrix;
}

int main()
{
    char matrix[20][200];
    func(matrix, 20, 200);
    return 0;
}

还有另一种可能的解决方案,但只适用于较小的数据类型(以避免不必要的复制和堆栈使用),例如:

struct matrix {
    char data[2][2];
};

struct matrix func(char a, char b, char c, char d)
{
    struct matrix m = { .data = {{a, b}, {c, d}} }; //initialize matrix
    return m; //return on stack
}

int main()
{
    struct matrix m = func('a', 'b', 'c', 'd');
    printf(
        "%c %c %c %c\n", 
        m.data[0][0], 
        m.data[0][1], 
        m.data[1][0], 
        m.data[1][1]
    );
    
    return 0;
}

只要数据类型 (struct) 是完整的(因此它的大小在编译时已知),return 这样的 struct 从一个函数应该没有问题(我不知道这种 struct 的最大大小限制)。