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