在C语言中传递指针地址与指针
我对这两段代码有点困惑: 版本1:(编译后给出警告) 输出:在C语言中传递指针地址与指针,c,pointers,C,Pointers,我对这两段代码有点困惑: 版本1:(编译后给出警告) 输出: Address of a: 5770a18c Before: 5770a18c After: 5770a18d Address of a: cc29385c Before: cc29385c
Address of a: 5770a18c
Before: 5770a18c
After: 5770a18d
Address of a: cc29385c
Before: cc29385c
After: cc293860
第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: 5770a18c
Before: 5770a18c
After: 5770a18d
Address of a: cc29385c
Before: cc29385c
After: cc293860
如果我在通过引用传递时正确理解了C中的指针,那么我们正在创建一个指向该位置的指针。这允许我们通过解引用运算符更改指针所持有地址处的值
但是,如果我们想更改指针所持有的值,我们就使用指向指针的指针。我们传递指针的地址,并创建一个新指针来保存所述地址。如果我们想更改该值,我们可以使用解引用操作符访问指针(在别处定义)的值
希望我在正确的轨道上,但我正在努力想象版本1具体发生了什么。主要是,我想了解这两个程序在组成和输出方面的差异。我假设版本1仍然是指向指针的指针,但是为什么两个程序的递增值不同呢?如果版本1成功增加了ptr的值(我怀疑不是),为什么我找不到具有相同语法的代码?我想我错过了一些非常琐碎的事情。。。非常感谢您提供的任何帮助根据您的输出,您似乎正在编译一个32位系统,其中地址和
int
大小相同
当您在类型为int
的情况下增加*ptr
处的值时,它只需加1
当*ptr
解析为int*
时,它将增加sizeof(int)
,因为在这种情况下,当前地址的值是4字节长,因此,我们必须将地址增加int
消耗的字节数,以便我们指向下一个int。请注意,只有在后续地址实际分配了内存时,这样做才有效。
通常,当被调用方需要修改要指向的地址时,您会传递一个
T**
,例如,被调用方执行malloc()
,为指针分配空间。&ptr
是指向指针的指针,但传递给func()的是
是以实现定义的方式从&ptr
转换而来的指向int
的指针。然后,*ptr2+=1
递增int
,并将1添加到ptr2
所指向的内容中(main()
中的指针ptr
,它最终与系统中的“int”具有相同的重新表示形式)
在版本2中,指向指针的指针被正确地传递到func()
。因此,执行指针算术运算,并将int
的大小添加到地址中
请注意,通过将类型错误的数据传递到printf()
,调用了未定义的行为。打印指针的正确方法如下所示:
printf("Before: %p\n", (void*)ptr);
如您所见,将指针投射到
void*
并使用%p
说明符。在C中没有“按引用传递”,在第一个示例中,您传递了int**
,但将其当作函数中的int*
使用。在这两种情况下func
都会增加ptr2
指向的值,在这两种情况下,这都是指针的值ptr
。第1种情况通常也会发出一条警告,提示将int**
传递给需要int*
的函数,您不应忽略该警告。最后,%x
不是指针的正确格式说明符,因此printf
在技术上调用UB(未定义的行为)。感谢您的回复,这些答案非常好,已经解决了我的主要问题。我注意到,如果我还将指向“a”的指针传递给func(),那么现在可以设置ptr2='a',给ptr调用方中a的地址位置。我猜如果我用提供的地址修改指针值,使用版本1是可以的?你能解释一下当被叫方执行内存分配时,为什么我们要传递ptr**vs ptr*?这与设置数据有关吗?我可能需要做一些刷新/进一步的阅读。C中的参数总是按值传递-如果我传递一个int
,那么函数将收到一个值的副本。如果我传递一个int*
,它将收到地址的副本。