我正在尝试更多地探索指针,下面是我正在尝试的一段示例代码
这有效:
int *arth, art;
art = 100;
arth = &art;
printf("arth address is %p arth+1 value is %d", arth, *(arth + 1));
现在,如果我尝试向关节添加大量数字,我会获得读取访问权限
这不是:
printf("arth address is %p arth+1 value is %d", arth, *(arth + 1000));
错误:
抛出异常:读取访问冲突。 关节是0xC9C5EFF964。发生
ASK:
有人可以解释为什么在添加1时这是有效的,而不是在添加1000
答案 0 :(得分:3)
因为此*(arth + 1)
调用未定义的行为!
未定义的行为是程序可以意外执行的行为。在您的情况下,可能在您的第一个代码段中工作,在第二个代码段中。或者,今天两种情况都可能根本不起作用。明天它可以。在你的机器上它可能会起作用,在我的机器中......可能不是!详细了解UB。
您正在访问指针不应访问的内存。
当您添加1时,您可能(非)幸运并且您访问了您的程序拥有的内存,因此您可以从警察(操作系统)中获取内存。
当您添加1000时,您将退出程序的段,从而导致分段错误或访问冲突(您将其命名为!)。
可视化:
您的行为类似arch
指向数组,当array[i]
有效时,array[i + 1]
也有效(假设i + 1不大于或等于数组的大小)
但是,arch
只是将指向一个变量,仅此而已!
C允许你整天做指针算术,但你要对此结果负责。在您的情况下,两个增量在语法等方面都是有效的,但调用未定义的行为,这是一个逻辑错误(导致运行时无效,可以说)。
答案 1 :(得分:2)
arth
指向int
的单个实例。将任何非零值添加到arth
,然后取消引用该新指针值将读取原始int
范围之外的内存位置。这会调用undefined behavior。
对于未定义的行为,任何事情都可能发生。您的程序可能会崩溃,它可能会输出奇怪的结果,或者它可能似乎正常工作。你没有在*(arth + 1))
案件上崩溃但在*(arth + 1000))
上崩溃的事实就是一个例子。
仅仅因为程序没有崩溃并不意味着它没有做错事。
答案 2 :(得分:1)
Arth指向一个整数,但是关节+ 1并没有指向你在代码中定义的任何地方,也没有指向关节+ 1000。
实际上,C允许你将指针增加到一个元素超过内存分配,因此技术上允许使用关节+ 1,但是关节+ 1000不是。关节+ 1000的行为是不确定的,所以任何事情都可能发生。在你的情况下,这是一个错误。答案 3 :(得分:1)
*(关节+ 1000),类似于关节[1000],(关节+ 1)等于关节[1]。(关节+ 1000),您尚未分配或初始化内存中的任何空间,因此编译器将抛出未定义的行为,并且没有这样的已分配数据到该位置。
答案 4 :(得分:0)
无论是*(关节+ 1)还是(关节+1000)都是无效的,因为你正在访问根本没有分配的内存。它可能因未定义的行为而起作用。用valgrind运行并检查valgrind登录它将始终报告无效读取是否*(关节+1)或*(关节+1000)。当您添加任何指针相关代码时,始终运行valgrind。