sud*_*udo 13 c linux macos gcc
我把我的main.c文件用Mac OS X中的gcc -std = c1x -c main.c编译,它没有错误,工作正常.然后我在LinuxMint和Raspberry Pi上执行完全相同的操作,在这两种情况下,它都给出了"初始化元素不是常量"的错误.
带有相关代码的问题行的一个示例:
//STATIC GLOBAL CONSTANTS
const unsigned long long LATITUDE = (long) 3600000;
const unsigned long long LONGITUDE = (long) 1810000;
const unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1); //compiler error: initializer element is not constant
Run Code Online (Sandbox Code Playgroud)
它应该让我做算术,对吗?我可以用实际数字替换它,它会起作用,但随后会变得混乱.无论如何,它在我的Mac上运行良好.在GCC中是否有一些选项我必须在Linux上指定(除了-std = c1x,你在Mac上也不需要)?
Kei*_*son 24
C语言要求静态对象的初始化程序为常量表达式.(由于静态对象的初始化在main开始之前发生,因此没有任何地方可以进行任何运行时评估.)
C的const关键词并不意味着"常数",尽管这些词语显然是相关的.甲常量表达式是一个,可以是,在某些情况下,必须在编译时,评价.const意味着只读.例如,在块范围内(在函数定义内),这:
const int r = rand();
Run Code Online (Sandbox Code Playgroud)
是完全合法的.显然,初始化程序无法在编译时进行评估; 在const仅仅意味着r它已经initalized后,不得修改.
当你写:
const unsigned long long LATITUDE = (long) 3600000;
Run Code Online (Sandbox Code Playgroud)
引用LATITUDE不是常量表达式.编译器当然可以在编译时评估这样的引用,但C标准并不要求它.(常量和非常量表达式之间的界限必须在某处绘制,并且该语言的作者选择使区分相对简单,几乎没有特殊情况.)
现在确实可以定义C语言,这LATITUDE是一个常量表达式.它是用C++编写的,我认为C采用了类似的规则.但是根据当前的C规则,它不是,这意味着你不能LATITUDE在初始化器中使用静态对象.
这也意味着clang(据我所知,编译器是gcc在MacOS下键入时调用的编译器)非常可能不符合,因为它无法诊断此错误.在我自己的Linux系统上,我发现,当调用时-std=c11 -pedantic,gcc 4.7.2正确诊断错误,但是clang 3.4没有.
除了也许从第6.6节,2011年ISO C标准的第10段(其也存在于1990和1999的标准)这个子句:
实现可以接受其他形式的常量表达式.
可以想象clang接受LATITUDE作为一个常量表达,因为它利用了这个权限 - 但是我仍然期望至少有一个警告clang -std=c11 -pedantic -Wall -Wextra,而且没有.
更新:当我编译以下内容时:
#include <stdio.h>
const unsigned long long LATITUDE = (long) 3600000;
int main(void) {
switch (0) {
case LATITUDE:
puts("wrong");
break;
default:
puts("ok(?)");
break;
}
}
Run Code Online (Sandbox Code Playgroud)
有了clang 3.0和选项-std=c99 -pedantic,我得到:
c.c:7:14: warning: expression is not integer constant expression (but is allowed as an extension) [-pedantic]
case LATITUDE:
^~~~~~~~
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
使用clang 3.4,警告是:
c.c:7:14: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]
case LATITUDE:
^~~~~~~~
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
所以clang确实认识到它不是一个恒定的表达; 错误是它没有警告声明MAX_COORDINATES_NUMBER.
另一个更新:
问题中的代码是:
const unsigned long long LATITUDE = (long) 3600000;
const unsigned long long LONGITUDE = (long) 1810000;
const unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1);
Run Code Online (Sandbox Code Playgroud)
(long)前两个声明中的强制转换无效.常量3600000和1810000(可能)类型int.您将它们转换为long然后使用结果初始化类型的对象unsigned long long.只需删除演员 - 或者,如果你想更明确,添加一个ULL后缀来制作常量unsigned long long:
const unsigned long long LATITUDE = 3600000ULL;
const unsigned long long LONGITUDE = 1810000ULL;
Run Code Online (Sandbox Code Playgroud)
问题出在第三个声明中,它引用的是,LATITUDE并且LONGITUDE都不是常量表达式.不幸的是,C不提供定义整数类型的命名常量的好方法int(你可以(ab)将该enum特性用于int常量).另一种方法是使用宏.这有效:
#define LATITUDE 3600000ULL
#define LONGITUDE 1810000ULL
const unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1);
Run Code Online (Sandbox Code Playgroud)
如果你需要MAX_COORDINATES_NUMBER成为一个常量表达式,你也可以使它成为一个宏:
#define LATITUDE 3600000ULL
#define LONGITUDE 1810000ULL
#define MAX_COORDINATES_NUMBER ((LATITUDE-1) + LATITUDE*(LONGITUDE-1))
Run Code Online (Sandbox Code Playgroud)
(当您MAX_COORDINATES_NUMBER在更大的表达式中使用时,需要额外的括号来避免运算符优先级问题.)
| 归档时间: |
|
| 查看次数: |
21385 次 |
| 最近记录: |