如何将宏用于无符号长数字

how to use macro for a unsigned long number?

本文关键字:无符号 数字 用于      更新时间:2023-10-16

这是我的代码:

#define MSK 0x0F
#define UNT 1
#define N 3000000000
unsigned char aln[1+N];
unsigned char pileup[1+N];
void set(unsigned long i)
{
    if ((aln[i] & MSK) != MSK ) {
        aln[i] += UNT;
    }
}
int main(void) {}

当我尝试编译它时,编译器抱怨如下:

 tmp/ccJ4IgSa.o: In function `set':
 bitmacs.c:(.text+0xf): relocation truncated to fit: R_X86_64_32S against symbol `aln' defined in COMMON 
 section in /tmp/ccJ4IgSa.o
  bitmacs.c:(.text+0x29): relocation truncated to fit: R_X86_64_32S against symbol `aln' defined in COMMON
 section in /tmp/ccJ4IgSa.o
 bitmacs.c:(.text+0x32): relocation truncated to fit: R_X86_64_32S against symbol `aln' defined in COMMON
  section in /tmp/ccJ4IgSa.o

我认为原因可能是N太大,因为如果我将 N 更改为 20000000000,它可以成功编译。但是我需要 3000000000 作为 N 的值。

有人对此有想法吗?

根据你最初的问题:使用整数文字后缀UL(或类似)来强制存储类型N:

#define N 3000000000UL

然而,(根据你对HLundvall答案的评论)relocation truncated to fit错误显然不是由于这个 - 它可能(正如Mystical和Matt Lacey所说)太大而无法适应该细分市场。


顺便说一句,如果你问一个单独的问题来解释你想用你的大数组完成什么,有人可能会提出一个更好的解决方案(更有可能适合内存)。

例如:

  • 您的示例代码仅使用所示代码中每个字节的低半字节:您可以将其打包成一半的大小(诚然,这仍然太大了)
  • 根据您的访问模式,您可能能够将阵列保留在磁盘上并在内存中缓存工作子集
  • 如果我们知道您需要什么,可能会有更好的整体算法和数据结构

撇开数字文字不是正确类型的"形式"问题(有关正确的语法,请参阅其他答案),这里的关键点是分配 3 GB 静态/全局数组是一个非常糟糕的主意。

大多数平台上的 static 和全局1 变量都是直接从可执行映像映射的,这意味着可执行文件必须大到 3 GB,即使对于当前标准来说也是相当大的。即使在某些平台上可能会取消此限制(请参阅评论),您也无法控制如何处理分配失败。

最重要的是,全局变量不适用于这么大的东西,你可能会发现链接器(例如你找到的链接器)和加载器施加的任意限制的问题。相反,您应该使用 mallocnew 或某些特定于平台的函数分配堆上大于几 KB 的任何内容,在运行时优雅地处理可能的故障。

不过,请记住,对于在几乎任何 32 位操作系统下运行的应用程序,不可能按照您的请求获得 3 GB 的连续内存,并且如果不诉诸特定于平台的技巧(例如,在给定时刻仅映射内存中数组的特定部分),就不可能完全获得多个这些数组(=超过 4 GB 的连续内存)。

另外,您确定自程序开始运行以来确实需要所有连续内存吗?难道没有一些更好的数据结构/算法可以避免分配所有内存吗?

<小时 />
  1. 通常,标准调用具有静态存储持续时间的变量。

要输入类型为无符号长使用的数字常量:

#define N 3000000000UL

问题是 gcc(默认情况下)使用 pc 相对访问来获取x86_64目标上静态数据对象的地址,并且这些访问限制为最大 2^31 字节。 因此,如果符号最终放置在距离访问它的代码超过 2GB 的位置,当它尝试使用太大而无法容纳指令中允许的 32 位空间的偏移量时,您最终会收到此链接错误。

您可以通过使用 gcc 的-mcmodel=large选项来避免此问题。 这告诉它不要假设它可以使用 32 位 PC 相对偏移量来访问符号(以及其他内容)

请注意,常量文本

的类型后缀大多是无关紧要的——对于 int 来说太大的常量文本将自动变成没有任何后缀的长整型(如果需要,甚至长长)。 请参阅 C99 规范的 6.4.4.1.5。

您的可执行文件正在尝试将内存中的对象放在超过 4GB 标记的内存中,这是不允许的。请参阅此链接:http://www.technovelty.org/code/c/relocation-truncated.html。

来自文章:"如果你看到这个并且你没有手动编码,你可能想看看 -mmodel 参数到 gcc。