我有一个关于C / C ++处理盲目递增指针的行为的查询。
所以,我有一个指向int的指针作为函数的参数
func(int* thePointer) {...
我在该函数中有一个循环
while(*thePointer) {
++thePointer;
}
据我所知,只要存在超出此指针的内存中的int
,循环就会继续,但如果内存属于另一种内存类型的一部分怎么办?假设你增加到double
的前4个字节。在这种情况下,int仍会有一个值/循环吗?
免责声明:我知道这很可能是不好的做法。这是一个纯粹的学术问题。
答案 0 :(得分:7)
在内存中没有 int 或 double 之类的东西。内存只是内存:字节的占位符。
所以,如果你继续递增指向 int 的指针,你将指向内存中接下来的四个字节,就是这样。如果您尝试通过指向整数的指针使用内存的该部分,您可能会将其内容视为 int 。
最终,您将指向未分配给您的流程的内存区域,并且您的程序将以 SEGMENTATION FAULT 退出。
答案 1 :(得分:4)
ISO 14882,第5.7节:
$ 4就这些运营商而言,a 指向非阵列对象的指针表现出来 与指向第一个的指针相同 长度为1的数组的元素 对象的类型作为其元素 类型。
$ 5当一个表达式有 积分类型被添加到或 从指针中减去结果 具有指针操作数的类型。 如果指针操作数指向一个 数组对象的元素,以及 数组足够大,结果 指向偏离的元素 这样的原始元素 下标的差异 结果和原始数组元素 等于积分表达式。在 换句话说,如果表达P 指向数组的第i个元素 对象,表达式(P)+ N. (等价地,N +(P))和(P)N(其中 N的值为n)指向, 分别是第i + n和第i 提供了数组对象的元素 它们存在。而且,如果 表达式P指向最后一个 数组对象的元素, 表达式(P)+1点过去了 数组对象的最后一个元素,和 如果表达式Q指向一个过去 数组对象的最后一个元素, 表达式(Q)1指向最后一个 数组对象的元素。如果两者 指针操作数和结果 指向同一个数组的元素 对象,或者是最后一个元素之后的对象 数组对象的评估 不得产生溢出; 否则,行为未定义。
答案 2 :(得分:2)
但是如果内存属于另一种内存类型的一部分怎么办?假设你增加到double的前4个字节。在这种情况下,int仍会有一个值/循环吗?
编译器不关心那里有什么类型的内存。你可以增加到你选择的任何类型的内存,它会没事的。
当您尝试访问该内存位置时,它只会出现问题。如果您尝试在指针位置设置一个值,并且它不是分配给您的进程的内存,它将崩溃。
只要该位置的内存属于您(即:您的程序已分配它),您就可以进行设置。话虽这么说,如果内存位置不是你所处理的整数值,你很可能会破坏其他对象的状态,这最终会导致坏事发生。
答案 3 :(得分:1)
我加入了所有人。考虑到这一点,即使有学术目的,也为魔鬼打开了大门。无论内存是什么,指针都会每次都提前调整int的大小。访问时,你会得到垃圾。
答案 4 :(得分:1)
如果访问内存(读取或写入),移动指针是危险的。
将指针移动到当前对象的末尾并取消引用该对象是未定义的行为。
单个对象:
int x;
int* xp = &x;
xp++; // Now pointing past the object.
int y = *xp; // Undefined behavior.
阵列:
int x[10];
int xp = x;
while(*xp)
{ ++xp; // Works fine the first 9 times.
} // After that it is UB to access the memory pointed at by xp
注意:循环播放
while(*xp) // This continues while the memory pointed at
// is not zero. As soon as a zero is found in memory
// the loop exits.
答案 5 :(得分:0)
如果你继续增加,最终你将得到一个SIGSEGV或Windows道德等价物。然而,在你到达那里之前,你很可能会参加Cooke的巡演,了解VM中的其他任何内容。其他变量,废弃的三明治包装纸,等等。
这样的循环不仅仅是'糟糕的做法',它们是攻击的主要来源。
答案 6 :(得分:0)
上面的代码与内存中有多少int
无关。你的代码一直运行,直到找到一个设置为零的整数的等价物。
是的,这是非常糟糕的做法。结果未定义。您很可能会遇到不属于预期数组的内存。而且你很有可能进入导致处理器故障的内存。