在C语言中,如何给指针赋值?
我正在为指令集架构创建一个模拟器,我需要实现一个堆栈结构。我决定我的%eip、%ebp和%esp将是int指针。但是,在某些情况下,我需要在堆栈上存储内存地址,在这种情况下,该内存将被编码为整数值。但是当我返回这个值时,我需要把它放回我的指令指针中,它被实现为一个int指针。C不允许我将整数分配给int指针,因此我无法从“堆栈”中恢复这些内存地址。有什么建议吗 它是实现定义的,但如果整数宽度不小于指针,则可以这样使用 有人说使用在C语言中,如何给指针赋值?,c,C,我正在为指令集架构创建一个模拟器,我需要实现一个堆栈结构。我决定我的%eip、%ebp和%esp将是int指针。但是,在某些情况下,我需要在堆栈上存储内存地址,在这种情况下,该内存将被编码为整数值。但是当我返回这个值时,我需要把它放回我的指令指针中,它被实现为一个int指针。C不允许我将整数分配给int指针,因此我无法从“堆栈”中恢复这些内存地址。有什么建议吗 它是实现定义的,但如果整数宽度不小于指针,则可以这样使用 有人说使用ptrdiff_t和NULL指针作为参考更方便、更安全 ptrdif
ptrdiff_t
和NULL
指针作为参考更方便、更安全
ptrdiff_t myptrdiff = myptr - (type_of_myptr *)NULL;
myptr = myptrdiff + (type_of_myptr *)NULL;
我决定我的%eip、%ebp和%esp将是int指针
这不是一个合理的架构决策。你需要重新考虑一下
int*
的宽度为64位。相比之下,所有这些寄存器定义为32位宽。使用64位指针存储其值将导致意外行为int*
将在许多系统上导致未对齐的访问故障请注意,当您在可能不是32位平台的平台上模拟32位系统时,您将需要某种方式将模拟系统中的地址转换为主机进程中的“真实”地址。有许多不同的方法可以做到这一点;哪一个最适合您将取决于您的具体目标。要将
int
值分配给int*
对象,请使用显式强制转换,如下所示:
destination = (int *) source;
您的问题是“C不允许我将整数指定给int指针”,但无法确切说明问题所在。您可能从编译器获得了一些诊断信息。这是因为将
int
值指定给int*
对象违反了C标准的赋值约束。上面的代码展示了如何解决这个问题
这就解决了编译器诊断的直接问题。但是,使用
int
值作为指针的容器可能存在各种问题,包括陷阱值的可能性以及指针和整数大小之间的差异。假设int
和int*
的大小相同,使用int
来保存int*
不太可能有效,但您应该确定C实现的属性。“C不允许我将整数分配给我的int指针”-到底发生了什么?你试过投吗int*iptr=(int*)您的_int
需要您的代码。没有代码就无能为力。也许您可以转换uintptr\u t
,这是一种在
中定义的类型,当它在您的计算机上可用时(通常是可用的,尽管理论上是可选类型)。或者您可能只需要添加一个显式强制转换。如果您收到关于不同大小的整数和指针的警告,那么您需要更加担心。对这些寄存器使用无符号非指针类型更有意义,因此您可以对它们执行无符号算术,而无需强制转换。对于您执行的几乎所有指令,您都需要这个。毕竟,在访问实际数据之前,您可能需要进行一些地址转换。您也不太可能在模拟器和模拟器运行的代码之间混淆地址空间。还要确保您的无符号类型足够宽,可以存储模拟体系结构的地址。这是关于OP的代码和设计的注释,而不是对他们问题的回答。它可以是注释,但不应作为答案输入。此外,关于第2项,OP的目的是在int
对象中存储指针,而不是在int*
对象中存储任意指针。他们之所以提到int*
,是因为他们的%eip、%ebp和%esp都有int*
,但他们要存储的指针将位于其中一个指向的int
中。@EricPostChil重新阅读OP关于他们将数据从堆栈弹出到这些寄存器的问题的描述。我很清楚,他们试图使用指针本身——而不是它所指向的值——作为寄存器值。关于弹出数据,问题是“…我需要把它放回指令指针,它被实现为int指针。”因此,他们没有使用int*
作为任意值的存储容器。它们正在还原为int*
某个值,该值是为int*
准备的,即%eip。他们的“%eip”是int*
的事实表明,他们正在模拟的ISA具有固定的指令大小,因此它的所有有效值也都是有效的int*
值。在任何情况下,他们都不会使用int*
作为任意值的载体,而只是用于指定的值。类似地,您对ModRM等的评论表明您采用的是x86体系结构,OP没有认可