我什么时候应该在嵌入式系统中使用类型抽象

发布于 2024-07-04 17:40:32 字数 735 浏览 6 评论 0原文

我曾参与过许多不同的嵌入式系统。 他们都使用 typedef(或 #defines)来表示 UINT32 等类型。

这是一项很好的技术,因为它可以让程序员了解类型的大小,并使您更加意识到溢出等的可能性。

但在某些系统上,您知道编译器和处理器在项目的生命周期内不会改变。

那么什么会影响您创建和实施项目特定类型的决定呢?

编辑 我想我失去了问题的要点,也许这真的是两个。

通过嵌入式编程,您可能需要特定大小的接口类型,并应对 RAM 等有限资源。 这是无法避免的,但您可以选择使用编译器中的基本类型。

对于其他一切,类型的重要性较低。
您需要小心不要导致溢出,并且可能需要注意寄存器和堆栈的使用。 这可能会引导您到 UINT16UCHAR。 然而,使用诸如 UCHAR 之类的类型可能会增加编译器的“错误”。 由于寄存器通常较大,因此某些编译器可能会添加代码以将结果强制转换为该类型。

i++;
can become
ADD REG,1
AND REG, 0xFF
which is unecessary.

所以我认为我的问题应该是:

考虑到嵌入式软件的限制,为一个有很多人参与的项目制定最好的政策是什么——并非所有人都具有相同的经验水平。

I've worked on a number of different embedded systems. They have all used typedefs (or #defines) for types such as UINT32.

This is a good technique as it drives home the size of the type to the programmer and makes you more conscious of chances for overflow etc.

But on some systems you know that the compiler and processor won't change for the life of the project.

So what should influence your decision to create and enforce project-specific types?

EDIT
I think I managed to lose the gist of my question, and maybe it's really two.

With embedded programming you may need types of specific size for interfaces and also to cope with restricted resources such as RAM. This can't be avoided, but you can choose to use the basic types from the compiler.

For everything else the types have less importance.
You need to be careful not to cause overflow and may need to watch out for register and stack usage. Which may lead you to UINT16, UCHAR.
Using types such as UCHAR can add compiler 'fluff' however. Because registers are typically larger, some compilers may add code to force the result into the type.

i++;

can become
ADD REG,1
AND REG, 0xFF

which is unecessary.

So I think my question should have been :-

given the constraints of embedded software what is the best policy to set for a project which will have many people working on it - not all of whom will be of the same level of experience.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

那小子欠揍 2024-07-11 17:40:32

如果您的嵌入式系统在某种程度上是一个安全关键系统(或类似系统),则强烈建议(如果不需要)使用 typedef 而不是普通类型。

正如 TK. 之前所说,MISRA-C 有一条(建议)规则来执行此操作:

规则 6.3(建议):应使用指示大小和符号的 typedef 来代替基本数字类型。

(来自 MISRA-C 2004;它是 MISRA-C 1998 的规则 #13 (adv))


同样也适用于该领域的 C++; 例如。 JSF C++ 编码标准

AV 规则 209 将创建一个 UniversalTypes 文件来定义所有 sta
供开发人员使用的标准类型。 类型包括:[uint16、int16、uint32_t等]

If your embedded systems is somehow a safety critical system (or similar), it's strongly advised (if not required) to use typedefs over plain types.

As TK. has said before, MISRA-C has an (advisory) rule to do so:

Rule 6.3 (advisory): typedefs that indicate size and signedness should be used in place of the basic numerical types.

(from MISRA-C 2004; it's Rule #13 (adv) of MISRA-C 1998)


Same also applies to C++ in this area; eg. JSF C++ coding standards:

AV Rule 209 A UniversalTypes file will be created to define all sta
ndard types for developers to use. The types include: [uint16, int16, uint32_t etc.]

朮生 2024-07-11 17:40:32

一致性、方便性和可读性。 “UINT32”比“unsigned long long”更具可读性和可写性,这对于某些系统来说是等效的。

此外,编译器和处理器可能在项目的生命周期内是固定的,但该项目的代码可能会在另一个项目中找到新的生命。 在这种情况下,拥有一致的数据类型就非常方便了。

Consistency, convenience and readability. "UINT32" is much more readable and writeable than "unsigned long long", which is the equivalent for some systems.

Also, the compiler and processor may be fixed for the life of a project, but the code from that project may find new life in another project. In this case, having consistent data types is very convenient.

靖瑶 2024-07-11 17:40:32

C99 标准有许多标准大小的整数类型。 如果您可以使用支持 C99 的编译器(gcc 可以),您将在 中找到它们,并且可以在项目中使用它们。

此外,在嵌入式项目中,使用类型作为诸如单位转换之类的“安全网”尤其重要。 如果您可以使用 C++,我知道有一些“单元”库可以让您在由 C++ 类型系统(通过模板)定义的物理单元中工作,这些物理单元被编译为对底层标量类型的操作。 例如,这些库不允许您将 distance_t 添加到 mass_t,因为单位不对齐; 你实际上会得到一个编译器错误。

即使您无法使用 C++ 或其他允许您以这种方式编写代码的语言,您至少可以使用 C 类型系统来帮助您通过肉眼捕获此类错误。 (这实际上是 Simonyi 匈牙利表示法的初衷。)仅仅因为编译器不会因为将 meter_t 添加到 gram_t 中而对您大喊大叫,并不意味着您应该这样做不要使用这样的类型。 代码审查在发现单元错误方面会更加高效。

The C99 standard has a number of standard sized-integer types. If you can use a compiler that supports C99 (gcc does), you'll find these in <stdint.h> and you can just use them in your projects.

Also, it can be especially important in embedded projects to use types as a sort of "safety net" for things like unit conversions. If you can use C++, I understand that there are some "unit" libraries out there that let you work in physical units that are defined by the C++ type system (via templates) that are compiled as operations on the underlying scalar types. For example, these libraries won't let you add a distance_t to a mass_t because the units don't line up; you'll actually get a compiler error.

Even if you can't work in C++ or another language that lets you write code that way, you can at least use the C type system to help you catch errors like that by eye. (That was actually the original intent of Simonyi's Hungarian notation.) Just because the compiler won't yell at you for adding a meter_t to a gram_t doesn't mean you shouldn't use types like that. Code reviews will be much more productive at discovering unit errors then.

热情消退 2024-07-11 17:40:32

我相信 MISRA 标准建议(要求?)使用 typedef。

从个人角度来看,使用 typedef 不会对某些类型的大小(以位/字节为单位)产生混淆。 我见过主要开发人员尝试使用标准类型(例如 int)和使用自定义类型(例如 UINT32)两种开发方式。

如果代码不可移植,那么使用 typedef 就没有什么真正的好处,但是,如果像我一样,那么您可以同时使用两种类型的软件(可移植环境和固定环境)保持标准并使用定制类型可能很有用。 至少就像你说的,程序员非常清楚他们使用了多少内存。 另一个需要考虑的因素是您有多“确定”代码不会被移植到另一个环境? 我见过处理器特定的代码必须被翻译,因为硬件工程师突然不得不更换一块板,这不是一个好的情况,但由于自定义的 typedef,情况可能会更糟!

I believe that MISRA standards suggest (require?) the use of typedefs.

From a personal perspective, using typedefs leaves no confusion as to the size (in bits / bytes) of certain types. I have seen lead developers attempt both ways of developing by using standard types e.g. int and using custom types e.g. UINT32.

If the code isn't portable there is little real benefit in using typedefs, however , if like me then you work on both types of software (portable and fixed environment) then it can be useful to keep a standard and use the cutomised types. At the very least like you say, the programmer is then very much aware of how much memory they are using. Another factor to consider is how 'sure' are you that the code will not be ported to another environment? Ive seen processor specific code have to be translated as a hardware engieer has suddenly had to change a board, this is not a nice situation to be in but due to the custom typedefs it could have been a lot worse!

小帐篷 2024-07-11 17:40:32

我的观点是,如果您依赖于最小/最大/特定大小,不要只是假设(例如)unsigned int 是 32 字节 - 使用 uint32_t 相反(假设您的编译器支持 C99)。

My opinion is if you are depending on a minimum/maximum/specific size don't just assume that (say) an unsigned int is 32 bytes - use uint32_t instead (assuming your compiler supports C99).

迷路的信 2024-07-11 17:40:32

我喜欢使用 stdint.h 类型来专门定义系统 API,因为它们明确说明了项目有多大。 回到 Palm OS 的旧时代,系统 API 是使用一堆从非常经典的 Mac OS 继承的软弱类型(如“Word”和“SWord”)来定义的。 他们进行了清理,改为使用 Int16,这使得新手更容易理解 API,特别是在该系统上存在奇怪的 16 位指针问题时。 当他们设计 Palm OS Cobalt 时,他们再次更改了这些名称以匹配 stdint.h 的名称,使其更加清晰并减少了他们必须管理的 typedef 数量。

I like using stdint.h types for defining system APIs specifically because they explicitly say how large items are. Back in the old days of Palm OS, the system APIs were defined using a bunch of wishy-washy types like "Word" and "SWord" that were inherited from very classic Mac OS. They did a cleanup to instead say Int16 and it made the API easier for newcomers to understand, especially with the weird 16-bit pointer issues on that system. When they were designing Palm OS Cobalt, they changed those names again to match stdint.h's names, making it even more clear and reducing the amount of typedefs they had to manage.

℡Ms空城旧梦 2024-07-11 17:40:32

我很少使用类型抽象。 以下是我的论点,按主观性升序排序:

  1. 局部变量与结构成员和数组不同,因为您希望它们适合寄存器。 在 32b/64b 目标上,与本地 int 相比,本地 int16_t 会使代码变慢,因为编译器必须根据 int16_t 的语义向 /force/ 溢出添加操作。代码>. 虽然 C99 定义了 intfast_t typedef,但据我所知,普通 int 也适合寄存器,而且它的名称肯定更短。

  2. 喜欢这些类型定义的组织几乎总是会使用其中的几个(INT32、int32_t、INT32_T,无穷无尽)。 因此,在某种程度上,使用内置类型的组织只拥有一组名称会更好。 我希望人们使用 stdint.h 或 windows.h 或任何现有的类型定义; 当目标没有该 .h 文件时,添加一个有多难?

  3. 从理论上讲,typedef 可以帮助可移植性,但我从未从它们中获得任何东西。 是否有一个有用的系统可以从 32b 目标移植到 16b 目标? 是否有 16b 系统可以轻松移植到 32b 目标? 此外,如果大多数变量是整数,您实际上会从新目标上的 32 位中获得一些东西,但如果它们是 int16_t ,则不会。 而那些难以搬运的地方往往还是需要人工检查; 在尝试端口之前,您不知道它们在哪里。 现在,如果有人认为如果你到处都有 typedef,那么移植东西就很容易 - 当需要移植时(这种情况发生在少数系统上),请编写一个脚本来转换代码库中的所有名称。 这应该按照“不需要手动检查”的逻辑进行,并且它将工作推迟到实际带来好处的时间点。

  4. 现在,如果可移植性可能是 typedef 的理论上的好处,那么可读性肯定会付诸东流。 只需查看 stdint.h:{int,uint}{max,fast,least}{8,16,32,64}_t。 种类很多。 一个程序有很多变量; 哪些需要是 int_fast16_t 哪些需要是 uint_least32_t 真的那么容易理解吗? 有多少次我们默默地在它们之间进行转换,使它们变得毫无意义? (我特别喜欢 BOOL/Bool/eBool/boolean/bool/int 转换。由强制 typedef 的有序组织编写的每个程序都充满了这种转换)。

  5. 当然,在 C++ 中,我们可以通过使用重载运算符和内容将数字包装在模板类实例化中,从而使类型系统更加严格。 这意味着您现在将收到以下形式的错误消息:“类 Number对于类型类 Number的参数没有运算符+重载,候选者是...”也不要称之为“可读性”。 正确实现这些包装类的机会是微乎其微的,大多数时候您将等待无数模板实例化的编译。

I use type abstraction very rarely. Here are my arguments, sorted in increasing order of subjectivity:

  1. Local variables are different from struct members and arrays in the sense that you want them to fit in a register. On a 32b/64b target, a local int16_t can make code slower compared to a local int since the compiler will have to add operations to /force/ overflow according to the semantics of int16_t. While C99 defines an intfast_t typedef, AFAIK a plain int will fit in a register just as well, and it sure is a shorter name.

  2. Organizations which like these typedefs almost invariably end up with several of them (INT32, int32_t, INT32_T, ad infinitum). Organizations using built-in types are thus better off, in a way, having just one set of names. I wish people used the typedefs from stdint.h or windows.h or anything existing; and when a target doesn't have that .h file, how hard is it to add one?

  3. The typedefs can theoretically aid portability, but I, for one, never gained a thing from them. Is there a useful system you can port from a 32b target to a 16b one? Is there a 16b system that isn't trivial to port to a 32b target? Moreover, if most vars are ints, you'll actually gain something from the 32 bits on the new target, but if they are int16_t, you won't. And the places which are hard to port tend to require manual inspection anyway; before you try a port, you don't know where they are. Now, if someone thinks it's so easy to port things if you have typedefs all over the place - when time comes to port, which happens to few systems, write a script converting all names in the code base. This should work according to the "no manual inspection required" logic, and it postpones the effort to the point in time where it actually gives benefit.

  4. Now if portability may be a theoretical benefit of the typedefs, readability sure goes down the drain. Just look at stdint.h: {int,uint}{max,fast,least}{8,16,32,64}_t. Lots of types. A program has lots of variables; is it really that easy to understand which need to be int_fast16_t and which need to be uint_least32_t? How many times are we silently converting between them, making them entirely pointless? (I particularly like BOOL/Bool/eBool/boolean/bool/int conversions. Every program written by an orderly organization mandating typedefs is littered with that).

  5. Of course in C++ we could make the type system more strict, by wrapping numbers in template class instantiations with overloaded operators and stuff. This means that you'll now get error messages of the form "class Number<int,Least,32> has no operator+ overload for argument of type class Number<unsigned long long,Fast,64>, candidates are..." I don't call this "readability", either. Your chances of implementing these wrapper classes correctly are microscopic, and most of the time you'll wait for the innumerable template instantiations to compile.

深白境迁sunset 2024-07-11 17:40:32

使用 使您的代码更易于在 PC 上进行单元测试。

当您对所有内容进行测试时,它可能会非常严重,但它仍然会在您的目标系统上崩溃,因为 int 突然只有 16 位长。

Using <stdint.h> makes your code more portable for unit testing on a pc.

It can bite you pretty hard when you have tests for everything but it still breaks on your target system because an int is suddenly only 16 bit long.

鲸落 2024-07-11 17:40:32

也许我很奇怪,但我使用 ub、ui、ul、sb、si 和 sl 作为我的整数类型。 也许 16 位的“i”看起来有点过时,但我比 uw/sw 更喜欢 ui/si 的外观。

Maybe I'm weird, but I use ub, ui, ul, sb, si, and sl for my integer types. Perhaps the "i" for 16 bits seems a bit dated, but I like the look of ui/si better than uw/sw.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文