-1

I'm working with the atmega2560 controller and avr-g++. I'm debugging code that works on my Ubuntu 18.04 host (when compiled with g++) but not on the atmega2560. I thought it might be a problem of different data type sizes, and used this code to investigate (also given below):

int integerType;
float floatType;
double doubleType;
char charType;

printf("Size of int: %ld bytes\n",sizeof(integerType));
printf("Size of float: %ld bytes\n",sizeof(floatType));
printf("Size of double: %ld bytes\n",sizeof(doubleType));
printf("Size of char: %ld byte\n",sizeof(charType));

The results on the host look ok but the avr-g++ compiled code on atmega2560 gives wild sizes for the different data types:

g++:

Size of int: 4 bytes
Size of float: 4 bytes
Size of double: 8 bytes
Size of char: 1 byte

avr-g++:

Size of int: 2 bytes
Size of float: 41680900 bytes
Size of double: 43253764 bytes
Size of char: 44957697 byte

which is completely unrealistic. What could be the reason for this?

update

It was suggested that I try %zu instead of %ld to print the std::size_t outputs from sizeof(...). This, unfortunately, didn't work, and the output looks as follows:

Size of int: Size of float: Size of double: Size of char: 
borizzzzz
  • 592
  • 1
  • 5
  • 16
  • 1
    According to [this](https://stackoverflow.com/a/5943869/10411602) answer, the correct specifier is `%zu`. Perhaps that's the issue. – Blaze Jun 27 '19 at 09:27
  • Thanks for the comment, @Blaze! Didn't work for me, unfortunately but I'll add it as an update. – borizzzzz Jun 27 '19 at 09:36
  • `sizeof` doesn't return a long. Your code is incorrect. – user207421 Jun 27 '19 at 09:42
  • @user207421, thanks for pointing that out. I also tried %lu which seems to be the usual way to cast size_t for printf (a myriad of hits on stack overflow), but it gave me the same output as in my question. I decided to leave the code as I found it on the linked website to avoid confusion. – borizzzzz Jun 27 '19 at 09:51
  • 1
    If you have a doubt on the return type, you can try `std::cout << sizeof(.) << "\n"` – Damien Jun 27 '19 at 10:01
  • 1
    There is no place for `l` in that format expression. I seem to have already alluded to that. Also `sizeof` is an operator, not a function: it doesn't need the parentheses. – user207421 Jun 27 '19 at 10:03
  • 1
    It seems that `sizeof()` return `unsigned int`s on avr-g++, not `unsigned long`s. So, if you remove `l` you will see correct results. – sklott Jun 27 '19 at 10:42
  • 4
    Well, you can always use an ugly cast: `printf("Size of float: %d bytes\n", (int)sizeof(float));`, but why aren't you using `std::cout`? – Bob__ Jun 27 '19 at 12:43
  • @user207421 and sklott, you were right. Removing the 'l' did the trick and now the data type sizes get printed correctly. Thank you for the help! – borizzzzz Jun 27 '19 at 20:11

2 Answers2

2

On the atmega2560, an integer is 2 bytes. So each of your calls to printf is passing the format string, followed by a 2-byte integer.

But the format string specifies %ld, which is a 4-byte long integer; so printf is expecting a 4-byte value on the stack. It is therefore reading bytes from the stack that weren't pushed there by the calling function; these bytes could have any value whatsoever.

If you had printed the values in hexadecimal with %lX, you would have seen the expected size in the low-order two bytes. For example, 41680900 is 0x027C0004, and you can see the size of a float in that 0004. The 027C is effectively random noise.

To fix this, use %d instead of %ld. This will work on your Ubuntu host (with 4-byte integers) and your atmega2560 (with 2-byte integers).

Perhaps even better is to use %z, as explained in chux's answer, in case the size of a sizeof is not the same as the size of an int.

TonyK
  • 16,301
  • 4
  • 33
  • 70
1

sizeof returns a size_t - some unsigned type. When using *printf(), use the specified matching specifier of "zu"`.

// printf("Size of float: %ld bytes\n",sizeof(floatType));
// () not needed with an object
printf("Size of float: %zu bytes\n", sizeof floatType);

If code is using an old version casting to the widest available type is an alternative:

// Assume unsigned long is widest
printf("Size of float: %lu bytes\n", (unsigned long) sizeof floatType);

Of course with small result expected, code could use unsigned

printf("Size of float: %u bytes\n", (unsigned) sizeof floatType);

Yet since this is C++, how about the following? @Bob__

cout << "Size of float: " << sizeof floatType << " bytes" << endl;
chux - Reinstate Monica
  • 127,356
  • 13
  • 118
  • 231