在 32 位处理器 (ARM Cortex A9) 中使用 64 位数据的问题
Posted
技术标签:
【中文标题】在 32 位处理器 (ARM Cortex A9) 中使用 64 位数据的问题【英文标题】:Problem using 64 bit data in 32 bit processor (ARM Cortex A9) 【发布时间】:2019-06-16 16:29:16 【问题描述】:首先,上下文:我正在 ARM Cortex A9 处理器中实现一个程序。我有一个与 C 代码本身相关的问题,在这里解决了:How to set the values of an array to a single variable
首先,我在我的计算机(OS Linux 64 位)中编写了代码,并且上述链接中接受的答案有效。然而,当我在 ARM A9 中做同样的事情时,它没有。我在ARM上做了一个简单的测试:
uint64_t test = 0x1B26B354A1CF;
printf("%lx", test);
打印出来:
d
我的电脑也是这样:
uint64_t test = 0x1B26B354A1CF;
printf("%lx \n", test);
打印:
1b26b354a1cf
所以这似乎是一个溢出问题或处理“大”数据的问题。如何找到解决方法或替代解决方案?
目标:ARTY Z7 FPGA(在这个问题中你可以忽略“FPGA”部分。我只是在使用该板的处理器:ARM A9 CORTEX)
【问题讨论】:
你在使用newlib吗?您是针对嵌入式设备还是填充 linux?xil_printf
是什么?
@KamilCuk 不是我没有使用 newlib。在帖子中添加了“目标设备”。老实说,我不知道什么是 xil_printf,因为我找不到文档。但它在我看到的所有教程和作品中都使用了我现在使用的同一块板。我将其更改为 printf 以避免混淆。我发现的唯一内容是“printf 已缓冲,而 xil_printf 未缓冲”。
检查你的库 printf 是否支持 64 位数字打印。许多人没有。
【参考方案1】:
您的代码中有两个问题:
您不知道在目标平台上使用哪个后缀来定义 uint64_t
文字。
您不知道在printf
中为您的目标平台上的uint64_t
值使用哪个格式说明符。
两者都可以通过using macros defined in stdint.h解决。
特别是定义一个文字并将其分配给一个变量:
uint64_t test = UINT64_C(0x1B26B354A1CF);
在printf
中打印变量的十六进制值:
printf("%" PRIx64 "\n", test);
保证可以在任何适当支持uint64_t
的平台上工作,无论其处理器有多少位。
虽然在大多数情况下语言本身并不要求您为整数文字使用后缀 - 一个值得注意的例外是直接使用文字作为可变参数函数的参数,例如 printf
- 做它在一般情况下明确是一种良好做法,并且可能在安全关键项目的代码指南中是强制性的。例如,MISRA C:2004 指南的规则 10.6 要求对所有无符号常量使用 U
后缀。
【讨论】:
我阅读了该页面,但不知道应该如何使用它们。在那里我看到了数据类型(我已经在使用 uint64_t)和每个数据类型的最大值。您能详细说明如何使用它们吗? C 自动为常量选择足够宽的类型。在这种情况下,缺少后缀不是问题。【参考方案2】:对于普通的printf
(and family),以十六进制打印unsigned long long
(uint64_t
最有可能是)的格式是"%llx"
。注意额外的l
大小前缀。
格式说明符和参数类型不匹配会导致未定义的行为。
最有可能发生的是long
在您的 32 位系统上是 32 位,而在您的家庭系统上是 64 位,这就是为什么它似乎在您的家庭系统上工作。
【讨论】:
你是对的。我刚刚测试了它。所以在 32 位系统中使用 64 位数据应该不会有问题吧?因为我的代码的另一部分有未定义的行为,但也许这是我如何处理数据的另一个问题。 @MiguelDuranDiaz 不,在 32 位系统上使用 64 位数据类型应该没有任何问题。 打印uint64_t
的正确方法不是猜测%llx
可能会起作用,而是包含<inttypes.h>
并使用”%” PRIx64
,如printf("%” PRIx64 “\n", test);
中所示
@EricPostpischil 这就是为什么我赞成 Kit 的答案。我会保留这个,因为它解释了发生的事情。【参考方案3】:
关于定义无符号64位文字的后缀,您可以检查stdint.h
中使用的后缀#define UINT64_MAX
。在我的例子中,如果我的字长为 64,则使用名为 __UINT64_C(c)
的宏将后缀 UL
粘贴到文字之后,如果我的字长为 32,则使用 ULL
粘贴后缀。
【讨论】:
__UINT64_C
不可移植。标准 C 标头定义了UINT64_C
(如果实现支持uint64_t
),因此通常首选。但是,当简单地将常量分配给整数对象时,不需要后缀。 C 会自动为常量选择足够宽的类型。仅当值在类型很重要的上下文中使用时(例如,在移位表达式中),才需要显式类型。
我认为宏是特定于我的平台的,但我没有意识到有一个标准对应物。很高兴知道。我不确定为什么__UINT64_C
不仅仅在我的标题中定义为UINT64_C
,因为它们的定义相同。以上是关于在 32 位处理器 (ARM Cortex A9) 中使用 64 位数据的问题的主要内容,如果未能解决你的问题,请参考以下文章
stm32的arm内核和cortex架构到底是啥意思?有啥区别?求指教!