了解C中的积分算术

时间:2019-03-08 13:40:54

标签: c types integer-overflow

编辑:将void *修改为uint8_t *值。问题仍然存在。 编辑:问题是一个简单的变量溢出,与整数提升无关。

我解决了简化代码中的一个错误。类型与原始源代码中的类型相同。

unsigned int entrySize;    // entrySize is 288
int startIndex, endIndex;  // both are 24536838
uint8_t *pStartAddr;          // valid initialized pointer (0x34f1e40)

/*Mystery begins...*/
uint8_t *curr_addr = pStartAddr + entrySize * startIndex;
while (curr_addr <= startAddr + entrySize * endIndex)
{
    externFunc(curr_addr);
    curr_addr+=entrySize;
}

乍一看,此代码似乎很明显,除了奇怪的类型选择。

但是,在我们的一次崩溃中,curr_addr似乎获得了无效的指针。 我的直觉是entrySize * startIndex存在一个问题,因为它们的乘法设置在第32位,并且将startIndexendIndex作为有符号类型可能会使期望值的编译器混淆使用。

在更改其类型后,问题就解决了。 但我无法弄清楚完全是什么错误。

我正在使用64位计算机,x86_64 CPU,gcc(GCC)4.8.5 20150623和linux red hat发行版(版本4.8.5-28)

我假设当以上计算在entrySize * startIndex的第32位上设置时,问题开始出现。但是,当我使用第32位打开的第一个startIndex值时,它仍然有效。它也显示了

我的问题是:

  • int * unsigned int的值结果,被认为是带符号或 未签名?结果类型的等级是多少?乘法可以 可能溢出到8个字节类型,我认为编译器会阻止 失去精度吧?
  • startAddrvoid*。然后添加 到第一个问题中计算出的任何值和类型。是void* 被认为是signedunsigned?我的直觉当然是unsigned value,但我不能支持它。
  • 在startAddr + <<< strong>结果>>>>中发生什么Integer促销。
  • 我们的while语句能否在实际时间内永不停止?如果不等式的右边是带符号的数字(宽度至少为8个字节),那么左侧(curr_addr)是否也将被提升为带符号的数字,从而导致无限循环?
  • 最好逐步解释:)

我阅读了那些链接中包含的内容,但仍然一无所知:

  1. https://www.oreilly.com/library/view/c-in-a/0596006977/ch04.html
  2. Integer conversion rank of signed and unsigned int

2 个答案:

答案 0 :(得分:5)

  1. void*上的指针算术行为未定义。

  2. 指针算术仅在数组内有效。请注意,您可以设置指向数组最后一个元素之后的指针,但不要尝试取消引用它。此规则也适用于可以视为规则目的的单元素数组的对象。

(1)当然不会在您的代码中服从(编译器不会警告您-如果没有,请对它进行装箱),(2)可能不会。那时(在我看来)有些滑稽,您的特定问题无关紧要。

答案 1 :(得分:2)

  

乘法可能溢出到8个字节类型,我认为编译器可以防止精度下降,对吗?

那是一个严重错误的假设。每个the 3.4.3 description of undefined behavior from the C standard(正在轰动我):

  

3.4.3

     

1种不确定行为,使用不可移植或错误的行为   程序结构或错误数据,本国际   标准没有任何要求

     

2注意可能的不确定行为包括忽略情况   完全具有不可预测的结果,可以在翻译过程中表现   或以书面形式记录程序执行   环境(带有或不带有诊断消息),   终止翻译或执行(签发   诊断消息)。

     

3 示例未定义行为的一个示例是整数行为   溢出。

整数溢出是C标准本身使用的未定义行为的一个很好的例子。

并且288 * 24536838等于7066609344,远远超出了32位int的容量,无论是signed还是unsigned,因此调用了undefined行为。

因此,不,编译器不会“防止精度下降”。实际上,恰恰相反。