0

Folks I am trying to understand if there is any thing in the following piece of code that will cause it to fail on 64 bit platforms. My main concern is whether some type conversions are happening that are not suitable for 64 bit. Do not pay too much attention on the actual numbers assigned to the variables as i made them up just for this example. My main concern is the type conversion issues happening between long and int and size_t and any other issues you may see.

#define NL_AREA 40      
#define NS_AREA 38     
#define NB_EXTRA (1536 - NS_AREA * NL_AREA) 

main()
{
    long int  bufsize;
    int       obssize, nelm, nbuf;
    int ncol, ndet = 10;
    void      *result;

    obssize = xxx; /* some size */
    bufsize = (long)obssize * (NL_AREA * NS_AREA + NB_EXTRA);
    ncol = 50;
    nbuf = ncol * ndet;
    nelm = 1;
    result = Buf_Init(bufsize, nelm, nbuf);
}

void * 
Buf_Init( size_t elm_size, 
          int    nelm_buf, 
          long   nbuf )
{
    long buf_size;
    void *p;
    buf_size = ((long) elm_size) * nelm_buf;
    if ((p = (void *)malloc(buf_size)) == NULL)
      return NULL;
    else
      return p;
}
srsci
  • 239
  • 5
  • 10
  • It looks OK but you should stick to `size_t` for all your size-related variables (i.e. don't use `long` for this). You can then get rid of a lot of useless and potentially dangerous casts. Also don't cast the result of `malloc`. – Paul R Mar 20 '14 at 14:52
  • 1
    Casting the return of malloc to a `void *` is the same as creating a `int x = some_literal;` and then `int y = (int)x;`. It doesn't make any sense to cast something from one type to the same type. – ciphermagi Mar 20 '14 at 14:55
  • 1
    More on casting the result of `malloc`: http://stackoverflow.com/q/605845/10077 – Fred Larson Mar 20 '14 at 15:00
  • Is this type casting issue valid for calloc too? – srsci Mar 20 '14 at 15:13
  • Yes, in C you should not cast the result of functions that return `void *`. C++ is a different story however. – Paul R Mar 20 '14 at 17:18

1 Answers1

1

I could comment on type conversions, but... why ponder about unexpected type conversions in your code when you can avoid them completely? If portability is important, then don't use the default primitive data types. Use stdint.h instead.

  • Swap int for int32_t.
  • Swap long for int32_t.
  • Keep size_t as it is, or swap it for uint32_t in case it matters. Most likely it does not.

And suddenly the code turned 100% portable.

Other comments:

  • Why would you do (void *)malloc(buf_size)? Casting from void* to void* doesn't make any sense.
  • For a hosted system, main() must always return int. Implicit int has been removed from the C language 15 years ago.
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for the type comment. Do you mean replace both `int and long` with `int32_t`? The issue with main() is okay. I am aware of that, forgot to put the `int` return type here in hurry. – srsci Mar 20 '14 at 15:01
  • @srsci That depends on what you use the variable for. If it is for checking the return value of a standard C function then you should use the specified return type for that function. – Klas Lindbäck Mar 20 '14 at 15:18
  • using fix widthed ints is not always advisable. for example if some library functions interface is int you may run into trouble if compiling on different platforms – vlad_tepesch Mar 20 '14 at 16:35
  • @vlad_tepesch I would rephrase that as: using libraries that are poorly written and non-portable is not advisable. Using `int` etc in C, is almost always bad practice in any kind of system from 8-bit MCUs to 64-bit PCs. There exists very few cases where you as a programmer want an int and don't care about how large it is. – Lundin Mar 21 '14 at 07:52
  • @Lundin i wouldn't completely agree with this. using fixed size types may result in performance loss. if you have a pure 32bit system it may be more performant to use int32 even if you just need 16bit. if you leave the descision which type to use to the compiler (using just int) your code may run faster on both, 16bit machines and 32bit machines. – vlad_tepesch Mar 21 '14 at 10:03
  • @vlad_tepesch No, they will not result in a performance loss. Use `uint_fast32_t`. – Lundin Mar 21 '14 at 10:07
  • @Lundin No? On some architectures using uint16_t instead of uint32_t will cause performance lose. you can't deny this. but ok i agree that uint16_fast_t would be the right choice (but that is not a fixed size type). – vlad_tepesch Mar 21 '14 at 10:12