【问题标题】:GCC Compilation Error on array assignment数组分配的 GCC 编译错误
【发布时间】:2021-07-06 13:28:03
【问题描述】:

我正在尝试将一个字符串转换为它在 C 中的等效矩阵形式。该矩阵将有 3 行和尽可能多的列。下面的代码没有编译,我也没搞清楚是怎么回事。

GCC 抛出的错误是:

app.c:10:25: error: subscripted value is not an array, pointer, or vector
      printf("%d\n", arr[i][k]);
                     ~~~^~
1 error generated.

主文件(app.c):

#include <stdio.h>
#include "converter.h"

int main() {

  char source[] = "This is the source. "; // placeholder text
  int arr = convert(source);
  for (int i = 0; i < 21; i++) {
    for (int k = 0; k < 3; k++) {
      printf("%d\n", arr[i][k]); // error occurs at this line.
    }
  }

  return 0;
}

converter.c 文件:

// Converts an input string to its respective ASCII matrix.

#include <string.h>
#include <stdio.h>
#include "converter.h"

// Converts the entire string into an multi-dimensional array.
int convert(char text[]){

    // copy the input text into a local store.
    char store[strlen(text)];
    strcpy(store, text);

    // make sure the length of the input string is a multiple of 3 or make it so.
    int excess = strlen(store)%3;
    char excess_spaces[3] = "   ";
    if (excess != 0) {
      strncat(store, excess_spaces, 3-excess);
    }

    // covert the source into an array
    int arr[3][strlen(store)/3];
    int steps = strlen(store)/3;
    for (int i = 0; i < steps; i++) {
      int t[3];
      for (int k = 0; k < 3; k++) {
        t[k] = (int) store[3*i+k];
        arr[k][i] = t[k];
      }
    }

    return arr;

}

converter.h 文件:

int convert(char text[]);

【问题讨论】:

  • 不是数组、指针或向量。这似乎很清楚。你理解 arr 之后是什么类型:int arr = convert(source);
  • convert 函数存在多个问题。它的返回类型是int,而不是数组。此外,您不能返回对局部变量的引用,因为它在函数退出后立即变为无效 - 传入一个数组以供函数填充或使用动态内存分配。 How to return matrix (2D array) from function? (C)

标签: c


【解决方案1】:

这段代码存在多个问题。

  1. 为字符串分配存储,必须包含一个字节作为空终止符。替换:
char store[strlen(text)];

与:

char store[strlen(text) + 1];

此外,store 必须足够大以包含最多 3 个空格的 excess

char store[strlen(text) + 3 + 1];
  1. 在 C 中,您不能将数组用作值。它被转换为指向它在所有上下文中的第一个元素的指针。因此无法直接返回数组。它可以通过用结构包装数组来解决,但它是另一天的主题。

结果return arr 将等价于return &amp;arr[0],即int (*)[XXX] 指向int 大小为XXX 的数组的指针。

  1. 从不返回指向自动存储对象的指针。这是未定义的行为。我知道目的是返回一个数组而不是指向它的指针。使用类似malloc 的函数创建具有动态存储的对象,以安全地返回指针。

  2. 无法按值返回可变长度数组 (VLA),因为无法在文件范围内定义可变修改 (VM) 类型。

  3. 看起来索引被交换了:

printf("%d\n", arr[i][k]);

我猜应该是arr[k][i]

现在...让我们解决它。

返回 VLA 很棘手。一种解决方案是将指向 VLA 的指针作为参数传递。见https://stackoverflow.com/a/14088851/4989451。 这个解决方案的问题是调用者必须能够计算维度。

convert() 的结果包装到struct 的另一种方式。请注意,函数和结构可以共享名称。结果的 VLA 大小为nm 成员,指向数据的指针为arr。调用者需要将其转换为正确的 VM 类型。

为了在非平凡指针类型之间进行繁琐的转换,可以通过void* 进行转换。

当数组的所有工作都完成后,使用free() 释放它的内存。

// Converts an input string to its respective ASCII matrix.

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

// Converts the entire string into an multi-dimensional array.
struct convert {
    int n, m;
    int *arr;
} convert(char text[]){

    // copy the input text into a local store.
    size_t textlen = strlen(text);
    char store[textlen + 3 + 1];
    strcpy(store, text);

    // make sure the length of the input string is a multiple of 3 or make it so.
    int excess = textlen % 3;
    char excess_spaces[3] = "   ";
    if (excess != 0) {
      strncat(store, excess_spaces, 3-excess);
    }
    size_t storelen = strlen(store);

    // allocate VLA with dynamic storage
    int (*arr)[storelen / 3] = malloc(3 * sizeof *arr);

    // covert the source into an array
    int steps = storelen / 3;
    for (int i = 0; i < steps; i++) {
      int t[3];
      for (int k = 0; k < 3; k++) {
        t[k] = (int) store[3*i+k];
        arr[k][i] = t[k];
      }
    }

    return (struct convert){ .n = 3, .m = steps, .arr = (int*)arr };
} 

int main() {

  char source[] = "This is the source. "; // placeholder text

  struct convert res = convert(source);
  int n = res.n, m = res.m;
  int (*arr)[m] = (void*)res.arr;

  for (int i = 0; i < n; i++, puts("")) {
    for (int k = 0; k < m; k++) {
      printf("%d ", arr[i][k]); // error occurs at this line.
    }
  }
  free(arr);

  return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    相关资源
    最近更新 更多