【问题标题】:How to convert array to 2d-matrix without allocating extra memory in C?如何在不在 C 中分配额外内存的情况下将数组转换为二维矩阵?
【发布时间】:2019-11-09 07:40:12
【问题描述】:

这是这个问题的后续问题:C - Convert array of elements into 2-d matrix

要进行转换,我得到的方法是:

int (* M)[b] = (int (*) [b])array

M[a][b]array[a * b] 的位置。

问题是我发现当我以这种方式进行转换时,实际上在堆栈上分配了一个大小为b 的数组,对于一个大的b 来说有点昂贵。所以我想知道是否有任何方法可以在没有这种分配的情况下进行转换。

示例(更新):

/* conversion.c */

int main(void) {
    int flag, array[30], b = 3;

    if (flag)
        goto done;

    int (* M)[b] = (int (*)[b]) array;

done:
    return 0;
}

用 gcc-9 编译:

conversion.c: In function 'main':
conversion.c:5:3: error: jump into scope of identifier with variably modified type
    5 |   goto done;
      |   ^~~~
conversion.c:9:1: note: label 'done' defined here
    9 | done:
      | ^~~~
conversion.c:7:9: note: 'M' declared here
    7 |  int (* M)[b] = (int (*)[b]) array;
      |         ^
conversion.c:5:3: error: jump into scope of identifier with variably modified type
    5 |   goto done;
      |   ^~~~
conversion.c:9:1: note: label 'done' defined here
    9 | done:
      | ^~~~
conversion.c:7:9: note: '({anonymous})' declared here
    7 |  int (* M)[b] = (int (*)[b]) array;
      |         ^

更新: error: jump into scope of identifier with variably 表示 goto 语句正在尝试跳过(编译时)堆栈上未知大小的内存,这意味着由于上述转换,堆栈上分配了内存。

【问题讨论】:

  • here is actually an array of size b allocating on the stack 你怎么确定这是因为int (*M)[b] 而发生的。你能显示minimal reproducible example吗?
  • 如果没有minimal reproducible example,我们不知道您指的是什么goto 语句和编译错误。帖子中的代码不会占用我们可以说的堆栈内存。
  • “实际上有一个大小为 b 的数组在堆栈上分配”谁说的? M 是指向大小为 b 的数组的指针。但是,您的演员表是非标准的,并且在取消引用 M 时可能会导致 UB。并且请不要使用 goto,这里完全没有根据。
  • 不,编译器错误并没有说明内存、堆栈或任何此类废话。它谈到了标识符类型
  • 投票结束不清楚,因为问题现在提出了完全不同的问题,并且发布的答案不再有意义。这是浪费大家的时间,干脆关闭吧。

标签: c arrays pointers matrix type-conversion


【解决方案1】:

实际上有一个大小为 b 的数组在堆栈上分配

没有这样的事情发生。您正在尝试声明指向数组的指针,而不是数组。

标准的 goto 部分的第一段禁止您尝试做的事情。

6.8.6.1 [goto 语句]/1 goto 语句不应从具有可变修改类型的标识符范围之外跳转到该标识符范围内。

由相关标识符表示的对象占用的内存量是变量还是常量都没有关系。它的类型从 VLA 类型派生就足够了,例如,如果它是指向一个的指针。

您不需要 goto 或其他任何东西。

int main(void) {
    int flag = 0, array[30], b = 3;

    if (!flag) {
        int (*M)[b] = (int (*)[b]) array;
        // note that dereferencing M here is undefined behaviour
        (void)M;
    }
    return 0;
}

Live demo

【讨论】:

  • 那么为什么在这里取消引用 M 是 UB?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多