将指针地址vs指针传递给C

时间:2016-08-18 02:27:50

标签: c pointers

我对这两段代码感到有些困惑:

版本1 :(编译后发出警告)

int func(int *ptr2)
{
    *ptr2 += 1;
}

int main()
{
    int a = 5;
    int *ptr = &a;

    printf("Address of a: %x\n", a);
    printf("Before: %x\n", ptr);
    func(&ptr);
    printf("After: %x\n", ptr);
    return 0;
}

输出:

Address of a: 5770a18c
Before: 5770a18c                                                                                                           
After: 5770a18d 

版本2:

int func(int **ptr2)
{
    *ptr2 += 1;
}

int main()
{
    int a = 5;
    int *ptr = &a;

    printf("address of a: %x\n", &a);
    printf("Before: %x\n", ptr);
    func(&ptr);
    printf("After: %x\n", ptr);
    return 0;
}

输出:

Address of a: cc29385c
Before: cc29385c                                                                                                           
After: cc293860

如果我在通过引用传递时正确理解C中的指针,我们将创建一个指向该位置的指针。这允许我们通过解引用运算符更改指针所占地址的值。

但是,如果我们想要更改指针所持有的值,我们使用指向指针的指针。我们传递指针的地址并创建一个新指针来保存所述地址。如果我们想要更改值,我们使用dereference运算符来访问指针(在其他地方定义)的值。

希望我走在正确的轨道上,但我正在努力想象一下具体版本1的情况。主要是,我想了解这两个程序之间的构成和输出的差异。我假设版本1仍然是指向指针的指针,但为什么两个程序之间的递增值不同?如果版本1成功递增ptr的值(我怀疑不是),为什么我找不到具有相同语法的代码?我想我在这里遗漏了一些相当微不足道的东西...感谢任何帮助

2 个答案:

答案 0 :(得分:0)

根据您的输出,您似乎正在编译32位系统,其中地址和int具有该大小。

当您使用*ptr类型的int增加值时,它只会添加1。

*ptr解析为int*时,它会增加sizeof(int),因为在这种情况下当前地址的值是4个字节长,所以我们必须增加地址int消耗的字节数,以便我们指向下一个int。 请注意,只有在后续地址实际分配了内存时,此操作才有效。

通常,当被调用者需要修改地址以指向时,传递T** - 例如,被调用者执行malloc()为指针分配空间。

答案 1 :(得分:0)

&ptr是指向指针的指针,但传递给func()的是指向实现定义方式的int转换的&ptr指针。然后,*ptr2 += 1;递增int并将ptr2指向的内容(ptr中的指针main()加1,最终具有相同的表示形式。你系统中的int。)

在版本2中,指向指针的指针正确传递给func()。因此,执行指针aritimetic并将int的大小添加到地址。

请注意,您通过将具有错误类型的数据传递给printf()来调用未定义的行为。打印指针的正确方法是这样的:

printf("Before: %p\n", (void*)ptr);

如您所见,将指针投向void*并使用%p说明符。