sizeof(float) 在 atmega2560 上给出错误的结果

sizeof(float) giving wrong result on atmega2560

我正在使用 atmega2560 控制器和 avr-g++。我正在调试适用于我的 Ubuntu 18.04 主机(使用 g++ 编译时)但不适用于 atmega2560 的代码。我认为可能是不同数据类型大小的问题,并使用this代码进行调查(下面也给出):

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));

主机上的结果看起来不错,但 atmega2560 上的 avr-g++ 编译代码给出了不同数据类型的野生大小:

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

这完全不现实。这可能是什么原因?

更新

有人建议我尝试使用 %zu 而不是 %ld 来打印 sizeof(...) 的 std::size_t 输出。不幸的是,这没有用,输出如下所示:

Size of int: Size of float: Size of double: Size of char: 

sizeof returns 一个 size_t - 一些 unsigned 类型。使用*printf()时,使用"zu"`.

的指定匹配说明符
// printf("Size of float: %ld bytes\n",sizeof(floatType));
// () not needed with an object
printf("Size of float: %zu bytes\n", sizeof floatType);

如果代码使用的是旧版本转换为最广泛可用的类型是一种替代方法:

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

当然,如果预期结果很小,代码可以使用 unsigned

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

但是既然是C++,下面的怎么样?

cout << "Size of float: " << sizeof floatType << " bytes" << endl;

在atmega2560上,一个整数是2个字节。因此,您对 printf 的每次调用都会传递格式字符串,后跟一个 2 字节整数。

但格式字符串指定%ld,这是一个4字节的long整数;所以 printf 期望堆栈上有一个 4 字节的值。因此,它从堆栈中读取未被调用函数压入的字节;这些字节可以有任何值。

如果您使用 %lX 打印十六进制值,您会在 low-order 两个字节中看到预期的大小。比如41680900就是0x027C0004,在那个0004里面可以看到一个float的大小。 027C 实际上是随机噪声。

要解决此问题,请使用 %d 而不是 %ld。这将适用于您的 Ubuntu 主机(具有 4 字节整数)和您的 atmega2560(具有 2 字节整数)。

也许更好的方法是使用 %z,如 chux 的回答中所述,以防 sizeof 的大小与 int 的大小不同。