【问题标题】:Can a standards-conforming string be longer than SIZE_MAX characters?符合标准的字符串可以长于 SIZE_MAX 个字符吗?
【发布时间】:2017-01-26 09:24:32
【问题描述】:

我没有在 C11 标准中找到任何说明字符串不能长于SIZE_MAX(其中SIZE_MAX 表示size_t 类型的最大值)字符的内容。例如。如果size_maxlong,并且在我的实现中有一个严格大于longlong long 类型,那么我可以使用long long 定义和索引这样的字符串。

但是,这会暗示一些不寻常的情况:例如,strlen 可能无法返回字符串的实际大小,因为结果会在末尾转换为 size_t,因此字符串的长度例如,SIZE_MAX+1 将被报告为大小为 0。例如,这会违反标准,从而阻止此类字符串的存在吗?作为参考,7.24.6.3 只说:

7.24.6.3 strlen 函数

概要

#include <string.h>

size_t strlen(const char *s);

说明

strlen 函数计算 s 所指向的字符串的长度。

退货

strlen 函数返回终止空字符之前的字符数。

我是否遗漏了什么,或者这在(给定的符合标准的)C11 实现中完全有效?

【问题讨论】:

  • "那么我可以使用 long long 分配 [ ...] 一个字符串。" 假设动态分配,你不能,因为 malloc() 需要一个 size_t
  • C11 草案“建议”在 7.19/4 下:“用于size_tptrdiff_t 的类型的整数转换等级不应大于signed long int,除非实现支持足够大的对象以使其成为必要。" 这间接表明不会有大于SIZE_MAX 的对象。
  • @alk 很好,我的意思是“声明”而不是“分配”。我修正了那个短语。
  • IMO 旨在创建大于SIZE_MAX 的对象。在这种情况下,标准的几个部分是有问题的。 C++ 标准明确说明了这一点,但 C 标准没有。

标签: c string language-lawyer c11


【解决方案1】:

来自[6.5.3.4 sizeof 和 alignof 运算符]:

4 当 sizeof 应用于 char、unsigned char 或 signed char 类型(或其限定版本)的操作数时,结果为 1。当应用于数组类型的操作数时,结果为总数数组中的字节数。 102) 当应用于具有结构或联合类型的操作数时,结果是此类对象中的总字节数,包括内部和尾随填充。

5 两个运算符的结果值是实现定义的,其类型(无符号整数类型)是 size_t,在"stddef.h"(和其他头文件)中定义。

由此可见,任何数组的大小都不能超过size_t可以容纳的大小,因此字符串的大小不能超过SIZE_MAX

编辑:使用calloc,参见[7.22.3.2 calloc 函数]:

calloc 函数为 nmemb 对象数组分配空间,每个对象的大小都是 size。该空间被初始化为所有位为零。

它为一个数组分配空间,但数组大小必须适合size_t,所以你不能用calloc分配超过SIZE_MAX。如果您尝试这样做,它必须返回 NULL

【讨论】:

  • Thar 没有跟上。您可以将两个参数传递给 calloc() 创建一个大于 SIZE_MAX 的对象并将字符串写入该对象。标准并不清楚应该发生什么 - 理想情况下 calloc() 将返回 null。
  • @MalcolmMcLean 不,您不能分配超过SIZE_MAXcalloc。见编辑。
  • @MalcolmMcLean 有人认为传递此类参数是未定义的行为。标准不明确。
  • 标准对我来说非常清楚:它必须返回指向数组的指针或NULL。既然不可能有这样的数组,它唯一的选择就是返回NULL
  • @chux:恕我直言,C 真正需要的可移植性是一种指定需要什么类型的方法。有一种方法可以让程序员指定“我需要将 32 位值存储为四个字符,LSB 在前”不会“区分”具有 36 位字的平台,但恰恰相反:它将允许此类平台通过使用移位和掩码模拟所需的行为,使用为其他平台编写的代码。在需要或不需要此类控制时使用不同的类型将允许编译器避免使用低效的移位/屏蔽逻辑,除非必要时。
【解决方案2】:

让我们把一些规格放在一起。


字符串 是一个连续的字符序列,由第一个空字符终止并包含第一个空字符。 C11 §7.1.1 1(我的重点)


sizeof被应用...具有数组类型的操作数时,结果是数组中的总字节数...。 C11 §6.5.3.4 4

size_t 这是sizeof 运算符结果的无符号整数类型; C11 §7.19 2

size_t 的限制是SIZE_MAX C11 7.20.3 2


如果我们只使用字符数组对象或为字符数组分配内存,最长的字符串大小为SIZE_MAXstrlen(x_big) 的最大返回值为SIZE_MAX - 1


如果代码在以下情况下成功,那么代码已经冒险了,在这种情况下,字符串的构造时间可能比SIZE_MAX长,但我怀疑calloc()会返回@987654331 @first 或 (char *) ptr 将失败。

double *ptr = calloc(SIZE_MAX, sizeof *ptr);
assert(ptr);
char *s_waybig = (char *) ptr;

【讨论】:

    猜你喜欢
    • 2013-07-27
    • 2021-11-14
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    相关资源
    最近更新 更多