c语言中长度待定,C / C ++中的固定长度数据类型

C / C ++中的固定长度数据类型

我听说typedefs等数据类型的大小可能因平台而异。

我的第一个问题是:有人带来一些例子,出现什么问题,程序时假设typedefs是4个字节,但在不同的平台上,它是2个字节?

我遇到的另一个问题是相关的。 我知道人们用typedefs解决了这个问题,像你有变量像u8,u16,u32 - 保证是8位,16位,32位,无论平台 - 我的问题是,这通常是如何实现的? (我不是指stdint库中的类型 - 我手动很好奇,如何强制某些类型总是说32位而不管平台?)

asked 2019-06-16T03:53:43Z

11个解决方案

40 votes

我知道人们用一些typedef来解决这个问题,就像你有u8,u16,u32这样的变量 - 保证是8位,16位,32位,无论平台如何

有些平台没有特定大小的类型(例如TI的28xxx,其中char的大小为16位)。 在这种情况下,不可能有8位类型(除非你真的想要它,但这可能会引入性能损失)。

这通常是如何实现的?

通常使用typedef。 c99(和c ++ 11)在头文件中有这些typedef。 所以,只需使用它们。

当程序假设一个int是4个字节时,有人会带来一些例子吗,出了什么问题,但是在另一个平台上它是2个字节?

最好的例子是具有不同类型大小的系统之间的通信。 从一个平台向另一个平台发送一组int,其中sizeof(int)在两个平台上是不同的,一个必须非常小心。

此外,在32位平台上保存二进制文件中的int数组,并在64位平台上重新解释它。

BЈовић answered 2019-06-16T03:54:42Z

22 votes

在C标准的早期迭代中,您通常会创建自己的inttypes.h语句,以确保您获得(例如)16位类型,基于传递给编译器的printf字符串,例如:

gcc -DINT16_IS_LONG ...

如今(C99及以上),有特定的类型,如inttypes.h,正好是16位宽的无符号整数。

如果包含inttypes.h,则可获得精确的位宽类型,至少为该宽度类型,具有给定最小宽度等的最快类型,如printf中所述。如果实现具有兼容类型,则需要提供这些类型。

同样非常有用的是inttypes.h,它为这些新类型(printf和scanf格式字符串)的格式转换添加了一些其他简洁的功能。

paxdiablo answered 2019-06-16T03:55:31Z

16 votes

对于第一个问题:整数溢出。

对于第二个问题:例如,对于typedef无符号32位整数,在stdint.h为4字节的平台上,使用:

typedef unsigned int u32;

在stdint.h是2字节而long是4字节的平台上:

typedef unsigned long u32;

这样,您只需修改一个头文件即可使这些类型跨平台。

如果有一些特定于平台的宏,则无需手动修改即可实现:

#if defined(PLAT1)

typedef unsigned int u32;

#elif defined(PLAT2)

typedef unsigned long u32;

#endif

如果支持C99 stdint.h,则首选。

Yu Hao answered 2019-06-16T03:56:34Z

7 votes

首先:永远不要编写依赖于类型宽度的程序,如int[n]_t,uint[n]_t,n,....

基本上:“如果没有标准保证,就不要依赖宽度”。

如果您想要真正独立于平台并存储,例如 值33000作为有符号整数,你不能只假设int[n]_t会持有它。 uint[n]_t至少具有范围n至8或16至32(取决于一个/二个补码)。 这还不够,即使它通常是32位,因此能够存储33000.对于这个值你绝对需要64类型,因此你只需选择或C。如果这种类型不存在,编译器会告诉你 错误,但它不会是一个无声的错误。

第二:C ++ 11为固定宽度整数类型提供标准头。 这些都不能保证在您的平台上存在,但是当它们存在时,它们保证具有确切的宽度。 有关参考,请参阅cppreference.com上的这篇文章。 类型以格式int[n]_t和uint[n]_t命名,其中n是8,16,32或64.您将需要包括标题.239439402194994184标题当然是。

