为何使用&用*传递函数值?

时间:2014-06-27 09:59:43

标签: c pointers

我想从Understanding functions and pointers in C

询问作者caf

我意识到我不能在同一页面上问这个问题。

我仍然对使用&将指针的值传递给函数。我一直认为& q只是传递q的地址,如何将q的值转换为int sqp(int * x)?

8 个答案:

答案 0 :(得分:2)

没有"翻译"。

你的功能

int sqp(int *x);

接受一个参数x,其类型为int *,即"指向整数"的指针。

所以,要调用它,你需要传递一个指向整数的指针,即整数的地址。

&前缀运算符用于计算其参数的地址,因此您可以这样做:

int foo = 4711;
sqp(&foo);

使用变量sqp()的地址调用foo函数。

答案 1 :(得分:1)

使用:

sqp(&q);

您将q的地址作为函数int sqp(int *x)中的参数传递。

从现在开始,在此函数中,使用x您将获得此地址。

使用*x,您将获得内存中此地址中包含的值。

这就是我们如何模拟" C中的pass by reference,通过值将变量本身的地址作为函数中的参数传递。

答案 2 :(得分:1)

就像你说的那样&q将变量q的内存地址传递给函数,所以我们发送给函数的只是q的地址。该函数不需要翻译任何值,因为它直接访问原始值,因为它具有存储在指针x中的地址,并且每次使用*x=7;执行*时都会x你取消引用一个变量,这意味着它没有修改变量x,而是修改{{1}}指向的任何内容。

答案 3 :(得分:1)

如果通过引用调用,则传递一个地址,以便可以通过引用地址(即引用)进行更改,如果您在参数中传递地址,则应该有一些指向该地址的机制。指针是某种东西指向地址所以在调用时如果已经传递了地址,则必须使用定义中的指针指向它。  示例

calling(&a); //passing address

void calling(int *b) //Pointing to address of 'a' via pointer 'b'
{   
 //some code

}

答案 4 :(得分:0)

嗯,你知道指针吗?我假设你做^ o ^

传递参数有两种方法。 传递价值传递参考

也许您通常使用按值传递

#include <stdio.h>

void foo(int i)
{
    printf("[foo] `i` was %d\n", i);
    i++;
    printf("[foo] Now `i` is %d\n", i);
}

int main()
{
    int i = 0;
    printf("[main] `i` was %d\n", i);
    foo(i);
    printf("[main] Now `i` is %d\n", i);
}

输出为:(live example

[main] `i` was 0
[foo] `i` was 0
[foo] Now `i` is 1
[main] Now `i` is 0

是的,i的{​​{1}} 已更改!为什么呢?

因为main()按值传递 。运行i时,会复制foo(i)的值,i会使用副本,而不是原始foo。所以它不能被改变。


但是,您已经看到了更改参数的函数 - 例如,i

scanf

怎么改变?因为int main() { int i = 0; scanf("%d", &i); /* `i` is changed!! */ } 使用 pass-by-ref 。看看这个例子。

scanf

输出为:(live example

#include <stdio.h>

void foo(int *pi)
{
    printf("[foo] `i` was %d\n", *pi);
    (*pi)++; /* please be careful ^o^ */
    printf("[foo] Now `i` is %d\n", *pi);
}

int main()
{
    int i = 0;
    printf("[main] `i` was %d\n", i);
    foo(&i);
    printf("[main] Now `i` is %d\n", i);
}

怎么可能?因为我们传递了[main] `i` was 0 [foo] `i` was 0 [foo] Now `i` is 1 [main] Now `i` is 1 指针,而不是i的副本。 i的指针为foo,因此可以访问i所拥有的i。我们称之为传递参考

我希望它可以帮到你!

答案 5 :(得分:0)

稍微缩短相关问题答案的例子:

void sqp(int *x) {
   *x = 10;
}

void foo() {
    int value = 42;
    sqp(&value);
}

所以sqp是一个想要通过参数返回数据的函数,这意味着它必须知道写入的位置。此信息是指针 - 要使用的内存地址。当传递C语言时,不会自动传递指针,但像sqp(value);这样的语句(如果编译器由于不兼容的类型而不禁止)将传递该值,在本例中为42。然后sqp会看到42并将其解释为地址并尝试写入内存位置42,这很可能不是数据所在的位置。

现在问题是编译器为什么不能自己进行演绎。该函数需要一个指向int的指针,我们提供一个int,因此可以自动推导出来。

我认为至少有两个不做扣除的原因

  • 它使调用代码更清晰 - &告诉读者我们传递地址并且值可能会更改
  • 在所有情况下都不可能扣除。即,对于期望void *的函数,编译器可能无法清除是否已经提供指针时是否需要额外的级别。

答案 6 :(得分:0)

是的,&qq的地址。 q的值未被“翻译” - 只是如果您的地址为q,则可以使用该地址执行的操作之一是访问对象q本身。

答案 7 :(得分:0)

因此,让我们再次查看sqp函数定义:

int sqp( int *x ) { ... }

C中的声明基于表达式的类型,而不是对象;如果您有一个指向名为x的整数的指针,并且您想要访问指向的整数值,则使用一元x运算符取消引用 *,像这样:

int y = *x;

表达式的类型 *xint,因此变量 x的声明写为

int *x;

当你听到某人使用短语&#34;声明模仿使用&#34;时,这就是他们的意思。

当我们将该函数称为

y = sqp( &q );

表达式 &q生成q的地址,表达式的类型int *x中的参数sqp会收到该地址值。

因此,*x中的表达式sqp等同于调用函数中的表达式q;两个表达式都引用内存中的同一个对象,并且都计算为相同的值。同样,x中的表达式sqp等同于调用函数中的表达式&q;两者都将评估q的地址。