为什么 Xcode 允许我在任何地方声明 C 变量?
Why is Xcode allowing me to declare C variables anywhere?
我在 Xcode 中创建了一个基本的 C 项目,并在 main.c 中稍微修改了起始代码。我还进入构建设置并告诉它使用 ANSI-C。这是我的代码:
int main(int argc, const char * argv[])
{
// a statement!
printf("Hello, World!\n");
// shouldn't this cause a compiler error?
// the variable isn't declared at the top of the scope.
int x;
x += 10;
return 0;
}
显然,它并没有做太多,但我预计变量声明会产生编译器错误(因为旧版本的 C 需要在作用域的开头,在其他语句之前进行变量声明)。然而,Xcode 愉快地编译并运行它,既没有错误也没有警告。
我可能在某个地方犯了一个愚蠢的错误,但我试图理解为什么这段代码可以编译。我读过 C99 和 C11 允许您在任何地方声明变量,所以这可行,但我明确地将项目设置为使用 ANSI-C。这就是 Apple 的 LLVM 编译器的工作方式吗?还是我在其他地方遗漏了什么?
TL;DR 您需要将 -pedantic
(或 -Wdeclaration-after-statement
)添加到 -ansi
以获得您想要的警告。
令我惊讶的是,clang
(来自 Apple XCode 7.2)和 gcc
(来自我构建的 GCC 5.3.0)在编译时都接受代码-std=c90
或 -ansi
,即使它不严格符合 C90。
然而,当被告知 -pedantic
时,两者都会抱怨 -pedantic
。
$ clang -ansi -c xyz.c
$ clang -std=c90 -c xyz.c
$ gcc -std=c90 -c xyz.c
$ which gcc
/opt/gcc/v5.3.0/bin/gcc
$ gcc -std=c90 -pedantic -c xyz.c
xyz.c: In function ‘main’:
xyz.c:7:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int x;
^
$ clang -pedantic -std=c90 -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$ clang -pedantic -ansi -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$
文件 xyz.c
是您的源代码,删除了注释,在顶部添加了 #include <stdio.h>
,并且 int main(void)
代替了 int main(int argc, char **argv)
,因为代码没有不要使用参数。
请注意,您的代码有 未定义的行为; 递增未初始化的变量是个坏主意。
我在 Xcode 中创建了一个基本的 C 项目,并在 main.c 中稍微修改了起始代码。我还进入构建设置并告诉它使用 ANSI-C。这是我的代码:
int main(int argc, const char * argv[])
{
// a statement!
printf("Hello, World!\n");
// shouldn't this cause a compiler error?
// the variable isn't declared at the top of the scope.
int x;
x += 10;
return 0;
}
显然,它并没有做太多,但我预计变量声明会产生编译器错误(因为旧版本的 C 需要在作用域的开头,在其他语句之前进行变量声明)。然而,Xcode 愉快地编译并运行它,既没有错误也没有警告。
我可能在某个地方犯了一个愚蠢的错误,但我试图理解为什么这段代码可以编译。我读过 C99 和 C11 允许您在任何地方声明变量,所以这可行,但我明确地将项目设置为使用 ANSI-C。这就是 Apple 的 LLVM 编译器的工作方式吗?还是我在其他地方遗漏了什么?
TL;DR 您需要将 -pedantic
(或 -Wdeclaration-after-statement
)添加到 -ansi
以获得您想要的警告。
令我惊讶的是,clang
(来自 Apple XCode 7.2)和 gcc
(来自我构建的 GCC 5.3.0)在编译时都接受代码-std=c90
或 -ansi
,即使它不严格符合 C90。
然而,当被告知 -pedantic
时,两者都会抱怨 -pedantic
。
$ clang -ansi -c xyz.c
$ clang -std=c90 -c xyz.c
$ gcc -std=c90 -c xyz.c
$ which gcc
/opt/gcc/v5.3.0/bin/gcc
$ gcc -std=c90 -pedantic -c xyz.c
xyz.c: In function ‘main’:
xyz.c:7:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int x;
^
$ clang -pedantic -std=c90 -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$ clang -pedantic -ansi -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$
文件 xyz.c
是您的源代码,删除了注释,在顶部添加了 #include <stdio.h>
,并且 int main(void)
代替了 int main(int argc, char **argv)
,因为代码没有不要使用参数。
请注意,您的代码有 未定义的行为; 递增未初始化的变量是个坏主意。