Sizeof(float) 在 atmega2560 上给出错误的结果
sizeof(float) giving wrong result on atmega2560
我正在使用atmega2560控制器和avr-g++。我正在调试适用于我的 Ubuntu 18.04 主机(使用 g++ 编译时)但不适用于 atmega2560 的代码。我认为这可能是不同数据类型大小的问题,并使用此代码进行调查(也给出如下):
int integerType;
float floatType;
double doubleType;
char charType;
printf("Size of int: %ld bytesn",sizeof(integerType));
printf("Size of float: %ld bytesn",sizeof(floatType));
printf("Size of double: %ld bytesn",sizeof(doubleType));
printf("Size of char: %ld byten",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:
在 atmega2560 上,整数为 2 个字节。因此,每次对printf
的调用都传递格式字符串,后跟一个 2 字节整数。
但是格式字符串指定%ld
,这是一个 4 字节long
整数;所以printf
期望堆栈上有一个 4 字节的值。因此,它从堆栈中读取未被调用函数推送到那里的字节;这些字节可以具有任何值。
如果您用%lX
以十六进制打印值,您将看到低位两个字节的预期大小。例如,41680900
是0x027C0004
,您可以在该0004
中看到float
的大小。027C
实际上是随机噪声。
要解决此问题,请使用%d
而不是%ld
。这将适用于您的 Ubuntu 主机(使用 4 字节整数)和 atmega2560(使用 2 字节整数)。
也许更好的是使用%z
,正如chux的答案中所解释的那样,以防sizeof
的大小与int
的大小不同。
sizeof
返回一个size_t
- 一些无符号类型。 使用*printf()
时,请使用指定的匹配说明符"zu
"'。
// printf("Size of float: %ld bytesn",sizeof(floatType));
// () not needed with an object
printf("Size of float: %zu bytesn", sizeof floatType);
如果代码使用旧版本,则转换为最广泛的可用类型是另一种选择:
// Assume unsigned long is widest
printf("Size of float: %lu bytesn", (unsigned long) sizeof floatType);
当然,如果预期的结果很小,代码可以使用unsigned
printf("Size of float: %u bytesn", (unsigned) sizeof floatType);
然而,既然这是C++,那么下面呢? @Bob__
cout << "Size of float: " << sizeof floatType << " bytes" << endl;
这是完全不现实的。这可能是什么原因呢?
原因是 avr-gcc/avr-g++ 将size_t
实现为 2 字节类型,请参阅 avr-gcc ABI 中的类型布局,但您使用的是需要long int
的打印修饰符%ld
,这是 avr-g++ 中的 4 字节类型。
什么将在主机和AVR 上工作
-
您可以强制转换 size_t 操作数,使其与 printf 操作数匹配,例如将
%u
与(unsigned) sizeof(float)
一起使用,或将%lu
与(unsigned long) sizeof(float)
一起使用。 -
在使用 GCC 时,有一些内置宏被定义为基本类型的大小,因此它们可以在预处理器指令(如
#if
)中使用。 为了显示它们,您可以运行1> echo "" | avr-g++ -xc++ - -E -dM | grep SIZEOF
这将打印类似的东西
#define __SIZEOF_INT__ 2 #define __SIZEOF_POINTER__ 2 #define __SIZEOF_FLOAT__ 4
缺少的是
。__SIZEOF_CHAR__
每个语言标准始终为 1
什么不适用于 avr-gcc
对像%zu
这样的size_t使用打印修饰符将不起作用2,因为 AVR-LibC 没有实现z
。此决定背后的原因是保持代码大小占用空间最小。
也不起作用的是使用像std::cout << sizeof(float) ...
中的流,因为 GNU 工具中没有用于 AVR 的 libstdc++。
1说明:-E
建议编译器只预处理源文件,-dM
打印所有已定义宏的值。 源文件-
,这意味着从标准输入读取,这是截至echo "" |
的空文件。 选项-xc++
指定要C++的语言,这是必需的,因为输入文件没有文件扩展名。
2例如,64 位类型也没有实现。 为了支持float
,你需要一个支持它的扩展版本的vfprintf。 这通常通过-Wl,-u,vfprintf -lprintf_flt
访问,因为默认版本的 printf(和 scanf)不支持float
。
- 分段错误当我试图运行程序时出错
- .h 和.cpp文件分离时出错,但仅使用 .h 文件时没有错误.我做错了什么?
- 创建 OpenCV 非自由版本 v4.3 时出错,可折叠.cpp错误 C2039、2605
- 制作时出错,C++"db.c:2127:错误:在"||"标记之前应使用";"
- C++语法错误,编译器不会警告或 int v = func(&v) 出错;
- 在VS2015中访问类成员时运行时错误,但在Linux上未访问时出错
- 如何更改路径以修复错误"./main:加载共享库 libmkl_core.so 时出错?
- 为什么在定义类之前声明类的对象会在友元类中给出错误,而在友元函数中不会出错
- 安装 mply 库时出错.致命错误:gsl/gsl_sf.h:没有这样的文件或目录
- Rcpp/C++/R:比较日期时间矢量与日期时间时出错(错误:"运算符>"的不明确重载)
- 编译特征程序时出错:错误:'seq'不是'Eigen'的成员
- 可能的 GCC 链接器错误会导致将弱符号和局部符号链接在一起时出错
- 非标准语法;使用 '&' 创建指向成员的指针错误,将成员函数分配给向量时出错
- 运算符重载时出错(错误:"运算符<<不匹配(操作数类型为"std::basic_ostream<char>"和"const char [2]")
- 编译类 C++ 中的线程时出错(错误 xthread)
- 加载GLEW库时出错(错误LNK2001)
- 通过函数指针调用函数时出错(错误C2064)
- 编译core.obj时出错:错误LNK2001:未解析的外部符号_harmony_core_init
- 链接c++静态库与android ndk时出错(错误:无法识别文件格式)
- 使用GCC编译游戏时出错.(错误:将"Screen"的含义从"class Screen&q