指针类型转换

时间:2012-11-20 06:56:12

标签: c

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个地址空间怎么办?

  1. 如何q-p=250
  2. 编辑:我尝试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
    
    1. 这是否意味着编译器使用的地址是整数?正常整数和地址整数之间没有区别?

6 个答案:

答案 0 :(得分:4)

  

这是否意味着p指向1000地址位置?

  

如果我这样做* p = 22

它正在调用未定义的行为 - 您的程序很可能会因为段错而崩溃。

请注意,在现代操作系统中,地址是虚拟的 - 您不能像这样覆盖其他进程的地址空间,但您可以尝试写入自己进程的地址空间中的无效内存位置。

  

q-p = 250怎么样?

因为指针算法的工作方式与此类似(为了与数组索引兼容)。两个指针的差异是它们的值除以sizeof(*ptr)的差值。同样,将n添加到ptr类型的指针T会产生数值ptr + n * sizeof(T)

Read this on pointers.

  

这是否意味着编译器使用的地址是整数?

“编译器使用”部分甚至不需要。地址整数,它只是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)

  1. 是的,p指向虚拟地址1000.如果您使用*p = 22;,则可能会出现细分错误;通常,整个前1024个字节对于读取或写入无效。假设您有虚拟内存,它不会影响另一个程序;每个程序都有自己的虚拟地址空间。

  2. 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地址可能属于其他一些进程地址。在这种情况下,你非法访问另一个进程的地址空间的内存。这可能导致分段错误。