未指定子数组的数量时如何在C中创建数组数组? [复制]

Posted

技术标签:

【中文标题】未指定子数组的数量时如何在C中创建数组数组? [复制]【英文标题】:How to create an array of arrays in C when the number of subarrays is not specified? [duplicate] 【发布时间】:2021-04-01 07:46:30 【问题描述】:

我正在尝试创建一个数组数组,但子数组的数量未知。

【问题讨论】:

数组使用malloc,可以使用realloc放大。对于整数,例如声明为int **myArrays; 您通常可以使用malloc 创建这样的“锯齿状”数组。但您的问题中的更多细节和清晰度将有助于获得具体答案。 所有子数组的长度都一样吗?如果是这样,数组可以很容易地定义为单个可变长度数组,或分配为单个动态分配的块(使用malloccalloc),而不是作为指向不同长度子数组的第一个元素的指针数组(这将是“锯齿状”)。 @DevUt 注意 newdelete 是 C++ 运算符,而 OP 询问 C 这个问题有点简约。这让我倾向于回答:“你不知道的,你不需要。” 【参考方案1】:

锯齿状数组是数组的数组,因此成员数组可以具有不同的大小,即我们可以创建一个二维数组,但每行的列数是可变的。

静态锯齿阵列

int kk0[4] =  1, 2, 3, 4 ;  
int kk1[2] =  5, 6 ; 
int* jagged[2] =  kk0, kk1 ; 

动态锯齿阵列

 int* jagged[2]; 
 jagged[0] = malloc(sizeof(int) * 1); 
 jagged[1] = malloc(sizeof(int) * 3); 

参考:https://en.wikipedia.org/wiki/Jagged_array

【讨论】:

更好的说法:“[A] 锯齿状数组可以像数组数组一样被访问...”,因为它明确不是数组的数组,但是……嗯……“锯齿状”数组。 好,第一次听说Jagged,但唯一的问题是无法进行顺序访问 抱歉,这不是我要找的那个 也可以创建“锯齿状”数组以使用一个连续的内存块。【参考方案2】:

"创建一个数组数组,但子数组的个数未知。"

如果使用C99 或此后支持variable length arrays 的编译器(自C11 起可选),这将提供一种在运行时执行此操作的方法。一个简短的例子:

#define ARRAY_BASE_SIZE 20 //known at compile time

int main()

    int numSubArrays = 0; 
    printf("enter a value for number of sub-arrays:\n");
    int count = scanf("%d", &numSubArrays);//not known until run-time
    if(count == 1)
    
        int array[ARRAY_BASE_SIZE][numSubArrays];
        memset(array, 0, sizeof(array)); 
    
    
    return 0;

【讨论】:

VLA 从 C11 开始是可选的。我知道你可能知道,但是…… @alk - 实际上从 C99 开始(当然更旧),这就是为什么我包含语句 "If using C99, or a compiler since then 支持 " 不过谢谢。 啊,好吧,很公平。仍然明确提到 C99 要么是多余的,要么只是事实的一半。 ;) 升级了。仍然:“sizeof 是运算符而不是函数!” ;-> 好吧,我觉得当我倾向于主要挑选其他人的帖子时,我可能需要转向全新的东西,再次戴上菜鸟帽,所以我决定深入了解和操纵这一点机器类型:mycloud.ch/l/… .... 数千页新旧文档可供阅读,旋钮可转动,按钮可切换,...​​ ;) 今天我或多或少地在这里绊倒了......好吧,假设是意外.但老实说,再次来到这里很有趣...... ;)【参考方案3】:

如果不知道子数组的数量,那么当子数组比你想象的多时,数组必须是可扩展的。

int **myArrays;        // the array of arrays
int nSubArrays= 0;     // its current size
int nUsed= 0;          // how many have been used
#define INCREMENT 5    // increment for alocation

myArrays= malloc(sizeof(int *) * INCREMENT);
nSubArrays= INCREMENT;
nUsed= 0;

现在填充数组:

myArrays[nUsed]= fillSubArray();
nUsed++;

并在数组满时展开:

if (nUsed==nSubArrays) 
    int **tmp= realloc(myArrays, sizeof(int *)*(nSubArrays+INCREMENT));
    if (!tmp) return 0; // error
    myArrays= tmp;
    nSubArrays += INCREMENT;

【讨论】:

【参考方案4】:

在 C 中,声明指针并将其作为数组引用是很常见的做法。在 C 中,当数组的引用分配给指针时,数组将衰减为指针。要引用一个数组数组,通常声明一个指向指针的指针,将其分配给二维数组的引用,然后像二维数组一样对其进行索引。

以下都是等价的。 argvchar 数组的数组。使用 [] 可以让其他可能正在阅读您的代码的程序员清楚地将指针用作数组的索引。

char **argv;
char *argv[];

字符 argv[][]; (这是错误的)

数组的大小通常是单独通信的。事实上,main 函数的参数就是这样做的。当你看到

int main(int argc, char *argv[]);

char *argv[] 是从命令行传递的字符数组(也称为字符串数组)。参数argc 表示argv 中的数组数量。要索引数组中的第一个元素,请使用argv[0],其类型将为char*(又名char[])。

【讨论】:

相信这是个问题。 char argv[][]; 这显示了如何声明它们而不是如何分配。请参阅 Paul 的评论 - 您想要包含 mallocrealloc 是的 char argv[][] 不正确。我会解决的【参考方案5】:

这个怎么样,只是尝试给出一个起点,而不是完整的答案,但我们可以在此基础上再接再厉。

我们还需要跟踪每个子数组的size 以访问有效位置,相信通过某种簿记可以轻松完成。

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

#define BASE_SIZE 3

int main()

    int** dyn_array = NULL;
    int countSubArray  = 0;
    int count = 0;
    int size = 0;
    
    dyn_array = malloc(sizeof (int* ) * BASE_SIZE);
    if ( dyn_array ) 
        printf("enter number of subarrays:");
        scanf("%d", &countSubArray);
        while( count < countSubArray) 
            printf("enter sizeof %d subarray", count+1);
            scanf("%d", &size);
            if ( dyn_array[count] = malloc(sizeof (int) * size) )
            
                printf("Allocated sub array %d at %p\n",count+1, (void*) dyn_array[count]);
            
            count++;
        
    
    return 0;

【讨论】:

以上是关于未指定子数组的数量时如何在C中创建数组数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有初始化和特定数量元素的情况下在 Kotlin 中创建对象数组?

如何在 C# 中创建一个包含数组但不使用堆的结构?

如何在 Java 中创建要打印到 JFrame 的 JLabels 数组

如何在 Unity 中创建数组的独立副本?

我必须在 C 中创建一个带有指向数组的结构数组

我们可以在 C++ 中创建可变长度数组吗