我对这两段代码感到有些困惑:
版本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的值(我怀疑不是),为什么我找不到具有相同语法的代码?我想我在这里遗漏了一些相当微不足道的东西...感谢任何帮助
答案 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
说明符。