我想声明一个指针,让它拥有一个自定义地址,然后为其分配一个值:
void main()
{
char *ptr;
ptr = (char *)0x123123; //the assignment works perfectly with a cast
printf("%p\n", ptr); //and the pointer indeed holds the address it's supposed to
*ptr = 'a'; //but this breaks
puts("2");
}
最初,我认为原因是因为我试图取消引用未初始化的内存。但实际上我怀疑是否确实如此,因为此some_type *some_ptr = &some_variable;
可以正常工作,因此交易必须是我为其分配的地址。
然后我想,以同样的方式,3
或'a'
或"alpine"
都是常量,(char *) 0x123123
也必须是常量。 const
-s不能在C语言中进行编辑,但这仍然不能做到,因为更改const
值的尝试不会编译。
第三个假设是这样的地址必须不可用,但这也没有道理,因为无论我给出的地址还是pointer
的类型,第4行始终有效。
答案 0 :(得分:6)
第三个假设是该地址必须不可用
是正确的:在现代OS(都具有内存保护)上,您不能写入任意内存地址。
过去可以访问未使用虚拟内存的操作系统上的任何内存(例如MS-DOS
),但通常这是一个非常糟糕的主意 –允许随机程序破坏操作系统状态,并且需要非常频繁地重新启动。
但这还是没有道理的,因为无论我给出的地址还是指针的类型,第4行始终有效。
您混淆了两个不同的操作:打印一个地址(无论该地址是什么)和取消引用一个地址,即读取或修改存储的值地址(仅适用于有效地址)。
区别类似于“您可以打印地址吗?” (例如“ 123 Main Street,SomeTown和SomeCountry”)和“您可以在该地址输入房屋吗?” (以上地址不可能,因为地球上没有“ SomeCountry”)。即使该地址有效,例如“ 1600 Pennsylvania Ave NW,Washington,DC 20500”,您可能仍然无法输入。
答案 1 :(得分:2)
OP在其他地方澄清说,这实际上是XY问题。
X问题:读取/写入任意内存位置。
Y问题:实现使用连续内存的链表。
当然,答案是:一个人必须实现自己完整的内存管理系统才能到达那里。
如:首先,您使用malloc()
来获取大块连续内存。然后,您可以在该内存块的内使用任意指针。但是,当然,您的代码必须跟踪已使用的地址。或在删除列表节点时正确“释放”。
棘手的部分是处理极端情况,例如:当您的最后一个“指针”用完时会发生什么?您是否在更大的区域malloc()并移动了内存中的所有数据?
最后:假设您不管理一个内存块,而是一个数组。 (链接列表的实现通常基于数组,因为这使某些事情变得容易得多)
答案 2 :(得分:0)
写到任意内存地址是危险的,现代操作系统不允许这样做,最好创建一个内存Blob并对其进行写入。
例如使用malloc:
ptr = malloc(32); // now you can write to this memory block and it perfectly legal
*ptr = 'a';