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
的大小不同。
我正在使用 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
的大小不同。