如何使我的数据类型独立于c中的编译器

Posted

技术标签:

【中文标题】如何使我的数据类型独立于c中的编译器【英文标题】:How to make my data types independent of compiler in c 【发布时间】:2013-09-27 08:09:43 【问题描述】:

我正在学习 uC/OS 并阅读了这篇文章:

由于不同的微处理器有不同的字长,端口 μC/OS-II 包括一系列类型定义,确保 可移植性 具体来说,μC/OS-II 的代码从不使用 C 的 short、int 和 long 数据类型,因为它们本质上是 不可移植。 相反,我定义了整数数据类型,它们都是 便携且直观,如清单 1.1 所示。另外,为了方便, 我已经包含了浮点数据类型,即使 μC/OS-II 没有 使用浮点数。以下为清单1.1

typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned int INT16U;
typedef signed int INT16S;
typedef unsigned long INT32U;
typedef signed long INT32S;
typedef float FP32;
typedef double FP64;
#define BYTE INT8S
#define UBYTE INT8U
#define WORD INT16S
#define UWORD INT16U
#define LONG INT32S
#define ULONG INT32U

我的问题是:

1- 作者所说的字长是什么意思(我的问题正文中的第一个粗体字)?!

2- 为什么 short int 和 long 数据类型本质上是不可移植的。

3-typedef是微处理器指令,如果是它的作用是什么?!

4- 我可以写typedef unsigned char (anything) 而不是typedef unsigned char INT8U;

5- 为什么作者编码typedef unsigned char INT8U; 然后#define UBYTE INT8U 我不能直接用这个吗typedef unsigned char UBYTE;

6- typedef unsigned char 有双重用途,其中一个是typedef unsigned char INT8U;,另一个是typedef unsigned char BOOLEAN; 他为什么要这样做?!

【问题讨论】:

请您也回答问题 5 和 6! @goldilocks 5- 我不会在这里过多地阅读作者的技术。这只是个人喜好问题。作者使用 typedef 定义固定宽度数据类型,然后使用宏将另一组术语(BYTE、WORD 等)与固定宽度数据类型相关联。是的,如果您愿意,可以使用 typedef 来定义 BYTE 和 WORD。 6- 作者想为 8 位宽的变量和布尔值(一位)定义数据类型,因为任何特定的软件抽象都可能需要这两种数据类型。他计划在比基本数据类型更高的抽象级别上编写代码。因此,当他的代码需要 TRUE/FALSE 变量时,他将使用布尔值。当他的代码需要一个 8 位变量时,他将使用 INT8U。这两种类型在下面碰巧是相同的,但是使用抽象类型为源代码增加了更多意义。当您查看他的代码并看到一个布尔值时,您就会知道它是一个 TRUE/FALSE 变量。 看起来我同时这样做了(在下面添加)——但 kkrambo 更简洁一些。 我强烈建议使用 C99 stdint.h typedefs;这些是为您的特定目标的编译器和架构定义的,而不是依赖于其他人的端口。我很想根据 stdint.h 类型重新定义所有 uC/OS-II 类型,所以你再也不需要这样做了。然后,您可以安全地互换使用这些类型,避免使用难看的大写类型名称。除此之外,您可能遇到的每个库都会认为定义具有非常相似(或相同)名称的整数类型是一个好主意,并且名称冲突的可能性很高 - 避免! 【参考方案1】:

1- 作者所说的字长是什么意思

一个词是记忆的基本单位,就像a page——实际上,还有一篇文章on word,我不再赘述。正如您的作者所说,对 C 的意义在于它并不总是相同的,而是由硬件特性决定的。这可能是 C 标准没有规定基本类型的字面量的原因之一。最明显的考虑是指针的大小,在 32 位系统上为 4 个字节,在 64 位系统上为 8 个字节,以反映地址空间的大小。

2- 为什么 short int 和 long 数据类型本质上是不可移植的。

更准确地说:它们与 C 一样可移植它们的大小不是标准化的,这可能使它们对于许多需要固定特定大小的应用程序无用。

3- typedef是微处理器指令吗,如果是它的作用是什么?!

