【问题标题】:Is Using 'sizeof(char)' When Dynamically Allocating A 'char' Redundant?动态分配“char”冗余时是否使用“sizeof(char)”?
【发布时间】:2014-01-08 03:51:33
【问题描述】:

在动态分配chars的时候,我一直是这样操作的:

char *pCh = malloc(NUM_CHARS * sizeof(char));

然而,最近有人告诉我,使用 sizeof(char) 是多余且不必要的,因为“根据定义,char 的大小是一个字节”,所以我应该/可以这样写上面的行:

char *pCh = malloc(NUM_CHARS);

我的理解是 char 的大小取决于目标计算机上使用的本机字符集。例如,如果本地字符集是 ASCII,char 是一个字节(8 位),如果本地字符集是 UNICODE,char 必然需要更多字节(> 8 位)。

为了提供最大的可移植性,难道没有必要使用sizeof(char),因为malloc 只是分配8 位字节吗?我是不是误会mallocsizeof(char)

【问题讨论】:

  • +1 用于省略右侧不必要的(char*) 演员
  • 我会做char * pCh = malloc(NUM_CHARS * sizeof(*pCh)); 并转向其他问题。
  • s/right/left/, 对 @Bathsheba?
  • "malloc 只分配 8 位字节" 。虽然 malloc 分配字节是真的,但 C 将字节定义为 char 的大小。所以 malloc 总是以 sizeof(char) 为单位分配,它总是 1,不管是多少位。 malloc(N) 将分配 N*CHAR_BIT 位。
  • @nos 好评论……应该是一个答案。 :-D

标签: c unicode char malloc ascii


【解决方案1】:

是的,这是多余的,因为语言标准规定 sizeof (char) 为 1。这是因为这是衡量事物的单位,所以单位本身的大小当然必须是 1。

生活变得奇怪,单位是根据自己定义的,这根本没有任何意义。许多人似乎“想要”假设“有 8 位字节,sizeof 告诉我在特定值中有多少这样的字节”。这是错误的,这根本不是它的工作原理。确实可以存在大于 8 位字符的平台,这就是我们有CHAR_BIT 的原因。

通常你总是“知道”什么时候分配字符,但如果你真的想包含sizeof,你应该考虑让它使用指针,而不是:

char *pCh = malloc(NUM_CHARS * sizeof *pCh);

这“锁定”了被分配事物的单位大小,该指针用于存储分配结果。如果您看到这样的代码,这两种类型应该匹配:

int *numbers = malloc(42 * sizeof (float));

这是一个巨大的警告信号;通过使用sizeof 左侧的指针,您可以避免这种类型的错误,我认为这是一个巨大的胜利:

int *numbers = malloc(42 * sizeof *numbers);

此外,如果您更改指针的名称,malloc() 可能无法编译,如果您在其中包含(错误的)基本类型的名称。如果你忘记了星号(写sizeof numbers而不是sizeof *numbers),你将无法得到你想要的东西。在实践中(对我来说)这似乎永远不会发生,因为对我来说,星号已经很好地成为这种模式的一部分。

此外,这种用法依赖于(并强调)sizeof 不是函数这一事实,因为在指针取消引用表达式周围不需要 ()s。这是一个很好的奖励,因为很多人似乎想否认这一点。 :)

我觉得这种模式非常令人满意,并推荐给大家。

【讨论】:

  • 你应该早点回答,我会给你正确答案的。
  • @BitFiddlingCodeMonkey Aawww。谢谢。 :) 我相信你可以移动接受状态,如果你愿意的话。 See this meta question.
【解决方案2】:

C99 draft standard 部分 6.5.3.4 sizeof 运算符 段落 3 声明:

当应用于具有 char、unsigned char 或 signed char 类型的操作数时, (或其合格版本)结果为 1。 [...]

在 C11 草案标准中是第 4 段,但措辞相同。所以NUM_CHARS * sizeof(char)应该等同于NUM_CHARS

3.6byte的定义可以看出,它是一个:

足够大的可寻址数据存储单元以容纳基本字符的任何成员 一套执行环境

注2说:

一个字节由一个连续的位序列组成,其数量由实现定义。最低有效位称为低位;最高位称为高位。

【讨论】:

    【解决方案3】:

    C 规范声明 sizeof(char)1,因此只要您处理符合 C 的实现,它就是多余的。

    malloc使用的大小单位是一样的。 malloc(120) 为 120 char 分配空间。

    char 必须至少为 8 位,但可能更大。

    【讨论】:

    • 那么在具有 16 位 chars 的系统上,不可能以 8-bits 的倍数分配内存?
    • @BitFiddlingCodeMonkey:完全正确。关键是 char (=byte) 被定义为最小的可寻址数据类型(只要大于 8 位),因此具有更精细的粒度没有意义。
    • @BitFiddlingCodeMonkey:你不能在这样的系统上要求 24 位。 malloc(1) 由于内存对齐,通常会分配 4 个字节,所以我看不到问题。
    • @CodeMonkey 在内存有限的系统上,我不希望使用 16 位字符。
    • 此外,优化您的代码以防止移植到内存少但字节大小大的假设平台的可能性不大,这需要过早优化到新的疯狂高峰 =)。编写正确、可移植的代码,并担心仅针对实际可能运行的平台进行特定于平台的优化。
    【解决方案4】:

    sizeof(char) 将始终返回 1,因此无论您使用它还是 nit,它都不会改变。您可能会将此与 UNICODE 宽字符混淆,后者有两个字节,但它们具有不同的类型 wchar_t,因此在这种情况下您应该使用 sizeof

    如果您在一个字节被定义为 16 位的系统上工作,那么sizeof(char) 仍将返回 1,因为这是底层架构将分配的内容。 1 字节,16 位。

    【讨论】:

    • 那么如果系统上1个字节为16位,malloc是否总是返回16-bits的倍数,即不能动态分配8-bits的倍数?
    • 是的,如果这是机器的规格,那就是这样。编译器只是反映了这种设计。在这样的机器上,您不能寻址少于 16 位。因此,如果您执行malloc(2),您将得到一个指向两个字节的指针,但由 32 位组成。
    【解决方案5】:

    分配大小始终以char 为单位,根据定义,其大小为 1。如果您在 9 位机器上,malloc 将其参数理解为 9 位字节数。

    【讨论】:

    • 您是否使用9-bits 作为假设示例?我从来没有听说过这样的事情。
    • @BitFiddlingCodeMonkey:IIRC 一些大型机使用 9 位字节 - 可能是由于 36 位字。如今,奇怪的比特大小通常在 DSP 中发现,它们往往每字节有 12 到 16 位。请参阅here 了解一些真实世界的示例。
    【解决方案6】:

    sizeof(char) 总是1,但不是因为char 总是一个字节(不一定是),而是因为sizeof 运算符以char 为单位返回对象/类型大小.

    【讨论】:

    • char 通常“平台字节”(=最小的可寻址数据类型),关键是并非所有平台上的字节都是八位字节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 2017-04-02
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多