所以我想在制作函数指针时,你不需要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
指向同一位置。为什么这是数组和函数?地址是否保存在与保存在其中的值(地址)具有相同地址的存储单元中?
答案 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也是一个指针。