简体   繁体   English

将指针地址与指针传递给C中的指针

[英]passing a pointer address vs pointer to a pointer in C

I'm slightly confused between these two pieces of code: 我对这两段代码有些困惑:

version 1: (gives warnings after compiling) 版本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;
}

Output: 输出:

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

version 2: 版本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;
}

Output: 输出:

Address of a: cc29385c
Before: cc29385c                                                                                                           
After: cc293860

If I'm understanding pointers in C correctly when we pass by reference, we are creating a pointer to that location. 如果在通过引用传递时我正确地理解了C中的指针,那么我们正在创建指向该位置的指针。 This allows us to change the value at the address held by the pointer through the dereference operator. 这使我们可以通过取消引用运算符来更改指针所持有的地址处的值。

However, if we want to change the value held by a pointer, we use a pointer to a pointer. 但是,如果要更改指针持有的值,可以使用指向指针的指针。 We pass the address of the pointer and create a new pointer to hold said address. 我们传递指针的地址并创建一个新的指针来保存该地址。 If we want to change the value, we use the dereference operator to access our pointer's (defined elsewhere) value. 如果要更改该值,则可以使用解引用运算符访问指针(在其他位置定义)的值。

Hopefully I'm on the right track, but I'm struggling to visualize what's happening with version 1 specifically. 希望我走在正确的轨道上,但我一直在努力可视化版本1的具体情况。 Mainly, I'd just like to understand the difference in make-up and output between these two programs. 主要是,我只想了解这两个程序之间在化妆和输出方面的区别。 I assume version 1 is still a pointer to a pointer, but why are the incremented values different between both programs? 我认为版本1仍然是指向指针的指针,但是为什么两个程序之间的增量值不同? If version 1 is successfully incrementing ptr's value (which I suspect is not), why is that I cannot find code with the same syntax? 如果版本1成功增加了ptr的值(我怀疑不是),为什么我找不到具有相同语法的代码? I think I'm missing something fairly trivial here... Any help is appreciated 我想我在这里错过了一些琐碎的事情...任何帮助,我们感激不尽

Based on your output, you appear to be compiling for a 32-bit system where addresses and int are of that size. 根据您的输出,您似乎正在为32位系统进行编译,其中地址和int都具有该大小。

When you increment the value at *ptr with that type being int , it will simply add 1. 当您将*ptr的值递增为int ,它将简单地加1。

When *ptr resolves to an int* then it will increment by sizeof(int) because the value at the current address in this case is 4 bytes long, so we have to increase the address by the number of bytes that an int consumes so that we're pointing at the next int. *ptr解析为int* ,它将以sizeof(int)递增,因为在这种情况下当前地址的值是4个字节长,因此我们必须将地址增加一个int消耗的字节数,以便我们指的是下一个int。 Note that doing this is only valid if you actually have allocated memory at the subsequent address. 请注意,仅当您实际上已在后续地址中分配了内存时,此操作才有效。

Generally you pass a T** when the callee needs to modify the address to point to - such as say, the callee performs a malloc() to allocate space for the pointer. 通常,当被调用方需要修改指向的地址时,您会传递一个T** -例如,被调用方执行malloc()来为指针分配空间。

&ptr is a pointer to a pointer, but what is passed to func() is a pointer to int converted from &ptr in implementation-defined manner. &ptr是指向指针的指针,但是传递给func()是指向以实现定义的方式从&ptr转换为int的指针。 Then, *ptr2 += 1; 然后, *ptr2 += 1; is incrementing int and add 1 to what is pointed by ptr2 (the pointer ptr in main() , which eventually have the same reepresentation as `int in your system). 是递增int并将1加到ptr2指向的对象( main()的指针ptr ,它最终与系统中的`int一样具有重新表示形式)。

In version 2, the pointer to a pointer is correctly passed to func() . 在版本2中,指向指针的指针已正确传递给func() Therefore, pointer aritimetic is performed and the size of int is added to the address. 因此,执行指针算术运算,并将int的大小添加到地址中。

Note that you invoked undefined behavior by passing data having wrong type to printf() . 请注意,您通过将类型错误的数据传递给printf()来调用未定义的行为 The correct way to print pointers is like this: 打印指针的正确方法是这样的:

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

As you see, cast the pointer to void* and use %p specifier. 如您所见,将指针强制转换为void*并使用%p说明符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM