c - C 语言中内存地址可以移植吗?

标签 c pointers

假设我们有程序 1...

./程序1

int main(int argc, char *argv[])
{
  int *i;
  *i = 10;
  printf("%lld", i);
  return 0;
}

现在程序 2...

./program2 程序1输出 10

int main(int argc, char *argv[])
{
  int *t;
  t = (int*)atoll(argv[1]);
  *t = atoi(argv[2]);
  return 0;
}

这行得通吗?不同程序之间可以共享内存地址吗?

最佳答案

C 标准未定义此行为。在任何通用多用户操作系统上,每个进程都有自己的虚拟地址空间。除了某些共享内存之外,分配给进程的所有内存都与分配给其他进程的内存分开:

  • 只读数据可以在进程之间共享,特别是运行同一可执行文件的两个进程的指令和常量数据以及共享库的指令和常量数据。该数据可能在不同的进程中具有相同的地址或不同的地址(取决于各种因素,包括代码是否与位置无关以及是否使用地址空间布局随机化)。
  • 默认情况下,某些操作系统还会将系统范围的共享数据映射到进程中。
  • 可以通过进程的显式请求来映射共享内存段,从而在进程之间共享内存。这些段可能会也可能不会出现在不同进程中的同一虚拟地址处。 (映射共享内存的请求可能会请求某个地址,在这种情况下,不同的进程可以安排使用相同的地址,或者可以让映射软件选择地址,在这种情况下,不同的进程不能依赖于接收相同的地址分配.)

在专用操作系统中,不同的进程可以共享一个地址空间。

补充

这不是正确的代码:

int *i;
*i = 10;

声明int *i;i定义为一个指针,但没有为其赋值。那么使用 *i 是不正确的,因为它试图引用 i 指向的位置,但 i 尚未被分配来指向任何东西。

要定义 int 并使其地址在输出中可见,您可以定义 int i;,然后打印 &i

这不是打印地址的正确方法:

printf("%lld", i);

要打印地址,请将其转换为 void * 并使用 %p 对其进行格式化。格式化的结果是实现定义的:

printf("%p", (void *) &i);

这不是重建地址的好方法:

int *t;
t = (int*)atoll(argv[1]);

printf 一样,类型应为 void *,并且尝试使用 atoll 进行转换时会出现问题。 C 标准并不保证它一定能工作;使用 %p 打印生成的格式可能不是正常的整数格式。相反,请使用 %p 说明符和 sscanf:

void *temp;
if (1 != sscanf(argv[1], "%p", &temp))
    exit(EXIT_FAILURE);
int *t = temp;

本地址来自其他进程时,sscanf 转换的行为不是由 C 标准定义的。

关于c - C 语言中内存地址可以移植吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59814733/

相关文章:

c - 在 visual studio 中跟踪变量的变化

c++ - 是否可以返回指向类中声明的结构的指针?

c - 如何将文本文件中一行中的整数分配给c中的变量?

c++ - c++ final 非虚拟类是否被重新解释为可以安全使用的数组?

c - C 程序的堆栈和堆内存

将 float 转换为相应的整数

c - 使用文件执行复制命令我的代码正在复制垃圾?

c - C中的条件语句和控制语句有什么区别吗?

c++ - 使用自己的指针遍历数组元素

c - 如何为结构、结构内的结构数组正确分配内存,并将该数组作为参数传递