【问题标题】:Pass a constant two-dimensional array to function as a structure in C传递一个常量二维数组作为 C 中的结构体
【发布时间】:2018-04-03 14:37:20
【问题描述】:

我是 C 的新手,我需要一个结构来传递常量二维数组以作为一个参数。我想做这个

const int a_size_x = 20;
const int a_size_y = 30;
const int a_output_array[size_x][size_y] = {{..., ...}, ..., {..., ...}};

const int b_size_x = 20;
const int b_size_y = 30;
const int b_output_array[size_x][size_y] = {{..., ...}, ..., {..., ...}};

void function(const int array[], int arr_size_x, int arr_size_y){
    for (int i = 0; i < arr_size_x; i++) 
    {
        for (int j = 0; j < arr_size_y; j++)
        {
            printf("%i ", array[i][j];
        }
        printf("\n");
    }

function(a_output_array, a_size_x, a_size_y);
function(b_output_array, b_size_x, b_size_y);

更容易像这样调用 function(a):

const struct OUTPUT
{
    const int size_x;
    const int size_y;
    const int array[size_x][size_y];
};

struct OUTPUT a = {.size_x = 20, .size_y = 30, .array = {{...}, ..., {...}};
....
struct OUTPUT z = {.size_x = 30, .size_y = 20, .array = {{...}, ..., {...}};


function(const struct OUTPUT out){
    for (int i = 0; i < out.size_x; i++) 
    {
        for (int j = 0; j < out.size_y; j++)
        {
            printf("%i ", out.array[i][j];
        }
        printf("\n");
    }

function(a);
function(b);

但是编译器当然会说 size_x 和 size_y 在结构声明中是未声明的。
我读过关于灵活数组成员的文章,但是需要动态内存分配,并且在 AVR 哈佛架构中,malloc 不能在程序内存中工作,我将所有这些数据都放在那里。

在 C 中有什么方法可以做到吗?可能是,在 C++ 中?

UPDATE 对我有用的答案 - 创建一个长度为 2 + width*height 的一维数组,其中前两个成员是真实的宽度和高度并使用指针与此合作。这是一个打印出这个数组的示例函数:

char arr [11] = 
{
   3 // width
   3 // height
   1, 2, 3,
   4, 5, 6,
   7, 8, 9
}

void print_array(char *ptr)
{
   char width = *ptr++;
   char height= *ptr++;
   for (int i = 0; i < height; i++)
   {
      for (int j = 0; j < width; j++)
      {
         print("%c\t", *ptr++);
      }
      print("\n");
   }
}

print_array(arr);

【问题讨论】:

  • 这个void function(const int array[], ... 将数组定义为指向int 的指针。所以这个printf("%i ", array[i][j]; 不会编译。将二维数组传递给它会调用未定义的行为,不说是完全错误的。
  • 什么是const struct OUTPUT?您需要一个或多个标签的列表
  • 是的,sn-ps肯定有一些错误。实际上,当我编写函数时,我使用了(int *array, int size_x, int size_y) 参数。但这不是一个问题。我的问题是得到一个结构,它可以更容易地定义许多具有不同维度的对象和只需要一个参数(这个结构)来处理这些数组的函数,因为其中有许多'A_array','B_array'然后在具有所有三个参数的函数中多次调用它会使程序变得一团糟。

标签: c arrays struct


【解决方案1】:

对于大多数编译器,2D 数组可以被称为 1D,如下所示: 矩阵[3][3]=[1,2,3 4,5,6 7,8,9] 一维索引按行大小*行数计算。例如:矩阵[5]=6。

这意味着您只能传递 1 个参数,即行长,通过calculating the length of the whole vector 您可以推导出第二个参数(行数)。

您可以将行长度参数添加到数组的末尾,并且只传递数组,如果有帮助的话。

【讨论】:

  • "在C语言中,二维数组可以称为一维" 不对,是a grey area at best。
  • 已编辑,谢谢。至少对于大多数编译器来说不是这样吗?
  • 这是您可能很难找到 C 的实际实现不按照您的期望进行的事情之一,但根据语言标准:)
  • 当然,这意味着您可能会为您的嵌入式项目选择这种方法,确保您的编译器符合您的预期。不过,为了确定,我总是更喜欢找到一个合规的解决方案。在这种情况下,我可能会选择直接使用平面数组。
  • 请注意,第一段中的matrix[5] 是数组的一行,只是它超出了数组的范围。 matrix[2] 将是指向包含 7、8、9 的行的指针——在许多情况下,它将成为指向包含 7 的元素的指针。在任何情况下,matrix[5] 都不会引用值为 6 的元素。您的初始值设定项会引发编译器设置的警告——他们更喜欢 int matrix[3][3] = { { 1, 2, 3, }, { 4, 5, 6, }, { 7, 8, 9, }, };(如果您愿意,最多可以省略四个尾随逗号)。
【解决方案2】:

使用初始化器声明数组时,数组的边界必须是常量。带有const 限定符的变量不符合常量的条件。但是,您可以使用执行文本替换的宏:

#define A_SIZE_X 2
#define A_SIZE_Y 3
const int a_output_array[A_SIZE_X][A_SIZE_Y] = {{3,4,5},{6,7,8}};

#define B_SIZE_X 2
#define B_SIZE_Y 3
const int b_output_array[B_SIZE_X][B_SIZE_Y] = {{1,2,3},{4,5,6}};

将二维数组传递给函数时,定义必须说明它需要一个二维数组。你期待const int array[] 这是一个一维数组。

你可以让一个函数接受具有不同边界的数组如果在定义中首先指定了边界:

void function(int arr_size_x, int arr_size_y, const int array[arr_size_x][arr_size_y]) {

你可以这样称呼它:

function(A_SIZE_X, A_SIZE_Y, a_output_array);
function(B_SIZE_X, B_SIZE_Y, b_output_array);

【讨论】:

  • 值得一提的是后者需要 VLA 支持。
【解决方案3】:

先说明一下,第一个 sn-p 有一个错误的签名,你的编译器应该警告你:

void function(const int array[], int arr_size_x, int arr_size_y){

这里,array 是一个 指向 int 的指针(在函数签名中,数组会自动调整为指针),但要传递二维数组,您需要一个 指向 int 数组的指针。你测试过那个sn-p吗?我认为它不会做你想要的。

对于 C99 及更高版本(假设编译器支持 VLA、可变长度数组),这样的事情是正确的:

void function( int arr_size_x, int arr_size_y, const int (*array)[arr_size_y]){

至于你对结构的想法,你只能在保持第二维固定的情况下这样做。 C 数组在内存中是连续的,因此要正确进行索引,编译器必须在编译时知道除第一个维度之外的所有维度。 VLA 是该规则的一个例外,但您不能静态声明 VLA。

但是,您可以做的是使用平面数组并自己进行二维索引,就像在这个小例子中一样:

struct outputdata
{
    size_t rows;
    size_t cols;
    int *data;
};

const int a_data[] = {1, 2, 3, 4, 5, 6};
const struct outputdata a = {
    .rows = 2,
    .cols = 3,
    .data = a_data
};

// [...]

void function(const struct outputdata x)
{
    for (size_t r = 0; r < x.rows; ++r)
    {
        for (size_t c = 0; c < x.cols; ++c)
        {
            printf("%d ", x.data[r*x.cols + c]);
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-03-23
    • 2014-05-28
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    • 2015-08-23
    • 2015-07-20
    相关资源
    最近更新 更多