我试图获得函数名[abc()和main()]所指向的地址的内存内容,但函数内的两个printf()都给出相同的输出,尽管我在每个函数内的第二个printf()中解引用函数名所指向的地址。为什么呢?为什么内存地址由*(abc)和*(main)打印而不是内容?
#include<stdio.h>
void abc(){
printf("n%p n ", abc);
printf("n%#xn ",*(abc));
}
void main(){
abc();
printf("n%p n ", main);
printf("n%#xn ",*(main));
}
不能对函数本身解引用,因为在解引用的上下文中,它将变成一个函数指针。当你对它进行解引用时,你会得到相同的旧函数…
你可以这样尝试:
printf("one");
(*printf)("two");
(**printf)("three");
要实际查看函数内容,您需要memcpy()
之类的东西。然而,这样做可能没有那么有用,因为没有办法获得函数的大小(至少通过任何标准方法)。如果您想看看函数的内容是什么样子,请在调试器中打开程序并反汇编该函数。
这是因为函数和函数指针的语法非常奇怪。
-
abc
给出函数指针 -
&abc
也给出了函数指针。 -
*abc
给出函数指示符
函数指示符衰变成函数指针,因此当在表达式中使用函数指示符时,得到的是函数的地址。
所以abc
, &abc
和*abc
都会给你相同的地址。
永远不要认为C是一种理性、理智、一致的语言!
您没有打印数据(实际上是代码),而是打印指向代码的指针的值。
#include<stdio.h>
void abc(){
int i;
printf("n%p n ", abc);
printf("n%#xn ",*(abc));
for( i = 0; i < 100; i++ ){
printf( "%X ", ((unsigned char *)abc)[i] );
}
}
void main(){
int i;
printf("n%p n ", abc);
abc();
printf("n%p n ", main);
printf("n%#xn ",*(main));
for( i = 0; i < 100; i++ ){
printf( "%X ", ((unsigned char *)main)[i] );
}
}
这表明代码在两个函数指针所指向的位置是不同的。除非您在头脑中精通反向汇编,否则它是相当没有帮助的,但是您应该能够验证它转储的代码与反汇编各自代码片段的调试器的输出一致。
在C语言中,函数指针的行为与普通指针不同——无论使用解引用操作符还是取址操作符,它都是对函数的引用。为了达到目的,需要将其强制转换为不同的指针类型;例如:
void main()
{
printf("n%p n ", main);
printf("n%#xn ", *((char*)main) );
}
指向函数的指针与指向对象的指针不一样,你不能像对待对象指针那样把函数指针当作任意字节数组来对待。
如果你愿意打破一些规则,你可以尝试将函数指针赋值给对象指针,如
unsigned char *data = (unsigned char *) abc;
然后检查data[i]
的内容。
注意你的编译器应该会报错。根据平台的不同,这可能根本不起作用。C标准没有定义从函数指针类型到对象指针类型的转换,反之亦然。允许单个实现这样做,但这不是必需的。