stefan answered 2019-06-16T03:57:29Z

6 votes

通常,当您最大化数字或进行序列化时会出现问题。 当有人做出明确的大小假设时,会发生一种不常见的情况。

在第一个场景中:

int x = 32000;

int y = 32000;

int z = x+y; // can cause overflow for 2 bytes, but not 4

在第二种情况下,

struct header {

int magic;

int w;

int h;

};

然后一个去fwrite:

header h;

// fill in h

fwrite(&h, sizeof(h), 1, fp);

// this is all fine and good until one freads from an architecture with a different int size

在第三种情况中:

int* x = new int[100];

char* buff = (char*)x;

// now try to change the 3rd element of x via buff assuming int size of 2

*((int*)(buff+2*2)) = 100;

// (of course, it's easy to fix this with sizeof(int))

如果您使用的是相对较新的编译器,我会使用uint8_t,int8_t等,以确保类型大小。

在较旧的编译器中,typedef通常基于每个平台定义。 例如,有人可能会这样做:

#ifdef _WIN32

typedef unsigned char uint8_t;

typedef unsigned short uint16_t;

// and so on...

#endif

通过这种方式,每个平台都会有一个标头,用于定义该平台的细节。

thang answered 2019-06-16T03:58:49Z

5 votes

我手动好奇,如何强制某些类型总是说32位无论平台?

如果您希望(现代)C ++程序的编译失败,如果给定的类型不是您期望的宽度,请在某处添加chars。 我将这个添加到关于类型宽度的假设的地方。

static_assert(sizeof(int) == 4, "Expected int to be four chars wide but it was not.");

最常用的平台上的chars是8位大,但并非所有平台都以这种方式工作。

chwarr answered 2019-06-16T03:59:34Z

3 votes

好吧,第一个例子 - 这样的事情:

int a = 45000; // both a and b

int b = 40000; // does not fit in 2 bytes.

int c = a + b; // overflows on 16bits, but not on 32bits

如果你查看int_least16_t标题,你会发现如何定义所有固定大小类型(int8_t,uint8_t等) - 并且只有不同架构之间的不同之处是这个头文件。 因此,在一个架构int16_t上可以是:

typedef int int16_t;

在另一个:

typedef short int16_t;

此外,还有其他类型,可能是有用的,如:int_least16_t

Nemanja Boric answered 2019-06-16T04:00:29Z

2 votes

如果类型小于您的想法,那么它可能无法存储您需要存储在其中的值。

要创建固定大小类型,请阅读要支持的平台的文档,然后根据特定平台的#ifdef定义typedef。

Juraj Blaho answered 2019-06-16T04:01:09Z

2 votes

当程序假设一个int是4个字节时,有人会带来一些例子吗,出了什么问题,但是在另一个平台上它是2个字节?

假设您已经将程序设计为读取100,000个输入,并且使用unsigned int计算它,假设32位大小(32位无符号整数可以计数到4,294,967,295)。 如果在具有16位整数的平台(或编译器)上编译代码(16位无符号整数只能计数到65,535),则由于容量而导致值绕过65535并表示错误计数。

legends2k answered 2019-06-16T04:01:45Z

1 votes

编译器有责任遵守该标准。 当您包括__32BIT__或stdint时,他们应根据标准尺寸提供类型。

编译器知道他们正在编译什么平台的代码,然后他们可以生成一些内部宏或魔法来构建合适的类型。 例如,32位计算机上的编译器生成__32BIT__宏,之前它在stdint头文件中包含以下行:

#ifdef __32BIT__

typedef __int32_internal__ int32_t;

typedef __int64_internal__ int64_t;

...

#endif

你可以使用它。

deepmax answered 2019-06-16T04:02:32Z

0 votes

位标志是一个简单的例子。 0x10000将导致您出现问题,您无法使用它进行掩码或检查是否在第17个位置设置了一个位,如果所有内容都被截断或粉碎以适合16位。

jheriko answered 2019-06-16T04:03:06Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值