递增指针而不解除引用仍可能导致段错误或其他(未)定义的问题吗?

8

我在网上找到的所有关于增加指针导致段错误的例子都涉及到了对指针的解引用 - 如果我只想增加它怎么办(例如在for循环的末尾),并且我不关心它最终是否处于无效内存中,因为我不会再次使用它。例如,在这个程序中,我只需要每次迭代步进4个,但是在最后一次迭代后我再也不会解引用这些指针。

float* leftRowPointer, resultRowPointer;
// assume they were correctly initialized

for (unsigned int i = 0; i < 4; ++i, leftRowPointer += 4, resultRowPointer += 4) {
    // do some stuff
}

我需要做类似这样的事情吗?
for (unsigned int i = 0; i < 4; ++i) {
    // same stuff
    if (i != 3) {
        leftRowPointer += 4;
        resultRowPointer += 4;
    }
}

有没有更好的方法来完成我所尝试做的事情?当我自己尝试时,似乎并没有发生什么不好的事情,但这并不能保证它总是有效的。不幸的是,我在工作中没有访问Valgrind或类似的工具。我们使用的是C++11标准,顺便说一下,我在里面找不到任何直接适用于此的内容,但我会第一个承认我不太了解标准,不知道从哪里查找相关内容。

1
请查看加法运算符(可能是[expr.plus]或类似的§5.5)。 - chris
1
这可能有助于回答您的问题:https://dev59.com/LHE85IYBdhLWcg3wikEu - Aiden Deom
1
因为它们是指向本地类型的指针,所以简单地增加指针应该是安全的(请记住,您的代码正在增加四个浮点数,而不是四个字节)。只有当它们指向无效地址时,才可能变成未定义行为,如果您在此期间对它们进行解引用。 - inetknght
2
我猜递增指针值就是这样的:通过其类型的sizeof()在内存中递增一个有效数字,不知道怎么会导致段错误。但我并不100%确定。 - Emile Vrijdags
3
顺便说一句,我非常确定在超过“指向结尾后一个元素”的指针时不断增加指针的行为是未定义的,即使没有对其进行解引用。只是想澄清一下。话虽如此,这样做很可能会奏效。 - chris
显示剩余7条评论
2个回答

8

第5.7节中的第5段规定了这一点 - 即使您从未解引用指针,加法本身的结果也是未定义的,因此程序无效。

如果指针操作数和结果都指向同一数组对象的元素或超出数组对象的最后一个元素,则评估不应产生溢出;否则,行为是未定义的。

即使它被允许,出现segfault的可能性非常小,但仍然是未定义的,具有所有相关含义。


4
如果仅仅将无效的引用赋值给指针是一个问题,那么将其初始化为NULL也会是一个问题。因此,对于您具体的问题,答案是“否”。

1
我相信,无效指针和空指针实际上是有区别的。我认为,标准中存在一些歧义,使得某些人渴望以这样的方式阅读它,即仅仅使指针无效就会触发未定义行为(类似于非定义术语“使用”)。然而,我不是语言律师,无法争论这个案例。 - SergeyA
空指针是一个有效的指针值。(“对象指针类型的有效值表示内存中字节的地址(1.7)或空指针”——3.9.2 复合类型。) - molbdnilo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接