【发布时间】:2015-02-19 11:40:41
【问题描述】:
我正在学习 88 个 C 程序,在将近 25 年后重新学习 C(由于自 1990 年以来该语言本身至少有两次主要版本修订,这一事实变得复杂,而且我确信我当时使用的 Turbo-C 不完全兼容 C89)。我不记得我参加的课程对二维数组做了任何重要的事情,并将它们传递给函数,并期望我需要在编译时不知道维度的情况下处理数据,这很好地制作我的头爆炸了。
我正在使用 gcc(目前在 Ubuntu 14.04 的标准存储库中找到的版本),我收集的它应该支持 C99 或 C2011 标准下的可变长度数组声明,但我试图使用的声明使函数识别数组而不必在编译时知道大小会收到有关“冲突类型”的错误。我正在编译时将警告设置为 max,使用一个小型 Python 程序来节省每次需要编译时都必须键入一个长命令行(结果命令是 gcc -std=c99 -pedantic -Wall -Wextra -o target target.c -lm)。以下是原型、调用者行和函数定义(代码也充满了引起警告的不良做法,我从书中复制了它;我现在不关心这些,我有兴趣学习理智的方法来做到这一点,所以我不必使用那些丑陋、令人困惑的方法)。
#include <stdio.h>
#include <stdlib.h>
/* ANSI prototypes */
void s2 (int, int, int*);
int main (void);
int main (void)
{
int one[5]={0,1,2,3,4};
int two[3][4] =
{
{0,1,2,3},
{10,11,12,13},
{100,101,102,103}
};
/* try to call s2, it won't work */
printf("\ncalling s2 \n");
s2(1, 5, one);
s2(3, 4, two); /* will be compiler warning */
}
void s2(int rows, int cols, int *x[rows][cols])
{
/* wants to use multiple square brackets; needs dimension info */
int i,j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
printf("%4i", x[i][j]);
}
}
这会给出以下警告和错误字符串:
./gccm sotest
sotest.c: In function ‘main’:
sotest.c:22:3: warning: passing argument 3 of ‘s2’ from incompatible pointer type [enabled by default]
s2(3, 4, two); /* will be compiler warning */
^
sotest.c:6:6: note: expected ‘int *’ but argument is of type ‘int (*)[4]’
void s2 (int, int, int*);
^
sotest.c: At top level:
sotest.c:25:6: error: conflicting types for ‘s2’
void s2(int rows, int cols, int *x[rows][cols])
^
sotest.c:6:6: note: previous declaration of ‘s2’ was here
void s2 (int, int, int*);
^
sotest.c: In function ‘s2’:
sotest.c:32:7: warning: format ‘%i’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%4i", x[i][j]);
^
我至少花了几个小时在这里挖掘其他类似的问题,阅读网络上的文章,并且通常试图将我的大脑包裹在当你需要通过二维数组到 C 中的函数——在许多其他语言中非常简单,而一维数组在 C 中很容易!我没有发现任何有意义的东西;我见过的唯一明智的建议是将数组包装在Struct 中,但是在 C 被广泛使用的前二十年左右肯定不存在这些建议,我不确定它是如何/为什么会这样的更好。
【问题讨论】:
-
你看这里无数类似的问题了吗?
-
@2501 他们无数的事实使得在有限的时间内不可能查看所有这些,但我确实检查过的样本(前 2-3 个搜索页面上的那些标题看起来相关) 没有回答我的问题——尽管完整阅读了其中的几个。
-
struct从一开始就是语言的一部分 (K&R)。没有解决“如何/为什么让它变得更好”,只是必须向使用网络上各种真正古老但免费的编译器之一的人指出这一点。 -
后期跟进——使用
struct让一切大大变得更简单;在大多数情况下,结构就像一维数组一样传递(并且很容易从编译错误中找出需要指针的少数情况)。对可变长度数组没有多大作用,但那里似乎没有太多可用的简化。