[英]Are memory addreses portable in C?
假设我们有程序 1...
./程序1
int main(int argc, char *argv[])
{
int *i;
*i = 10;
printf("%lld", i);
return 0;
}
现在程序2...
./program2 program1output 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 *
转换为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 标准定义的。
原则上,应用程序在其自己的/私有内存上运行。 有多种方法可以在不同的进程之间共享内存,但这需要特殊的机制来克服上述“主要”(例如内存映射文件)。 有在短期看,例如, 该文章共享内存。
在您的情况下,程序一将结束并且其内存不再可用; 并且您访问它的方式绝对不是访问共享内存所需的“特殊机制”之一:
尽管整数值可以转换为指针值,但仅当整数值最初从指针转换为有效对象时,访问该指针才有效。 在您的示例中情况并非如此,因为在t = (int*)atoll(argv[1]);
计算的积分值t = (int*)atoll(argv[1]);
从未指向当前程序中的有效对象。
通常,内存地址与进程相关联,因为每个进程可能有自己的内存空间。 因此,地址是虚拟地址而不是物理地址,这意味着它们是对进程内存空间中某个位置的引用,而不是对芯片上某个位置的引用。
(并非所有环境都有虚拟内存。例如,嵌入式系统可能没有。)
如果有两个程序在同一个进程中运行,则可以在它们之间传递一个指针。 例如,主程序可以传递一个指向它加载的动态链接库的指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.