【发布时间】:2019-07-08 12:23:15
【问题描述】:
所以我有一个类似这样的项目设置:
-
myfile.cpp其中包括:fsl_clock.h
myfile 是一个 c++ 文件,fsl_clock.h 是来自 NXP 的纯 C 头文件,可以看到它的一个版本here
我的文件看起来像:
#include "fsl_clock.h"
现在我的文件中确实有更多东西,但我清空了它,直到只剩下这些。
以下是我尝试过的编译结果:
- 使用 arm 交叉编译器
arm-none-eabi-g++可以正常编译。 - 使用主机 (x86Linux) g++ --version
7.3.0-16ubuntu3可以正常工作 - 使用主机 (x86Linux) g++ --version
7.3.0-27ubuntu1~18.04会出现大量奇怪的错误。
我得到的错误是这样的:
device/MIMX8MQ6_cm4.h8856:51: error 'reinterpret_cast<CMM_Type*>(808976384)' is not a constant expression
这行代码是纯C,看起来像:
kCLOCK_RootM4 = (uint32_t)(&(CCM)->ROOT[1].TARGET_ROOT)
其中 CCM 定义为:
#define CCM_BASE (0x30380000u)
#define CCM ((CCM_Type*)CCM_BASE)
所以看起来较新的 g++ 7.3.0-27ubuntu1~18.04(也许是正确的)正在 C 风格包含的头代码中做 c++ 的事情(例如 reinterpret_cast)。较旧的编译器 7.3.0-16ubuntu3 的行为方式不同 - 编译正常。
谁能说出这两种编译器之间的区别是什么以及为什么一种有效而另一种无效?两个编译器 gnu g++ 具有相同的 g++ 版本 7.3.0。但我不太明白 16ubuntu3 与 27ubuntu1~18.04 的后缀以及为什么这可能会改变行为......
注意现在,我知道对于我的主机构建,我真的不想在我的主机构建中包含特定于板的代码,但那是另一回事。我现在更感兴趣的是了解为什么两个编译器之间存在差异。
更新
对于主机构建,编译器行如下所示:
g++ -w -Isource/drivers -Isource/board -Isource/device -m32 -g -std=c++11 -c source/myfile.cpp -o out.o
CMM_Type(必须手动复制它,因为原件埋在 NXP 网站中)看起来像(注意它的缩写,因为要复制的内容太多 - 但它的 uint32_t 结构):
typedef struct {
volatile uint32_t GPR0;
volatile uint32_t GPR0_SET;
struct {
:
} PLL_CTRL[39];
:
struct {
volatile uint32_t TARGET_ROOT;
volatile uint32_t TARGET_ROOT_SET;
volatile uint32_t TARGET_ROOT_CLR;
:
} ROOT[142];
} CCM_Type;
最小示例 - 在线 GDB 我做了一个最小的例子——它不能用在线 GDB 编译,但它确实产生了我在编译器中解释的错误。链接是here
极简 - 魔杖盒 与在线 GDB 示例完全相同的代码,但这实际上显示了我得到的相同错误:here
最小的示例代码
#include <stdint.h>
typedef struct {
struct {
volatile uint32_t TARGET_ROOT;
} ROOT[4];
} CCM_Type;
#define CCM_BASE (0x30380000u)
#define CCM ((CCM_Type *)CCM_BASE)
typedef enum _clock_root_control
{
kCLOCK_RootM4 = (uint32_t)(&(CCM)->ROOT[1].TARGET_ROOT)
} clock_root_control_t;
int main()
{
return 0;
}
【问题讨论】:
-
可能是因为您将 C 代码编译为 C++?
-
各种可能的解释,包括将
unsigned转换为指针并取消引用该指针会产生未定义行为的可能性。如果没有更多信息(例如,CCM_Type是什么,考虑到它的用法暗示它是一种数据结构?)任何试图提供帮助的人都不得不求助于猜测。阅读有关提供minimal reproducible example 的信息 - 一小段演示问题的代码示例,其他人可以使用它来获得相同的症状。这需要付出努力,但会显着提高您获得有用建议的机会。 -
您是否尝试将包含在
#extern "C" {...}中? -
请在此处发布minimal reproducible example,而不是链接。这些链接很有帮助,但还不够。如果您使用 g++ 编译,那么它是 C++ 而不是 C,更不用说 C 中没有
reinterpret_casts。 -
最小示例中的代码不是有效的 C 和无效的 C++。枚举数必须是任一语言中的常量表达式。
(uint32_t)(&(CCM)->ROOT[1].TARGET_ROOT)不是一个。你的编译器没有问题。原包装坏了,需要修理。它依赖于一个不可移植且可能未记录的编译器扩展,没有人承诺永远存在,你瞧,它不再存在了。