我拿到了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
应该让我做算术吧?我可以将其替换为实际数字,它可以工作,但随后会变得混乱。无论如何,它在我的Mac上都能正常工作。我必须在Linux上指定GCC中的某些选项(-std
= c1x除外,在Mac上也不需要)?
C语言要求静态对象的初始化程序为常量表达式。(由于静态对象的初始化发生在main
开始之前,所以没有地方进行任何运行时评估。)
const
尽管单词显然是相关的,但C的关键字并不表示“常量”。甲 常量表达式
是一个,可以是,在某些情况下,必须在编译时,评价。const
表示只读。例如,在块作用域内(在函数定义内),这是:
const int r = rand();
是完全合法的。显然,初始化器无法在编译时求值;在const
那只是意味着r
可能没有后进行修改一直initalized。
当你写:
const unsigned long long LATITUDE = (long) 3600000;
引用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;
}
}
使用带有选项的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.
使用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.
因此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);
(long)
前两个声明中的强制转换没有用。常量3600000
和1810000
是(可能是)类型int
。您将它们转换为long
,然后使用结果初始化类型的对象unsigned long long
。只需删除强制类型转换;或者,如果您想更明确一些,则添加一个ULL
后缀以使这些常量生效unsigned long long
:
const unsigned long long LATITUDE = 3600000ULL;
const unsigned long long LONGITUDE = 1810000ULL;
问题出在第三个声明中,该声明引用LATITUDE
和LONGITUDE
,这两个声明都不是常量表达式。不幸的是,C除了定义整数类型的命名常量之外,没有提供一种好方法int
(您可以(将)enum
html" target="_blank">功能用于int
常量)。替代方法是使用宏。这有效:
#define LATITUDE 3600000ULL
#define LONGITUDE 1810000ULL
const unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1);
如果您需要MAX_COORDINATES_NUMBER
成为一个常量表达式,也可以使其成为一个宏:
#define LATITUDE 3600000ULL
#define LONGITUDE 1810000ULL
#define MAX_COORDINATES_NUMBER ((LATITUDE-1) + LATITUDE*(LONGITUDE-1))
(MAX_COORDINATES_NUMBER
在较大的表达式中使用时,需要使用多余的括号来避免运算符优先级问题。)
在我更好地学习Java的过程中,我一直试图理解异常处理。我不明白为什么下面的代码不能编译。 编译器消息为:
问题内容: 行给出了编译错误。 为何不允许这样做的任何特定原因?如何使用数组常量初始化String数组? 编辑:谢谢大家的回答。现在,我很清楚什么是允许的,什么是不允许的。但是我能问你 为什么 不允许这样做吗? 仔细搜索一下之后,我发现了这个链接,在其中,被告知像这样的编码使编译器不明确- 宠物应该是String数组还是Objects数组。但是,从声明中可以很好地看出它是一个String数组,对吗
当我使用带VS2015的英特尔C编译器编译发行版时,它将失败。但是当我编译调试版本时,它就工作了。我不明白发生了什么。配置是否有一些错误?错误列表如下所示。我该怎么做? --编辑-- 今天,我比较了每个选项的调试版本和发布版本之间的配置,我最终发现如果我将过程间优化设置为no或单文件(/Qip),它是有效的。但是如果我把过程间优化设置为多文件(/Qipo),就不行了。另外,我在intel C编译器
我有一个问题编译以下漏洞代码: http://downloads.securityfocus.com/vulnerabilities/exploits/59846-1.c 我使用的是"gcc file. c"和"gcc-O2 file. c",但是这两个文件都会导致以下错误: 我试着在Kali Linux和Ubuntu上编译它们
我有一个爪哇项目。它由以下层次结构组成: 项目: < li >服务器(包含server.java) < li >客户端(包含client.java) < li >协议(包含中的消息类型。java文件) 我正在用Eclipse运行这个项目。我已经到了需要用终端测试的地步。我如何使用 build.xml 文件来格式化它,以便每当我将其从 Eclipse 中取出并在服务器中运行时,它都能正常工作,但在上
异常堆栈跟踪 eclipse.buildid=4.6.2.m20161124-1400 java.version=1.8.0_121 java.vendor=Oracle Corporation BootLoader常量:OS=win32,arch=x86_64,ws=win32,nl=en_us框架参数:-product org.eclipse.epp.package.jee.product命令