函数指针和函数的地址

时间:2012-03-04 05:44:48

标签: c function pointers function-pointers

所以我想在制作函数指针时,你不需要operator &来获取初始函数的地址:

#include <stdio.h>

double foo (double x){
    return x*x;
}

int main () {

    double (*fun1)(double) = &foo;
    double (*fun2)(double) =  foo;

    printf("%f\n",fun1(10));
    printf("%f\n",fun2(10));

    printf("fun1 = %p \t &foo = %p\n",fun1, &foo);
    printf("fun2 = %p \t  foo = %p\n",fun2,  foo);       

    int a[10];

    printf("  a = %p \n &a = %p  \n",a,&a);

    return 0;
}

输出:

>./a.out 
100.000000
100.000000
fun1 = 0x4004f4      &foo = 0x4004f4
fun2 = 0x4004f4       foo = 0x4004f4
  a = 0x7fff26804470 
 &a = 0x7fff26804470 

然后我意识到数组也是如此,这意味着如果int a[10] a&a指向同一位置。为什么这是数组和函数?地址是否保存在与保存在其中的值(地址)具有相同地址的存储单元中?

5 个答案:

答案 0 :(得分:66)

鉴于int a[10]a&a都会产生相同的地址,是的,但它们的类型不同。

a的类型为int[10]。当它被隐式转换为指针类型时,指针的类型为int*,并指向数组的初始元素。 &a的类型为int (*)[10](即指向十个整数数组的指针)。因为数组中没有填充,它们都会产生具有相同的指针,但指针具有不同的类型

函数类似于数组,但不完全相同。您的函数foo的类型为double(double)。只要在表达式中使用foo并且不是一元&运算符的操作数,它就会隐式转换为指向自身的指针,类型为double(*)(double)

因此,出于所有实际目的,函数的名称和指向同一函数的指针是可互换的。有一些细微之处,我在回答"Why do all these crazy function pointer definitions all work? What is really going on?"时都讨论过这个问题(这个问题是关于C ++的问题,但C ++中非成员函数的规则与C中的函数相同。)

答案 1 :(得分:8)

不,没有专门用于指向函数/数组的额外存储空间。

大多数变量variable_name除了获取该变量的地址之外还有其他含义,因此您需要使用&variable来获取地址。

对于函数或数组,function_name(本身,后面没有括号)没有任何其他含义,因此将它解释为获取函数的地址没有问题。

同样反过来:普通指针需要显式解除引用,但指向函数的指针不会(再次,因为没有其他合理的解释),所以给定一个指向函数的指针,如:

int (*func)(param_list);

以下内容彼此相同 - 两者都调用函数func指向:

(*func)(params);

func(params);

答案 2 :(得分:1)

基本上,由于功能名称是“已知”的功能,因此&amp;并非绝对必要。对于数组,此行为是相同的。回想一下,函数本身不是变量,因此它的行为与您有时可能会有的不同。如果您有第二版K&amp; R,您可以查看第5.11节关于功能的指示,或最后的参考手册,

  

第A7.1节指针生成:如果表达式的类型或   对于某些类型T,子表达式是“T的数组”,那么该值就是   expression是指向数组中第一个对象的指针,以及类型   表达式被改为“指向T的指针”这种转换可以   不取代表达式是一元&amp;的操作数。   operator,...类似地,类型为“函数返回T”的表达式   除非用作&amp;的操作数。运算符,转换为   “指向返回T的函数的指针。”

     

第A7.4.2节地址操作员:一元&amp;运营商获取地址   其操作数....结果是指向对象或函数的指针   左值所指的。如果操作数的类型是T,则为类型   结果是“指向T的指针。”

据我所知,C99也是如此。

答案 3 :(得分:1)

fun&fun完全相同(除了sizeof(f)是非法的)。 a&a与指针算法相同:a + 10 == &a + 1,因为10*sizeof(*a) == sizeof(a)(其中sizeof(*a) == sizeof(int))。

答案 4 :(得分:0)

  

printf(“fun1 =%p \ t&amp; foo =%p \ n”,fun1,foo);

这里你通过传递函数指针foo来调用pass by value

  

printf(“fun2 =%p \ t foo =%p \ n”,fun2,&amp; foo)

您可以通过将函数指针传递给&foo

来调用pass by reference

在这两种情况下,您只使用函数指针调用printf

请记住foo本身是function pointer value而不是变量。

数组也是如此。 int arr[10]转换为连续的10个整数块,第一个元素的地址存储在arr中。所以arr也是一个指针。