应该 C++嵌入式应用程序使用带有 typedef 的通用标头来实现内置 C++类型?
我的常见做法是避免直接使用内置类型,而是包含一个 standardtypes.h,其中包含以下项目:
// \Common\standardtypes.h
typedef double Float64_T;
typedef int SInt32_T;
几乎所有组件和源文件都依赖于此标头,但有些人认为需要抽象出以下内容的大小:类型(实际上不需要)。
这是一个好的实践吗(特别是在大型组件化系统中)?有更好的选择吗?还是应该直接使用内置类型?
It's common practice where I work to avoid directly using built-in types and instead include a standardtypes.h that has items like:
// \Common\standardtypes.h
typedef double Float64_T;
typedef int SInt32_T;
Almost all components and source files become dependent on this header, but some people argue that it's needed to abstract the size of the types (in practice this hasn't been needed).
Is this a good practice (especially in large-componentized systems)? Are there better alternatives? Or should the built-in types be used directly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这种方法的最大问题是,如此多的开发人员这样做,如果您使用第三方库,您可能最终会遇到符号名称冲突,或者同一类型有多个名称。在必要时坚持使用 C99 的 stdint.h 提供的标准实现是明智的。
如果您的编译器不提供此标头(例如 VC++),请创建一个符合该标准的标头。例如,可以在 https://github.com/chemeris/msinttypes 找到 VC++ 版本/blob/master/stdint.h
在您的示例中,我看不到定义特定于大小的浮点类型的意义,因为这些类型通常与目标的 FP 硬件和所使用的表示形式紧密耦合。此外,浮点值的范围和精度由指数宽度和有效宽度的组合确定,因此整体宽度本身并不能告诉您太多信息,也不能保证跨平台的兼容性。对于单精度和双精度,跨平台的可变性要小得多,其中大多数使用 IEEE-754 表示形式。在一些8位编译器上float和double都是32位,而x86 GCC上的long double是80位,但在VC++中只有64位。 x86 FPU 在硬件中支持 80 位(2)。
The biggest problem with this approach is that so many developers do it that if you use a third-party library you are likely to end up with a symbol name conflict, or multiple names for the same types. It would be wise where necessary to stick to the standard implementation provided by C99's stdint.h.
If your compiler does not provide this header (as for example VC++), then create one that conforms to that standard. One for VC++ for example can be found at https://github.com/chemeris/msinttypes/blob/master/stdint.h
In your example I can see little point for defining size specific floating-point types, since these are usually tightly coupled to the FP hardware of the target and the representation used. Also the range and precision of a floating point value is determined by the combination of exponent width and significant width, so the overall width alone does not tell you much, or guarantee compatibility across platforms. With respect to single and double precision, there is far less variability across platforms, most of which use IEEE-754 representations. On some 8 bit compilers float and double are both 32-bit, while long double on x86 GCC is 80 bits, but only 64 bits in VC++. The x86 FPU supports 80 bits in hardware (2).
我认为这不是一个好的做法。好的做法是在您确实需要 32 位无符号整数的情况下使用类似 uint32_t 的东西,如果您不需要特定范围,则仅使用 无符号。
I think it's not a good practice. Good practice is to use something like uint32_t where you really need 32-bit unsigned integer and if you don't need a particular range use just unsigned.
如果您正在编写跨平台代码,那么本机类型的大小可能因系统而异,这可能很重要。例如,wchar_t 类型可以从 8 位到 32 位不等,具体取决于系统。
然而,就我个人而言,我认为您所描述的方法并不像其支持者所建议的那样实用。即使对于跨平台系统,我也不会使用这种方法。例如,我宁愿构建我的系统来直接使用 wchar_t,并简单地编写代码,并意识到 wchar_t 的大小将根据平台而变化。我相信这更有价值。
It might matter if you are making cross-platform code, where the size of native types can vary from system to system. For example, the wchar_t type can vary from 8 bits to 32 bits, depending on the system.
Personally, however, I don't think the approach you describe is as practical as its proponents may suggest. I would not use that approach, even for a cross-platform system. For example, I'd rather build my system to use wchar_t directly, and simply write the code with an awareness that the size of wchar_t will vary depending on platform. I believe that is FAR more valuable.
正如其他人所说,使用 stdint.h 中定义的标准类型。我不同意那些说只在某些地方使用它们的人。当您使用单个处理器时,这可以正常工作。但是,当您的项目使用多种处理器类型(例如 ARM、PIC、8051、DSP)(这在嵌入式项目中并不罕见)时,需要跟踪 int 的含义或能够将代码从一个处理器复制到另一个处理器要求您使用固定大小的类型定义。
至少它对我来说是必需的,因为在过去的六个月里,我为各种项目编写了 8051、PIC18、PIC32、ARM 和 x86 代码,并且我无法跟踪所有差异而不搞砸某个地方。
As others have said, use the standard types as defined in stdint.h. I disagree with those who say to only use them in some places. That works okay when you work with a single processor. But when you have a project which uses multiple processor types (e.g. ARM, PIC, 8051, DSP) (which is not uncommon in embedded projects) keeping track of what an int means or being able to copy code from one processor to the other almost requires you to use fixed size type definitions.
At least it is required for me, since in the last six months I worked on 8051, PIC18, PIC32, ARM, and x86 code for various projects and I can't keep track of all the differences without screwing up somewhere.
您可以在头文件中使用现代 C 和 C++ 实现中可用的标准化版本: stdint.h
它具有类似的类型:uint8_t、int32_t 等。
一般来说,这是保护代码免受平台依赖性的好方法。即使您迄今为止还没有遇到过需要它的情况,它肯定会使代码更容易解释,因为人们不需要像“int”或“long”那样猜测存储大小,它们的大小会随平台。
You can use the standardized versions available in modern C and C++ implementations in the header file: stdint.h
It has types of the like: uint8_t, int32_t, etc.
In general this is a good way to protect code against platform dependency. Even if you haven't experienced a need for it to date, it certainly makes the code easier to interpret since one doesn't need to guess a storage size as you would for 'int' or 'long' which will vary in size with platform.
最好使用 stdint.h et al 中定义的标准 POSIX 类型,例如
uint8_t
、int32_t
等。不确定是否有 C++ 的一部分,但它们在 C99 中。It would probably be better to use the standard POSIX types defined in stdint.h et al, e.g.
uint8_t
,int32_t
, etc. I'm not sure if there are part of C++ yet but they are in C99.因为还没有说,即使您已经接受了答案:
仅当您需要具体大小的类型时才使用具体大小的类型。大多数情况下,这意味着当您保存数据时,如果您直接与硬件交互,或者使用需要具体大小类型的其他代码(例如网络堆栈)。大多数时候,您应该只使用抽象大小的类型,以便编译器可以更智能地优化,并且代码的未来读者不会受到无用细节的负担(例如循环计数器的大小和符号)。
(正如其他几个回复所说,在编写新代码而不是与旧代码交互时,请使用 stdint.h,而不是自制程序。)
Since it hasn't been said yet, and even though you've already accepted an answer:
Only used concretely-sized types when you need concretely sized types. Mostly, this means when you're persisting data, if you're directly interacting with hardware, or using some other code (e.g. a network stack) that expects concretely-sized types. Most of the time, you should just use the abstractly-sized types so that your compiler can optimize more intelligently and so that future readers of your code aren't burdened with useless details (like the size and signedness of a loop counter).
(As several other responses have said, use stdint.h, not something homebrew, when writing new code and not interfacing with the old.)