当您不知道程序开始时的长度时如何在多个函数中使用数组

How to use an array in multiple functions when you don't know what the length will be at the start of your program

我有一个项目,我需要在两个不同的函数中使用一个数组,但它的长度因命令行参数而异,所以我以后才知道它是什么。我如何全局初始化数组,但是当我知道长度后我可以更改长度。这是我能做的问题的最简化版本:

#define _XOPEN_SOURCE 500

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


char tile_numbers[1];
void print (void);

int main (void)
{
    int x = 7;
    char tile_numbers[x];
    tile_numbers[0] = 'h';
    tile_numbers[1] = 'e';
    tile_numbers[2] = 'l';
    tile_numbers[3] = 'l';
    tile_numbers[4] = 'o';
    tile_numbers[5] = '!';

    print();

}

void print (void)
{

    for(int i = 0; i < 10 ; i++)
    {
        printf("char: %c", tile_numbers[i]);
    }

}

您可以使用 malloc() 动态分配内存,而不是数组。假设在 运行 时,您将数组的大小存储在 int 变量 n 中。然后,您可以使用

分配内存
char *tile_numbers = (char*)malloc(sizeof(char)*n);

然后,您可以像以前一样为内存位置编制索引,如 tile_numbers[i] 用于 0n-1 范围内的任何 i


如果需要全局声明,将声明和赋值分开。在全球范围内,使用

char *tile_numbers;

在获取尺寸的函数中,

tile_numbers = (char*)malloc(sizeof(char)*n);

此外,如果需要调整内存大小,可以使用realloc(),

tile_numbers = (char*)realloc(tile_numbers,new_size);

不要使用全局 - 在main(或最初分配的任何地方)定义数组,然后将其作为参数传递给函数需要使用它:

void print( size_t size, const char *arr)
{
  for ( size_t i = 0; i < size; i++ )
    printf( "char: %c\n", arr[i] );
}

int main( int argc, char **argv )
{
  // define tileNumbers here -- we'll get into details below

  print( arraySize, tileNumbers );
  return 0;
}

不要养成使用全局(文件范围)变量的习惯 - 它会导致代码难以维护和扩展。 有时这是有道理的,但你还不知道那些时间是什么时候。通常,函数应该只通过参数或 return 值共享信息;他们不应该共享全局状态。

因为直到运行时才知道 tileNumbers 需要多大,所以不能将其分配为固定大小的数组并在以后调整大小。在知道大小之前,您需要推迟数组的定义。

在 C99 之前,您唯一的选择是使用动态内存(即 malloccalloc):

#include <stdlib.h> // for malloc declaration
...
size_t arraySize = getArraySize( );  // where getArraySize is a stand in for any code that sets arraySize

char *tileNumbers = malloc( sizeof *tileNumbers * arraySize );
if ( tileNumbers )
{
  // code to initialize tileNumbers goes here

  print( arraySize, tileNumbers );

  // deallocate memory when we're done with it
  free( tileNumbers );
}

从 C99 开始,您可以使用所谓的 可变长度数组 (VLA)。 VLA 的行为主要 类似于常规的固定长度数组,但由于其大小直到运行时才知道,因此不能在文件范围内声明(不能将其用作global), 不能是 structunion 类型的成员,并且在其声明中不能有初始化器。

size_t arraySize = getArraySize( );  // where getArraySize is a stand in for any code that sets arraySize;

char tileNumbers[arraySize];

// code to initialize tileNumbers goes here

print( arraySize, tileNumbers );

无论如何,print 的原型将保持不变。在第一种情况下,我们传递一个指针。在第二种情况下,我们传递一个数组表达式,在计算时 decays 到一个指针表达式。