【发布时间】:2020-11-14 11:55:45
【问题描述】:
让我们有一个char 数组:
char arr[(size_t)PTRDIFF_MAX + (size_t)2];
让我们接受我们的系统有足够的可用内存。
以数组表示法或指针表示法访问数组是已定义、未定义或实现定义的行为?
char c = arr[(size_t)PTRDIFF_MAX + (size_t)1];
char d = *(&arr[0] + ((size_t)PTRDIFF_MAX + (size_t)1));
我担心索引可能会在访问之前转换为ptrdiff_t,从而导致索引无效。
编辑:
在不可能有这么多元素的数组的情况下,让我们把这个类似的情况:
我们有一个比PTRDIFF_MAX 少元素的数组,但是大元素(例如:int64_t,或具有许多元素的结构),因此数组的原始大小仍然超过PTRDIFF_MAX。我们通过char * 访问数组,这是一个有效的强制转换(或多或少在memcpy 内部发生了什么)。
【问题讨论】:
-
这看起来很相关:stackoverflow.com/a/31864574/634919。我认为简短的回答是您根本无法拥有那么大的数组。
-
我假设这是在一台 32 位机器上,
PTRDIFF_MAX是0x7FFFFFFF(31 位)?在 64 位机器上,PTRDIFF_MAX是0x7FFFFFFFFFFFFFFF,所以你不太可能靠近 [或关心]。但是,这是一个 signed 数量。PTRDIFF_MIN是0x80000000它可以取决于环境。您可以解决这个问题。例如,在 32 位机器上,可寻址性为0xFFFFFFFF(32 位)。签名是因为您想在这样做时倒退:&arr[3] - &arr[5]。但是,即使未签名也有效。指针算术是无符号的。所以,PTRDIFF_MAX可能不是看待它的最佳方式 -
@CraigEstey re:32 位或 64:是的,32 或更少。 re: 指针算法是无符号的: 很高兴知道。我认为因为指针算法使用了
ptrdiff_t,所以它是签名的。这在标准中的什么地方? -
@CacahueteFrito:标准在哪里说指针算术使用
ptrdiff_t?唯一的说法是指针减法(不是计算)的结果作为ptrdiff_t返回。 -
它明确表示
i-j必须适合ptrdiff_t,而不是地址之间的差异。我会在我的答案中添加语言律师的报价。