0

I wrote the following code in Nano from the Linux command line to get errors when compiling:

Warnings when compiling

I'd like to know what I need to change in my code to make it compile properly. I am trying to get the number of bits in each data type listed to print on a single line.

#include<stdio.h>

int main(void){
    char A;
    unsigned char B;
    int a;
    unsigned int b;
    long c;
    unsigned long d;
    float e;
    double f;
    long double g;

    printf(
        "%c %c %i %u %li %lu %f %lf %Lf\n",
         sizeof(char), sizeof(unsigned char),
         sizeof(int), sizeof(unsigned int),
         sizeof(long), sizeof(unsigned long),
         sizeof(float), sizeof(double), sizeof(long double)
    );

    return 0;
}
  • Use `%zu` instead of `%whatever` in the `printf`. Its arguments are not their respective types, rather `size_t`, because `sizeof` returns the `size_t` type. – zbw May 17 '17 at 01:40
  • 1
    @zbw That would make a nice answer, with some links and a fixed version of the relevant code. –  May 17 '17 at 01:43
  • Looking for similar questions, I found [this one](http://stackoverflow.com/questions/5943840/how-do-i-print-the-size-of-int-in-c) with a very good explanation. I wouldn't be able to give a better answer, so I'll just provide the link. – zbw May 17 '17 at 01:48
  • Also, `sizeof` returns the number of bytes, which is generally more useful than the number of bits. Multiply by 8 to get the number of bits – zbw May 17 '17 at 01:50
  • @zbw The `char` type is not 8 bits on every machine. For portability, multiply by `CHAR_BIT` from ``. –  May 17 '17 at 01:51
  • @InternetAussie I agree, though 8 (the [POSIX-specified char size](http://stackoverflow.com/a/2098444)) would work too, as he's on linux. – zbw May 17 '17 at 02:04
  • 1
    @zbw: `8` will almost certainly work, but `CHAR_BIT` is clearer. (Suppose you have some other value in the program that happens to be `8`, and you want to change it to `16`. It's a lot easier to make the change if you don't have too many irrelevant occurrences of `8`. Magic numbers are best avoided. – Keith Thompson May 17 '17 at 02:14

2 Answers2

2

The sizeof operator returns an integer of type size_t, so you should use the appropriate printf format specifier ("%zu") (assuming C99):

printf(
    "%zu %zu %zu %zu %zu %zu %zu %zu %zu\n",
     sizeof(char), sizeof(unsigned char),
     sizeof(int), sizeof(unsigned int),
     sizeof(long), sizeof(unsigned long),
     sizeof(float), sizeof(double), sizeof(long double)
);

However, this prints the number of bytes in each type. If you want the number of bits in each type, include <limits.h> and multiply each result by CHAR_BIT to get that:

#include <limits.h>

/* ... */

printf(
    "%zu %zu %zu %zu %zu %zu %zu %zu %zu\n",
     sizeof(char) * CHAR_BIT, sizeof(unsigned char) * CHAR_BIT,
     sizeof(int) * CHAR_BIT, sizeof(unsigned int) * CHAR_BIT,
     sizeof(long) * CHAR_BIT, sizeof(unsigned long) * CHAR_BIT,
     sizeof(float) * CHAR_BIT, sizeof(double) * CHAR_BIT, sizeof(long double) * CHAR_BIT
);

IMO, it would look much clearer if you label what you're printing and print each value on its own line, like this:

printf("Number of bits in char = %zu\n", sizeof(char) * CHAR_BIT);
printf("Number of bits in unsigned char = %zu\n", sizeof(unsigned char) * CHAR_BIT);
printf("Number of bits in int = %zu\n", sizeof(int) * CHAR_BIT);
printf("Number of bits in unsigned int = %zu\n", sizeof(unsigned int) * CHAR_BIT);
printf("Number of bits in long = %zu\n", sizeof(long) * CHAR_BIT);
printf("Number of bits in unsigned long = %zu\n", sizeof(unsigned long) * CHAR_BIT);
printf("Number of bits in float = %zu\n", sizeof(float) * CHAR_BIT);
printf("Number of bits in double = %zu\n", sizeof(double) * CHAR_BIT);
printf("Number of bits in long double = %zu\n", sizeof(long double) * CHAR_BIT);

And that can be reduced with a macro (though macros aren't the best, they are useful for repetitive code):

#define PRINT_BITS_IN_TYPE(type) \
    printf("Number of bits in " #type " = %zu\n", sizeof(type) * CHAR_BIT)

PRINT_BITS_IN_TYPE(char);
PRINT_BITS_IN_TYPE(unsigned char);
PRINT_BITS_IN_TYPE(int);
PRINT_BITS_IN_TYPE(unsigned int);
PRINT_BITS_IN_TYPE(long);
PRINT_BITS_IN_TYPE(unsigned long);
PRINT_BITS_IN_TYPE(float);
PRINT_BITS_IN_TYPE(double);
PRINT_BITS_IN_TYPE(long double);
  • Thank you InternetAussie. I'm not quite at a level to use macros so I'll look back at this when I get there. However, I also found I could use %lu rather than %zu. I got this from the web, "%lu format specifier, which prints a unsigned long integer type. I chose this format because on my 64-bit machine sizeof outputs an unsigned long (storage size can only be positive). If you are using a 32-bit operating system, you might need to use “%u” instead of “%lu”. The compiler will complain if you have the wrong format." –  May 17 '17 at 02:29
  • @NickAdoyot "The compiler will complain if you have the wrong format" --> the compiler is not required to complain. The best approach uses `"%zu"`. Use `"%lu"` and the person who needs to maintain your code will mutter evil thoughts. – chux - Reinstate Monica May 17 '17 at 02:37
  • @InternetAussie Thanks again for your assistance. –  Jun 21 '17 at 01:37
0

This is because the unsigned char is promoted to an int (in normal C implementations), so an int is passed to printf for the specifier %c. However, %c expects an unsigned int, so the types do not match, and the C standard does not define the behavior. you can perform the following methods: 1) try using C11(standard version). 2) try using %zu.

Madhur Yadav
  • 635
  • 1
  • 11
  • 30
  • "However, %c expects an unsigned int," --> Not quite. `"%c"` expects an `int`. The value is converted to `unsigned char` and the corresponding character is printed. The behavior is defined. – chux - Reinstate Monica May 17 '17 at 02:35