Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use macro for a unsigned long number?

Tags:

c++

c

macros

Here're my codes:

#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) {}

When I try to compile it, the compiler complains like this:

 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

I think the reason may be the N is too big, because it can compile successfully if I change N to 2000000000. But I need 3000000000 as the value of N..

Anyone has idea about that?

like image 315
Hanfei Sun Avatar asked Aug 15 '12 23:08

Hanfei Sun


2 Answers

Per your original question: use the integer literal suffix UL (or similar) to force the storage type of N:

#define N 3000000000UL

However, (per your comment on HLundvall's answer) the relocation truncated to fit error obviously isn't due to this - it may (as Mystical and Matt Lacey say) simply be too big to fit in the segment.


As an aside, if you ask a seperate question explaining what you're trying to accomplish with your huge arrays, someone may be able to suggest a better solution (that is more likely to fit in memory)

For example:

  • your sample code is only using the low nibble of each byte in the code shown: you could pack this into half the size (which is admittedly still much too large)
  • depending on your access patterns, you might be able to keep the array on disk and cache a working subset in memory
  • there may be better overall algorithms and data structures if we knew what you needed
like image 108
Useless Avatar answered Sep 29 '22 06:09

Useless


Disregarding the "formal" problem that your numeric literal isn't of the correct type (see the other answers for the correct syntax), the key point here is that it's a very bad idea to allocate a 3 GB static/global array.

static and global1 variables on most platforms are mapped directly from the executable image, which means that your executable would have to be as big as 3 GB, which is quite big even for current day standards. Even if on some platforms this limitation may be lifted (see the comments), you don't have any control on how to handle the failure of allocation.

Most importantly, global variables are not intended for such big stuff, and you are likely to find problems with arbitrary limits imposed by the linker (such as the one you found) and the loader. Instead, you should allocate anything that's bigger than a few KBs on the heap, using malloc, new or some platform-specific function, handling gracefully the possible failure at runtime.

Still, keep in mind that for an application running under almost any 32 bit operating system it's not possible to get 3 GB of contiguous memory as you request, and it's impossible altogether to get more than one of these arrays (=more than 4 GB of contiguous memory) without resorting to platform-specific tricks (e.g. mapping only specific parts of the arrays in memory at a given moment).

Also, are you sure that you do need all that contiguous memory since your program starts to run? Isn't there some better data structure/algorithm that could avoid allocating all that memory?


  1. In general, what the standard calls variables with static storage duration.
like image 33
Matteo Italia Avatar answered Sep 29 '22 07:09

Matteo Italia