Gcc 4.8.2 默认编译和运行可变长度数组
Gcc 4.8.2 default compiles and runs variable length arrays fine
在 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,但它工作。谁能给我解释一下为什么会这样?
除了C99标准,GCC还允许可变长度数组作为扩展:
6.19 Arrays of Variable Length.
Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++.
AFAIK,GCC 4.8.2 默认在 -std=gnu90
模式下编译代码。使用选项 -std=c89
编译它,您将看到大量警告和错误。
所以 GCC 支持两个不同版本的 C89。它支持 c89
和 gnu89
。后者意味着启用了一些 gcc 扩展。
GCC 4.8.2 的默认标准语言是 gnu90
,与 gnu89
相同。 [see gcc documentation]
让我们看看使用这些不同语言时收到的不同警告/错误:
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]
首先,没有C98这样的东西。它是C89/90,然后是C95(通常合并到C89/90),然后是C99等等。
其次,默认模式下的 GCC 编译器根本不实现任何标准 C。它正在编译的语言称为 GNU C。默认情况下它支持 VLA 没有什么不寻常的。您必须手动配置 GCC 才能使其符合任何 C 标准。 -pedantic
或 -pedantic-errors
之类的开关是必须的。
在 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,但它工作。谁能给我解释一下为什么会这样?
除了C99标准,GCC还允许可变长度数组作为扩展:
6.19 Arrays of Variable Length.
Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++.
AFAIK,GCC 4.8.2 默认在 -std=gnu90
模式下编译代码。使用选项 -std=c89
编译它,您将看到大量警告和错误。
所以 GCC 支持两个不同版本的 C89。它支持 c89
和 gnu89
。后者意味着启用了一些 gcc 扩展。
GCC 4.8.2 的默认标准语言是 gnu90
,与 gnu89
相同。 [see gcc documentation]
让我们看看使用这些不同语言时收到的不同警告/错误:
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]
首先,没有C98这样的东西。它是C89/90,然后是C95(通常合并到C89/90),然后是C99等等。
其次,默认模式下的 GCC 编译器根本不实现任何标准 C。它正在编译的语言称为 GNU C。默认情况下它支持 VLA 没有什么不寻常的。您必须手动配置 GCC 才能使其符合任何 C 标准。 -pedantic
或 -pedantic-errors
之类的开关是必须的。