我想问一下作者,caf,从C语言中的函数和指针的理解
我意识到我不能在同一页上问这个问题。
我仍然对使用&;将指针的值传递给函数感到困惑。我一直认为Q只是传递Q的地址,如何将Q的值转换为int sqp(int*x)?
- 你应该通过评论来问,但不幸的是你没有足够的声誉来评论。在这里回答一些问题,在帖子上做一些编辑,以获得一些声誉,然后回到那里问同样的问题。结束投票(但不是结束投票),因为不清楚你在问什么。
- 5个答案/18分钟前提问=1.39个答案/5分钟。
- &用作前缀运算符时,表示"取的地址"。因此,&someIntVar返回的地址是int*(指向int的指针)。当您传递一个值的地址时,当然不会直接传递该值,但是该地址的接收者可以"取消引用"接收到的指针来获取(或设置)该值。
没有"翻译"。
你的功能
取一个参数,x,类型为int *,即"指向整数的指针"。
所以,要调用它,需要将指针传递给一个整数,即一个整数的地址。
&前缀运算符用于计算其参数的地址,因此可以执行以下操作:
1 2
| int foo = 4711;
sqp(&foo); |
用变量foo的地址调用sqp()函数。
在按引用调用的情况下,会传递一个地址,以便可以通过引用地址(即引用)进行更改;如果在参数中传递地址,则应该具有指向该地址的某种机制。指针是指向地址的东西,因此在调用时,如果传递了地址,则必须在定义中使用指针。离子指向它。例子。
1 2 3 4 5 6 7
| calling(&a); //passing address
void calling(int *b) //Pointing to address of 'a' via pointer 'b'
{
//some code
} |
就像你说的,&q将变量q的内存地址传递给函数,所以我们发送给函数的只是q的地址。函数不需要转换任何值,因为它直接访问原始值,因为它的地址存储在指针x中,并且每次您对*执行类似*x=7;的操作时,都会取消对变量的引用,这意味着它不修改变量x,而是修改任何ocx1〔2〕指向。
使用:
将EDOCX1的地址(0)作为函数int sqp(int *x)中的参数传递。
从现在开始,在这个函数内部,使用x就可以得到这个地址本身。
使用*x可以在内存中获得此地址中包含的值。
这就是我们如何在C中"模拟"pass by reference,通过值传递变量本身的地址作为函数中的参数。
- C中没有旁路引用,那么它是如何实现的?
- @哈克斯:事实上,我表达的方式似乎是错误的。改变它。谢谢!
那么让我们再看一下sqp函数定义:
1
| int sqp( int *x ) { ... } |
C中的声明基于表达式的类型,而不是对象;如果您有一个指向名为x的整数的指针,并且您希望访问被指向的整数值,则可以使用一元*运算符取消对x的引用,如下所示:
表达式*x的类型是int,因此变量x的声明编写为
当你听到有人使用"声明模仿使用"这个短语时,这就是他们的意思。
当我们调用函数时
表达式&q生成q的地址,表达式类型为int *。sqp中的参数x接收该地址值。
因此,sqp中的表达式*x相当于调用函数中的表达式q;两个表达式在内存中引用同一对象,并且都计算为同一值。同样,sqp中的表达式x与调用函数中的表达式&q相等;两者都将计算到q的地址。
是的,&q是q的地址。q的值不是"翻译的"—只是如果您有q的地址,您可以使用该地址访问对象q本身。
从链接问题的答案中稍微缩短示例:
1 2 3 4 5 6 7 8
| void sqp(int *x) {
*x = 10;
}
void foo() {
int value = 42;
sqp(&value);
} |
所以sqp是一个函数,它希望通过参数返回数据,这意味着它必须知道在哪里写入数据。这个信息是一个指针——要使用的内存地址。当传递C语言时,不会自动传递指针,但是像sqp(value);这样的语句(如果编译器由于不兼容的类型而不禁止)会传递值,在本例中是42。然后,函数sqp将看到42并将其解释为地址,并尝试写入内存位置42,而该位置很可能不是数据应该到达的位置。
现在的问题是为什么编译器不能自己进行演绎。函数需要一个指向int的指针,我们提供了一个int,以便可以自动推导它。
我认为至少有两个理由不做扣除
- 它使调用代码更清晰——&告诉读者我们正在传递地址,并且值可能会更改。
- 在所有情况下都不可能扣除。也就是说,对于一个期望void *的函数,编译器可能不清楚在已经提供指针的情况下是否需要额外的级别。
嗯,你知道指针吗?我想你会的。^
传递论点有两种方法。传递值和传递引用。
也许您通常使用传递值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <stdio.h>
void foo (int i )
{
printf("[foo] `i` was %d
", i );
i ++;
printf("[foo] Now `i` is %d
", i );
}
int main ()
{
int i = 0;
printf("[main] `i` was %d
", i );
foo (i );
printf("[main] Now `i` is %d
", i );
} |
输出为:(实况示例)
1 2 3 4
| [main] `i` was 0
[foo] `i` was 0
[foo] Now `i` is 1
[main] Now `i` is 0 |
是的,main()的i没有改变!为什么?
因为i是按值传递的。当foo(i)运行时,复制i的值,foo使用副本,而不是原来的i使用副本。所以不能改变。
但是,您已经看到了改变参数的函数——例如,scanf。
1 2 3 4 5
| int main ()
{
int i = 0;
scanf("%d", &i ); /* `i` is changed!! */
} |
如何改变?因为scanf使用pass-by-ref。看这个例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <stdio.h>
void foo (int *pi )
{
printf("[foo] `i` was %d
", *pi );
(*pi )++; /* please be careful ^o^ */
printf("[foo] Now `i` is %d
", *pi );
}
int main ()
{
int i = 0;
printf("[main] `i` was %d
", i );
foo (&i );
printf("[main] Now `i` is %d
", i );
} |
输出为:(实况示例)
1 2 3 4
| [main] `i` was 0
[foo] `i` was 0
[foo] Now `i` is 1
[main] Now `i` is 1 |
怎么可能?因为我们传递的是i的指针,而不是i的副本。foo有i的指针,可以访问i的指针,main的指针。我们称之为参照传递。
希望它能帮助你!
- 因为scanf使用pass-by-ref:你从哪里学来的?
- @哈,嗯,你什么意思?
- 我的意思是你从哪里知道C中的旁路参考?
- @噢,我明白了……严格来说,它是指针的传递值,但是代码的含义等于引用传递。OP的情况是这样的(我想是…)
- 严格来说,传递值和传递引用是不同的。
- @当然,你是对的,但是这个代码意味着旁路参考(i是通过指针改变的),我认为可以称之为旁路参考。
- 读这个和这个。
- @当然不是,但是有了关于数组的知识,我们可以把它当作数组是指针来使用(尽管它不同于指针)。我认为我们的例子比数组的例子有更少的混淆点。
- @ HACKS并注意我们在C而不是C++。没有int &。
- 对。这就是为什么我说在C中没有旁路参考。
- 是的。由于没有by ref,pass-by指针被用作pass-by-ref,而且它是广泛使用的约定,而且几乎没有混淆点(除了我们正在做的一些理论参数),这与数组的情况不同。因为这些原因,我认为可以说是通过参考。