不,它不是处理器指令。这是syntactic sugar 的一个很好的部分,它使您能够定义自定义类型。

4- 我可以写 typedef unsigned char (anything) 而不是 typedef unsigned char INT8U;

是的,就是这样。请注意,C 标准甚至没有规定 char 的大小,尽管我从未听说过除了 8 位之外的任何实现 [但 cmets 中的某个人有]

5-为什么作者编码typedef unsigned char INT8U;然后 #define UBYTE INT8U 我不能直接用这个 typedef unsigned char UBYTE;

你可以,是的。可能作者想限制定义这种类型的地方的数量。由于使用#define 是一个预处理器指令,它还可以稍微简化可执行文件(尽管没有达到普遍认为重要的程度)。

6- typedef unsigned char 有双重用途,其中之一是 typedef unsigned char INT8U;和另一个 typedef unsigned char BOOLEAN;他为什么要这么做?!

再一次,typedef 的使用与“糖”有很大关系;它们可以使您的代码更清晰、更易于阅读,并且(假设它们做得正确)更健壮。 “布尔”是一个数学派生的 CS 术语,表示只有两个有意义的值,零 (false) 或非零 (true)。所以理论上它可以只用一个位来实现,但这既不容易也不是最终有效的(因为没有具有 1 位寄存器的处理器,它们无论如何都必须切骰子并伪造这样的)。定义“bool”或“boolean”类型在 C 中很常见,用于指示值的意义是真还是假——它适用于例如if (var) (true) 和 if (!var) (false) 因为 C 已经以这种方式计算(0 和 NULL 是唯一将通过 if (!var) 的值)。而使用 INT8U 之类的东西表示您正在处理一个范围从十进制 0 到 255 的值,因为它是无符号的。我认为将U 放在前面是一种更常见的做法(UINT8),但如果您习惯了这些概念,那就相当清楚了。当然 typedef/define 也不难检查。


关于stdint.h

整数类型是变化范围最大的类型,事实上,ISO C 标准确实要求实现在stdint.h 中包含具有特定最小大小的各种整数类型的定义。这些名称类似于int_least8_t。当然,许多事情都需要具有真正固定大小(不仅仅是最小)的类型,并且大多数常见的实现都提供了它们。 C99 标准规定,如果它们可用,它们应该可以通过遵循模式intN_t(有符号)和uintN_t(无符号)的名称访问,其中N 是位数。签名类型也被指定为two's complement,因此可以以各种高度可移植的方式使用这些值。

最后一点,虽然我不熟悉 MicroC,但我一般不会将该文档视为 C 的代表——它旨在用于一些限制性和专业化的环境(16 位 int,隐含通过 typedefs,是不寻常的,因此如果您在其他地方运行该代码,则 INT16U 可能是 32 位等)。我猜 MicroC 只符合 ANSI C,这是最古老和最小的标准;显然它没有 stdint.h。

【讨论】:

您对stdint.h 的描述有点方向错误。它同时具有精确宽度和最小宽度整数类型。像 uint32_t 这样的东西是精确宽度类型,而 uint_least32_t 是至少 32 位的类型。 也许还可以补充一点,在引用的代码中执行此操作的方式已过时,应替换为stdint.h 中定义的类型。 @goldilocks 将 TI 的编译器用于他们的一些 DSP 会产生一个 16 位的 char @Jens stdint.h,这使得整个定制解决方案变得不必要。看起来这里的实际代码是基于给定编译器的独特属性的实现,即这是实现可移植基线的特定于平台的粘合剂。 @JensGustedt :我只是在 C99 草案的 7.18 中使用非可选类型。但我已经充实了最后一段以更好地解释固定尺寸。 我不明白你对问题 5 @goldilocks 的回答

以上是关于如何使我的数据类型独立于c中的编译器的主要内容,如果未能解决你的问题,请参考以下文章

如何使我的 C++ 类事件系统成为仅限于类型数组的模板类?

如何使我的正则表达式匹配我的文本中的任何类型的 str [重复]

如何使我的字符串属性可以为空?

我如何使我的函数返回双精度而不更改Metric类型?

如何在C语言中定义自己的数据类型?

如果C代码比较不同的数据类型,如何获得警告?