1

在 C 编程中,我遇到了一种情况,我不小心初始化了一个可变大小的数组并且它起作用了。我做了一些研究,显然可变长度数组可从 C99 编译中获得。显然,GCC 4.8.2 的默认编译选项是 C98。

这是我用来测试的代码:

#include "stdio.h"
#include "stdlib.h" // rand(), srand()
#include "time.h"

void printArray(const char* c) {
    // impossible to get size of c because it returns pointer size
    int array[sizeof(c)/sizeof(char)];
    int i;
    for(i=0; i<(sizeof(c)/sizeof(char))-1; i++) {
        int fill=-1;
        if(c[i]=='a')
            fill = 0;
        else if(c[i]=='b')
            fill = 1;
        array[i]=fill;
    }
    printf("contents of array in binary: \n");
    for(i=0; i<(sizeof(c)/sizeof(char))-1; i++) {
        printf("%d, ", array[i]);
    }
    printf("\n");
}

void printRandomArray() {
    srand(time(NULL));
    // variable length array is possible using C99
    int array[rand()%10];
    int i;
    printf("contents of random array: \n");
    for(i=0; i<(sizeof(array)/sizeof(int)); i++) {
        array[i]=rand()%10;
        printf("%d, ", array[i]);
    }
    printf("\n");
}

int main(int argc, char* argv[]) {
    char c[]="abbabbabbaababababababb";
    printArray(c);

    printRandomArray();
    return 1;
}

printRandomArray() 不应该工作,因为我使用 GCC 4.8.2 默认编译,即 C98,但它可以工作。有人可以向我解释为什么会这样吗?

4

3 回答 3

2

除了 C99 标准,GCC 还允许变长数组作为扩展:

6.19 可变长度数组

ISO C99 允许可变长度自动数组,作为扩展,GCC 在 C90 模式和 C++ 中接受它们。

-std=gnu90AFAIK,GCC 4.8.2默认以模式编译代码。用 option 编译它,-std=c89你会看到很多警告和错误。

于 2015-01-10T20:09:35.713 回答
1

所以GCC支持两种不同版本的C89。它支持c89gnu89。后者意味着启用了许多 gcc 扩展。

GCC 4.8.2 的默认标准语言是gnu90,与gnu89. [参见 gcc 文档]

让我们看看我们在使用这些不同的语言时得到的不同警告/错误:

GNU89 和 GNU90

[2:10pm][wlynch@apple /tmp] /opt/gcc/4.8.2/bin/gcc            asd.c
[2:10pm][wlynch@apple /tmp] /opt/gcc/4.8.2/bin/gcc -std=gnu89 asd.c
[2:10pm][wlynch@apple /tmp] /opt/gcc/4.8.2/bin/gcc -std=gnu90 asd.c
[2:10pm][wlynch@apple /tmp] 

C89

[2:10pm][wlynch@apple /tmp] /opt/gcc/4.8.2/bin/gcc -std=c89 asd.c
asd.c:2:21: warning: extra tokens at end of #include directive [enabled by default]
 #include "stdlib.h" // rand(), srand()
                     ^
asd.c: In function ‘printArray’:
asd.c:6:5: error: expected expression before ‘/’ token
     // impossible to get size of c because it returns pointer size
     ^
asd.c:15:9: error: ‘array’ undeclared (first use in this function)
         array[i]=fill;
         ^
asd.c:15:9: note: each undeclared identifier is reported only once for each function it appears in
asd.c: In function ‘printRandomArray’:
asd.c:26:5: error: expected expression before ‘/’ token
     // variable length array is possible using C99
     ^
asd.c:30:24: error: ‘array’ undeclared (first use in this function)
     for(i=0; i<(sizeof(array)/sizeof(int)); i++) {
                        ^
[2:10pm][wlynch@apple /tmp] /opt/gcc/4.8.2/bin/gcc -std=gnu89 asd.c
[2:10pm][wlynch@apple /tmp] 

如果我们修复了这些错误,然后也使用 编译-pedantic,我们将看到您正在寻找的诊断:

[2:28pm][wlynch@apple /tmp] /opt/gcc/4.8.2/bin/gcc -std=c89 -pedantic asd.c
asd.c: In function ‘printRandomArray’:
asd.c:27:5: warning: ISO C90 forbids variable length array ‘array’ [-Wvla]
     int array[rand()%10];
     ^
asd.c:27:5: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
于 2015-01-10T20:12:03.333 回答
0

首先,没有C98这样的东西。它是 C89/90,然后是 C95(通常合并到 C89/90),然后是 C99,依此类推。

其次,GCC 编译器在其默认模式下根本不实现任何标准 C。它正在编译的语言称为 GNU C。它默认支持 VLA 并没有什么不寻常的地方。您必须手动配置 GCC 以使其符合任何 C 标准。开关喜欢-pedanticor-pedantic-errors是必须的。

于 2015-01-10T20:42:06.573 回答