views:

731

answers:

6

I would like to compile the following C program for 32- and 64-bit systems.

#include <stdio.h>                                                                                                                                                                  
#include <stdlib.h>                                                                                                                                                                 
#include <stddef.h>                                                                                                                                                                 

int main(int argc, char** argv) {
  size_t size = atoi(argv[1]);                                                                                                                                                      
  int *array;                                                                                                                                                                       

  array = malloc(size * sizeof(int));                                                                                                                                               
  if (array == NULL) {                                                                                                                                                              
    fprintf(stderr, "could not allocate memory\n");                                                                                                                                 
    exit(1);                                                                                                                                                                        
  }                                                                                                                                                                                  
  fprintf(stdout, "memory allocated on heap: %u bytes\n", sizeof(int)*size);                                                                                                        

  fprintf(stdout, "press Return to quit\n");                                                                                                                                        
  getchar();                                                                                                                                                                        

  fprintf(stdout, "freeing memory\n");                                                                                                                                              
  free(array);                                                                                                                                                                      

  exit(0);                                                                                                                                                                          
}

What I have been doing with my Makefile is pass in -m32 and -64 to make bit-specific binaries:

CFLAGS=-ansi -pedantic -Wall -O3
32BIT_ARCH=-m32
64BIT_ARCH=-m64
32_CFLAGS=${32BIT_ARCH} ${CFLAGS}
64_CFLAGS=${64BIT_ARCH} ${CFLAGS}
CC=gcc
ARRAY_32BIT_BINARY_NAME=arrayTest32
ARRAY_64BIT_BINARY_NAME=arrayTest64

all: ${ARRAY_32BIT_BINARY_NAME} ${ARRAY_64BIT_BINARY_NAME}
arrayTest32: main32_array.o 
             ${CC} ${32_CFLAGS} main32_array.o -o ${ARRAY_32BIT_BINARY_NAME}
arrayTest64: main64_array.o
             ${CC} ${64_CFLAGS} main64_array.o -o ${ARRAY_64BIT_BINARY_NAME}
main32_array.o: main.c
             ${CC} ${32_CFLAGS} -c main.c -o main32_array.o 
main64_array.o: main.c
             ${CC} ${64_CFLAGS} -c main.c -o main64_array.o 
clean:
             -rm *.o *~ ${ARRAY_32BIT_BINARY_NAME} ${ARRAY_64BIT_BINARY_NAME}
install:
             cp ${ARRAY_32BIT_BINARY_NAME} ${ARRAY_64BIT_BINARY_NAME} ../bin

This works great, but I run into a warning when compiling:

$ make                                                                                                                                   
gcc -m32 -ansi -pedantic -Wall -O3 -c main.c -o main32_array.o                                                                                                                      
gcc -m32 -ansi -pedantic -Wall -O3 main32_array.o -o arrayTest32                                                                                                                    
gcc -m64 -ansi -pedantic -Wall -O3 -c main.c -o main64_array.o                                                                                                                      
main.c: In function ‘main’:                                                                                                                                                         
main.c:14: warning: format ‘%u’ expects type ‘unsigned int’, but argument 3 has type ‘long unsigned int’                                                                            
gcc -m64 -ansi -pedantic -Wall -O3 main64_array.o -o arrayTest64

What I would like to do is fix this warning without having two main.c files for two "bit" targets.

Is there an #ifndef or other preprocessor conditional I can add to line 14 of main.c to handle this difference?

Or is there a different and better way to handle this?

EDIT: I used the following solution:

#if defined(__LP64__)                                                                                                                                                               
  fprintf(stdout, "memory allocated on heap: %lu bytes\n", sizeof(int)*size);                                                                                                       
#else                                                                                                                                                                               
  fprintf(stdout, "memory allocated on heap: %u bytes\n", sizeof(int)*size);                                                                                                        
#endif

Thanks for your help.

+2  A: 

See here for a similar question.

LP64 _LP64 These macros are defined, with value 1, if (and only if) the compilation is for a target where long int and pointer both use 64-bits and int uses 32-bit.

Onots
A: 

You don't want to have an #ifdef for every line of code that might be different like this - it won't scale.

The issue is that sizeof() returns a 64-bit quantity on 64-bit. One possible fix:

fprintf(stdout, "memory allocated on heap: %u bytes\n", (unsigned int)(sizeof(int)*size));

Provided you know the quantity will always be 32-bits.

Michael
+4  A: 

C99 provides the 'z' modifier for printing size_t values; use that in the format string.

Jonathan Leffler
A: 

The accepted answer is ok if you need to be portable to non-C99 compilers (such as Visual Studio), but since you seem to be using gcc only, I'd strongly suggest to #define __STDC_FORMAT_MACROS and use the PRI* macros, as I've described here. Then you won't have to sprinkle your code with unnecessary #ifdefs every time you need to print a 64-bit integer.

JesperE
A: 

See also: Lesson 10. Pattern 2. Functions with variable number of arguments

Andrey Karpov