c - 理解 C 中的积分运算

标签 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 作为有符号类型可能会使编译器混淆要使用的所需值。

将它们的类型更改为unsinged long 后,问题就解决了。 但我无法弄清楚到底哪里出了问题。

我正在使用 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 的值结果被认为是有符号的或 未签名?结果类型的排名是多少?乘法 jar 可能溢出到 8 字节类型,我假设编译器会阻止 失去精度,对吧?
  • startAddr 是一个 void*。然后添加 到第一个问题中计算的任何值和类型。是 void* 被认为是 signed 还是 unsigned?我的预感当然是 unsigned value,但我无法支持它。
  • 在 startAddr + <<result>> 中发生什么整数提升。
  • 我们的 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

最佳答案

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

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

(1) 在你的代码中肯定没有被遵守(你的编译器没有警告你 - 如果没有,将它装箱),(2)可能不是。有点滑稽(就我而言),你的具体问题不相关。

关于c - 理解 C 中的积分运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55064445/

相关文章:

java - 在 Java 中使用 FUSE 库;尝试复制 hello.c 示例

javascript - 理解 Elm 中的类型

haskell - 函数无法匹配类型

在 C 中计算整数溢出

C++ 为什么 LLONG_MIN == -LLONG_MIN

C:如何迭代 `signed int` 的所有可能值,从 `INT_MIN` 到 `INT_MAX` ?

python - 在python中评估shellcode的方法?

c - 在 yacc/bison 之外使用 lex/flex

c - C99 中复杂算术的类型安全

php - 在 Symfony2 中设置实体类型的默认值