0

Was trying to port 32bit to 64bit code I was wondering if there are some standard rules when it comes to porting ?

I have my code compiling in a 64bit environment and now I come across some errors like

cast from pointer to integer of different size [-Werror=pointer-to-int-cast] for

x = (int32_t)y;

And to get of this I use x = (size_t)y; I get rid of the error but is this the correct way. Also in various location I have to cast a variable to (unsigned long long). For example

printf("Total Time   : %5qu\n",time->compile_time

This gives an error error: format '%qu' expects argument of type 'long long unsigned int', but argument 2 has type (XYZ).

to get this fixed i do something like

 printf("Total Time   : %5qu\n",(unsigned long long) time->compile_time

Again is this proper ??

Rags
  • 434
  • 2
  • 6
  • 20
  • 3
    Use `intptr_t` or `uintptr_t` instead of `size_t`. – nonsensickle Nov 06 '13 at 20:33
  • What actual types are `x` and `y`? – kfsone Nov 06 '13 at 20:34
  • 5
    For well-written code, there shouldn't be any need for "porting" at all. –  Nov 06 '13 at 20:34
  • 1
    @H2CO3 Correct but that does not answer his question. He is clearly asking for help in writing "well-written code". – nonsensickle Nov 06 '13 at 20:36
  • @nonsensickle Conversely. It perfectly answers the "Just wondering if someone can guide me here and point me towards correct way of doing things" question. If you think that we should now write an answer that explains each and every detail of writing portable code, that's wrong -- then the question fits into the "too broad" category and as such, it isn't suited for Stack Overflow. –  Nov 06 '13 at 20:38
  • Yea.. that true.. I am porting code that is clearly not well written. – Rags Nov 06 '13 at 20:41
  • Sorry for that broad question. I was guessing someone can point me to blogs where I can read about it. – Rags Nov 06 '13 at 20:42
  • @H2CO3 Ok, it can be understood that way. However, he did give us a particular example to work with, hence not "too broad". Btw, I like how finicky you are! I almost started my previous commend with "we meet again! Dun, dun, dun" – nonsensickle Nov 06 '13 at 20:43
  • 1
    @Rags Here's a short but good hint http://stackoverflow.com/questions/2303516/writing-a-portable-c-program-which-things-to-consider – nonsensickle Nov 06 '13 at 20:45

2 Answers2

2

I think it's safe to assume that y is a pointer in this case.

Instead of size_t you should use intptr_t or uintptr_t.

See size_t vs. uintptr_t.

As for your second cast it depends what you mean by proper?

The usual advice is to avoid casting. However, like all things in programming there is a reason that they are available. When working on an implementation of malloc on an embedded system I had to cast pointers to uintptr_t in order to be able to do the necessary arithmetic on them. This code was tested on a 64 bit PC but ran on a 32 bit micro controller. The fact that I used two architectures was the best way to ensure it was somewhat portable code.

Casting though makes your code dependent on how the underlying type is defined! Just like you noticed with your x = (int32_t)y this line made your code dependent on the fact that a pointer was 32 bits wide.

The only advice I can give you is to know your types. If you want to cast, it is ok (so long as you can't make your variable of the correct type to begin with) but it may reduce your portability unless you choose the "correct" type to cast to.

The same goes for the printf cast. If I was you, I would read the definition of %5qu thoroughly first (this may help). Then I would attempt to use an appropriately typed variable (or conversely a different format string) and only if that failed would I resort to a cast.

I have never used %qu but I would interpret it as a 64 bit unsigned int so I would try using uint64_t (because long long is not guaranteed to be 64 bits across all platforms). Although by what I read on Wikipedia the q specifier is platform specific to begin with so it might be wise to change it.

Any more than this and the question becomes too broad (it's good that we stuck to specific examples). If you get stuck, come back with individual types that you want to check and ask questions only about them.

Community
  • 1
  • 1
nonsensickle
  • 4,438
  • 2
  • 34
  • 61
  • For the `[u]intptr_t` types there are specific [constants](https://en.cppreference.com/w/c/types/integer#Format_constants_for_the_fprintf_family_of_functions) defined to assure correct format strings – ugly to use, admitted, but they are guaranteed to work. – Aconcagua Feb 14 '23 at 11:43
1

Was it Stroustrup that said they call it a 'cast' because it props up something that's broken ? ;-)

 x = (int32_t) y;

In this case you are using an exact width type, so it really depends on what x and y are. The error message suggest that y is a pointer. A pointer is not an int32_t, so the real question is why is y being assigned to x ... it may indicate a potential problem. Casting it away may just cover the problem so that it bites you at run-time rather than compile-time. Figure out what the code thinks it's doing and "re-jigger" the types to fit the code. The reason the error goes away when you use a (size_t) cast is that likely the pointer is 64 bits and size_t is 64 bits, but you could consider that a simple form of random casting luck. The same is true when casting to (unsigned long long). Don't assume that an int is 32 or 64 bits and don't using casting as a porting tool ... it will get you in trouble. It's tough to be more specific based on a single line of code. If you want to post a < 25 line function that has issues; more specific advice may be available.

Dweeberly
  • 4,668
  • 2
  • 22
  • 41