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

#define SIZE_TYPE
#define MEM_SIZE_BYTES  4096
#define MEM_SIZE_WORDS  MEM_SIZE_BYTES/sizeof(int)

int main() {

    printf("bytes are %d\n", MEM_SIZE_BYTES);
    printf("words are %d\n", MEM_SIZE_WORDS);

}

Compilation gives a warning...why?

testintsize.c:11:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]

I found out SIZE_TYPE macro here: https://gcc.gnu.org/onlinedocs/gccint/Type-Layout.html Is that related to this.

Doing this did not cause the warning to go away:

#define SIZE_TYPE int 
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208
  • 2
    The `sizeof` operator returns a value of type `size_t`, which has to be unsigned and big enough to fit all possible sizes on the platform, and on your specific platform is `unsigned long int` for which you need the `"%lu"` format. See e.g [this `printf` reference page](http://en.cppreference.com/w/c/io/fprintf). – Some programmer dude Oct 19 '14 at 05:25
  • What does SIZE_TYPE macro do ? – Ankur Agarwal Oct 19 '14 at 05:34
  • The compiler probably checks for it for the definition of `size_t`. Defining it could cause weird things to happen. – Some programmer dude Oct 19 '14 at 05:38
  • 1
    Unrelated to your problem: please surround any macro that's an expression more complex than a single number or identifier with parens. – Michael Burr Oct 19 '14 at 05:45

3 Answers3

2

You have several different ways to resolve this warning:

Option #1:

#define MEM_SIZE_WORDS MEM_SIZE_BYTES/sizeof(int)      // change this
#define MEM_SIZE_WORDS MEM_SIZE_BYTES/(int)sizeof(int) // to this

Option #2:

#define MEM_SIZE_WORDS MEM_SIZE_BYTES/sizeof(int)        // change this
#define MEM_SIZE_WORDS (int)(MEM_SIZE_BYTES/sizeof(int)) // to this

Option #3:

printf("words are %d\n", MEM_SIZE_WORDS);  // change this
printf("words are %lu\n", MEM_SIZE_WORDS); // to this
barak manos
  • 29,648
  • 10
  • 62
  • 114
2

In this case, sizeof returns an long unsigned int. One way to get around the warning:

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

#define SIZE_TYPE
#define MEM_SIZE_BYTES  4096
int intSize = sizeof(int);
#define MEM_SIZE_WORDS  MEM_SIZE_BYTES/intSize

int main() {

    printf("bytes are %d\n", MEM_SIZE_BYTES);
    printf("words are %d\n", MEM_SIZE_WORDS);

}

intSize is global variable. In some cases, it will not be considered as a best practice. Using a cast to int will be superior (see barak's comment and answer).

Rotem Varon
  • 1,597
  • 1
  • 15
  • 32
  • 1
    This will yield a runtime calculation every time you use `MEM_SIZE_WORDS`. – barak manos Oct 19 '14 at 05:36
  • What is `#define SIZE_TYPE` macro doing here ? – Ankur Agarwal Oct 19 '14 at 05:37
  • Hi @barak, it's been ages since I wrote my last C code. Isn't that the case where MEM_SIZE_BYTES/intSize will be calculated once before compilation by the preprocessor? At that point, MEM_SIZE_WORDS will be simply replaced by the resulting value. That is, no recalculation at runtime. – Rotem Varon Oct 19 '14 at 05:46
  • `intSize` is a variable, the **preprocessor** does not handle variables in C. In c++, if you declare it as `const`, then the **compiler** might replace it with the value of that variable, and then ultimately replace the entire expression with a constant value. – barak manos Oct 19 '14 at 05:58
  • @barak, thanks for the refresher. So, how the code will look like after the preprocessor is done? Will MEM_SIZE_WORDS be replaced with a 4096/intSize? – Rotem Varon Oct 19 '14 at 06:10
  • I believe so, yes. You can always view the dis-assembly if you want to be sure. – barak manos Oct 19 '14 at 06:14
  • -1, this is not an anwer to the question, and gives not a good solution to the problem. – Jens Gustedt Oct 19 '14 at 15:59
1

The sizeof operator returns type size_t which is an unsigned integer type. By C's implicit type conversion rules MEM_SIZE_BYTES/sizeof(int) also has the same type, size_t.

To print a value of that type use %zu as a printf format.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177