【问题标题】:Can an address be assigned to a variable in C?可以将地址分配给C中的变量吗?
【发布时间】:2012-11-13 14:01:22
【问题描述】:

是否可以在内存中为变量分配你想要的地址?

我尝试这样做,但我收到一个错误,因为“需要左值作为赋值的左操作数”。

int main() {
  int i = 10;
  &i = 7200;
  printf("i=%d address=%u", i, &i);
}

我的方法有什么问题? 在 C 语言中有什么方法可以将我们想要的地址分配给变量吗?

【问题讨论】:

  • 等等,你想把内存中的i移动到地址7200吗?
  • 我认为不可能。
  • 是的!我绝对希望变量 i 存储在 7200。

标签: c pointers memory-address addressof address-operator


【解决方案1】:

C 语言无法为您提供将名称“附加”到特定内存地址的方法。 IE。您无法告诉语言特定变量名称应该引用位于特定地址的左值。因此,如前所述,您的问题的答案是“否”。故事结束。

此外,从形式上讲,没有其他可移植的方式来处理 C 中的特定数字地址。语言本身没有定义可以帮助您做到这一点的功能。

但是,特定的实现可能会为您提供访问特定地址的方法。在典型的实现中,将整数值A 转换为指针类型会创建一个指向地址A 的指针。通过取消引用此类指针,您可以访问该内存位置。

【讨论】:

    【解决方案2】:

    我认为 '&' in &a 在我认为的编译时评估 i 的地址是一个虚拟地址。因此根据您的编译器,它不是左值。改用指针

    【讨论】:

      【解决方案3】:

      假设您在现代操作系统上使用 x86 类型的处理器,则无法写入 aribtray 内存位置; CPU 与操作系统协同工作以保护内存,以便一个进程不会意外(或有意)覆盖另一个进程的内存。允许这样做会带来安全风险(请参阅:缓冲区溢出)。如果您仍然尝试这样做,则会收到“分段错误”错误,因为 OS/CPU 会阻止您执行此操作。

      有关这方面的技术细节,您可以从1、2 和3 开始。

      相反,您使用malloc 请求操作系统给您一个可以写入的内存位置。在这种情况下,操作系统内核(通常是允许写入任意内存位置的唯一进程)找到一个空闲的内存区域并将其分配给您的进程。分配过程还会将该内存区域标记为属于您的进程,以便您可以对其进行读写。

      但是,不同的操作系统/处理器架构/配置可能允许您写入任意位置。在这种情况下,此代码将起作用:

      #include <stdio.h>
      void main() {
        int *ptr;
        ptr = (int*)7000;
        *ptr = 10;
        printf("Value: %i", *ptr);
      }
      

      【讨论】:

      • 请务必注意,您可以请求操作系统更改内存页面的权限以允许您写入(或从中执行,或两者兼而有之)。这仍然在进程的虚拟内存映射中,但允许您写入更多位置。这是有多少 JIT 编译系统起作用的基础。
      • 这可能会导致seg-fault。
      【解决方案4】:

      这是不可能的,也许可以通过编译器扩展来实现。但是,您可以访问所需地址的内存(如果您的进程可以访问该地址):

      int addr = 7200;
      *((int*)addr) = newVal;
      

      【讨论】:

      • 这可能会导致seg-fault。
      • 谢谢,这就是我提到的原因:“(如果您的进程可以访问该地址)”
      【解决方案5】:

      使用 ldscript/linker 命令文件。但是,这将在链接时分配,而不是在运行时分配。

      链接器命令文件语法很大程度上取决于特定的编译器。因此,您需要为您的编译器搜索链接器命令文件。

      近似的伪语法有点像这样:

      In linker command file:
      .section start=0x1000 lenth=0x100 myVariables
      In C file:
      #pragma section myVariables
      int myVar=10;
      

      【讨论】:

        【解决方案6】:

        不直接。 你可以这样做: int* i = 7200; .. 然后使用 i (ie. *i = 10) 但你很可能会崩溃。这仅在使用已知内存地址进行低级开发时才有意义 - 设备驱动程序等。

        【讨论】:

        • 为了安全地为您的变量使用特定地址,请使用链接器命令文件。 (详情请参阅下面的答案。)
        【解决方案7】:

        可能无法确定变量将具有哪个地址。但是作为最后的希望,有一个叫做“指针”的东西,所以你可以修改地址 7200 上的值(尽管这个地址可能无法访问):

        int *i = (int *)7200;
        *i = 10;
        

        【讨论】:

          【解决方案8】:

          不便携。但是一些编译器(通常用于嵌入式世界)有扩展来做到这一点。

          例如在 IAR 编译器上(此处为 MSP430),您可以这样做:

          static const char version[] @ 0x1000 = "v1.0";
          

          这会将对象version 放在内存地址0x1000。

          【讨论】:

            【解决方案9】:

            没有。

            即使你可以,7200 也不是指针(内存地址),它是一个 int,所以无论如何这都行不通。

            【讨论】:

            • 解释原因会很有帮助。我自己也不确定为什么,但我有一个大致的想法,它可能与虚拟到真实的寻址有关。
            • >> “7200 不是指针(内存地址),它是一个 int,所以无论如何这都行不通”:不同意。这就是为什么它必须被铸造。然后它就可以工作了。
            • 仅适用于奇怪的“工作”值。它不是标准的 C。该语言不保证 (char *)7200 会做任何明智的事情。
            • 这是嵌入式系统中非常标准的做法。
            • 查看这个问题,例如将整数转换为指针...stackoverflow.com/questions/13763006/…
            猜你喜欢
            • 2018-02-24
            • 1970-01-01
            • 1970-01-01
            • 2015-09-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多