有時看到如下的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*****************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void
test()
{
printf
(
"123456\n"
);
}
int
main(
int
argc,
char
*argv[])
{
printf
(
"0x%x\n"
,test);
printf
(
"0x%x\n"
,&test);
}
[root@localhost pht]# ./a.out
0x8048328
0x8048328
|
按照&運算符本來的意義,它要求其操作數是一個對象,但函數名不是對象(函數是一個對象),本來&test是非法的,但很久以前有些編譯器已經允許這樣做,
c/c++標准的制定者出於對象的概念已經有所發展的緣故,也承認了&test的合法性。
因此,對於test和&test你應該這樣理解,test是函數的首地址,它的類型是void (),&test表示一個指向函數test這個對象的地址,
它的類型是void (*)(),因此test和&test所代表的地址值是一樣的,但類型不一樣。test是一個函數,&test表達式的值是一個指針!
跟此問題類似的還有對一個數組名取地址。
int a[100];
printf("%p\n", a);
printf("%p\n", &a[0]);
打印值一樣。
但是數組名a,指向的是具有100個int類型的組數;
&a[0]指向的是元素a[0]。
即他們的值相同,但指向的類型不同。
標准在其rationale中解釋了這個問題,摘錄如下:
6.5.3.2 Address and indirection operators
Some implementations have not allowed the & operator to be applied to an array or a function.
(The construct was permitted in early versions of C, then later made optional.) The C89 Language
Committee endorsed the construct since it is unambiguous, and since data abstraction is
enhanced by allowing the important & operator to apply uniformly to any addressable entity.