int main()
{
int *p,*q;
p=(int *)1000;
q=(int *)2000;
printf("%d:%d:%d",q,p,(q-p));
}
输出
2000:1000:250
1.我无法理解p=(int *)1000;
行,这是否意味着p指向1000地址位置?如果我*p=22
怎么办这个值存储在1000地址并覆盖现有值?如果它覆盖了该值,那么如果另一个程序正在使用1000个地址空间怎么办?
q-p=250
? 编辑:我尝试printf("%u:%u:%u",q,p,(q-p));
输出相同
int main()
{
int *p;
int i=5;
p=&i;
printf("%u:%d",p,i);
return 0;
}
输出
3214158860:5
答案 0 :(得分:4)
这是否意味着p指向1000地址位置?
是
如果我这样做* p = 22
它正在调用未定义的行为 - 您的程序很可能会因为段错而崩溃。
请注意,在现代操作系统中,地址是虚拟的 - 您不能像这样覆盖其他进程的地址空间,但您可以尝试写入自己进程的地址空间中的无效内存位置。
q-p = 250怎么样?
因为指针算法的工作方式与此类似(为了与数组索引兼容)。两个指针的差异是它们的值除以sizeof(*ptr)
的差值。同样,将n
添加到ptr
类型的指针T
会产生数值ptr + n * sizeof(T)
。
这是否意味着编译器使用的地址是整数?
“编译器使用”部分甚至不需要。地址是整数,它只是C中的一个抽象,我们有很好的指示来缓解我们的生活。如果你在汇编中编码,你只需将它们视为无符号整数。
顺便说一下,写
printf("%u:%d", p, i);
也是未定义的行为 - %u
格式说明符需要unsigned int
,而不是指针。要打印指针,请使用%p
:
printf("%p:%d", (void *)p, i);
答案 1 :(得分:1)
是的,用*p=22
写入1000地址。
q-p
是250因为int的大小是4所以它是2000-1000 / 4 = 250
答案 2 :(得分:1)
p = (int *) 1000
的含义是实现定义的。但是,在典型的实施中,它会使p
指向地址1000
。
之后执行*p = 22
确实会尝试将22
存储在地址1000
。但是,在一般情况下,此尝试将导致未定义的行为,因为您不允许仅将数据写入任意内存位置。您必须以某种方式分配内存才能使用它。在您的示例中,您没有在地址1000
上分配任何内容。这意味着您的程序很可能只会崩溃,因为它试图将数据写入未正确分配的内存区域。 (此外,在许多平台上,为了通过指针访问数据,这些指针必须指向正确的对齐位置。)
即使您以某种方式成功地在地址22
处写1000
,但这并不意味着它会以任何方式影响“其他程序”。它会在一些旧平台上(比如DOS,一个例子)。但现代平台为每个正在运行的程序(进程)实现独立的虚拟内存。这意味着每个正在运行的进程都有自己独立的地址1000
,并且无法看到其他程序的地址1000
。
答案 3 :(得分:0)
是的,p
指向虚拟地址1000.如果您使用*p = 22;
,则可能会出现细分错误;通常,整个前1024个字节对于读取或写入无效。假设您有虚拟内存,它不会影响另一个程序;每个程序都有自己的虚拟地址空间。
q - p
的值是两个地址之间sizeof(*p)
或sizeof(*q)
或sizeof(int)
的单位数。
答案 4 :(得分:0)
将任意整数转换为指针是未定义的行为。任何事情都可能发生,包括任何事情,分段错误或无声地覆盖其他进程的内存(现代虚拟内存模型中不太可能)。
但我们过去常常在DOS模式下使用这样的绝对地址来访问中断表和BIOS变量:)
关于q-p == 250
,它是指针算术的语义结果。显然sizeof int
在你的系统中是4。因此,当您向int指针添加1时,它实际上会增加4,因此它指向下一个int
而不是下一个字节。此行为有助于阵列访问。
答案 5 :(得分:-1)
does this mean that p is pointing to 1000 address location?
是肯定的。但是这个1000地址可能属于其他一些进程地址。在这种情况下,你非法访问另一个进程的地址空间的内存。这可能导致分段错误。