很无聊的test:C++函数指针解引用仍返回函数指针值,将函数指针强转成其他指针后可以解释函数代码区地址开始的若干字节,但没有什么意义

C++解引用函数指针时仍返回函数指针的值,也就是指向的函数代码区地址。将函数指针强转成其他指针后解引用便可返回函数代码区地址那几个字节的值

#include <iostream>
int Function(){ //函数名本身也是个指针,指向函数代码区
    std::cout<<"Call Function!"<<"\n";
    return 0;
}
int main(int argc,char *argv[]){
    int (*p)();
    p=Function;
    p();
    Function();
    (*p)();         //与p()函数调用的结果相同,这里*p提取函数指针指向内容与p访问函数指针内容效果相同
    (*Function)();  //同上
    std::cout<<(long)p<<",1\n";         //访问函数指针,返回函数指针的值,即代码区地址,64位平台指针必须转换成long8字节整数
    std::cout<<(long)Function<<",2\n";  //同上
    std::cout<<(long)*p<<",3\n";        //提取函数指针指向的数据,对函数指针而言总是返回指针的值(这里如果是其他
                //指针返回指向数据的话是可以类型转换的,见下10,11的int *p2
        //但此处尝试int类型转换时会报错"cast from pointer to smaller type'int' loses information gcc"),
        //因为,如果直接提取函数指针指向的数据而不是调用,由于函数指针指向的就是函数代码,不调用是没有意义的,任何
        //格式转换也是没有意义的,取函数代码的前面若干字节出来要搞毛啊?所以编译器处理"提取函数指针指向数据"时将
        //返回函数指针的值,也就是指向的代码区的地址,地址是64位的,像上面一样只能类型转换成long8字节整数
        //函数代码区在固定地址区间,提取函数指针内容,时返回指针的值而不是尝试
        //对函数代码区起始地址开始的若干字节进行类型转换返回一个数,那没有意义。毕竟不是一般的数据指针
    std::cout<<(long)*Function<<",4\n"; //代码区地址,
    int *p4=(int*)p;    //将函数指针强制类型转换成int*指针,赋值给int *p4,赋值函数代码区地址,p4也指向函数代码区
    std::cout<<(int)*p4<<",A\n";   //提取int*指针p4的指向数据,此时p4虽然仍指向函数代码区但类型不是函数指针,从而
                                //可以对指向的函数代码区地址开始的4个字节按int翻译成一个整数
    int *p3=(int*)4294979328; //不能对右值进行(int*)的类型转换,int的类型转换是可以的,
                            //指针描述一个变量类型,int可以描述一个变量类型,也可以对一个值进行类型转换
                            //右式创建一个(int*)的临时指针变量
                              //初始化指针值为4294979328,然后这个临时指针赋值指针p3,指针p3的值为4294979328
    std::cout<<(long)p3<<",5\n";//访问指针,返回指针的值
    std::cout<<(int)*p3<<",6\n"; //提取指针指向的数据,p3没有声明为函数指针,不会像函数指针那样返回指针的值,而是按类型转换进行翻译

    std::cout<<(long)&p<<",7\n";   //函数指针p自身地址
    long *p2=(long*)&p; //&p是一个右值,(int*)不是对一个右值进行类型转换,应该是创建一个临时指针,p2的值就是&p,本质上是二级指针
                        //p2指向p,p又指向函数代码区
    std::cout<<(long)p2<<",8\n";        //访问指针,返回指针的值,返回&p
    std::cout<<(long)(int*)&p<<",9\n";  //构造一个临时指针,值就是指针p自身地址,访问该临时指针,返回指针的值,返回&p,转换为long8整数
    
    std::cout<<(long)*p2<<",10\n";       //提取指针指向的数据,p2没有声明为函数指针,不会像函数指针那样返回指针的值,而是按类型转换进行解释
    std::cout<<(long)*(long*)&p<<",11\n"; //提取指针指向的数据,按类型转换进行解释

    int **p5=(int**)&p; //&p是一个右值,(int**)不是对一个右值进行类型转换,应该是创建一个临时指针,p2的值就是&p,本质上是二级指针
                        //p2指向p,p又指向函数代码区
    std::cout<<(long)p5<<",12\n";        //访问指针,返回指针的值,返回&p
    std::cout<<(long)(int**)&p<<",13\n";  //构造一个临时指针,值就是指针p自身地址,访问该临时指针,返回指针的值,返回&p,转换为long8整数
    
    std::cout<<(long)*p5<<",14\n";       //提取指针指向的数据,p2没有声明为函数指针,不会像函数指针那样返回指针的值,而是按类型转换进行解释
    std::cout<<(long)*(int**)&p<<",15\n"; //提取指针指向的数据,按类型转换进行解释,&p是long的数据,提取时也要按long8字节解释

    std::cout<<(int)**p5<<",16\n";       //提取指针指向的数据,p2没有声明为函数指针,不会像函数指针那样返回指针的值,而是按类型转换进行解释
    std::cout<<(int)**(int**)&p<<",17\n"; //函数代码区地址开始4个字节的解释,没有了函数指针的类型限制

    std::cin>>*p2;


}

猜你喜欢

转载自blog.csdn.net/HayPinF/article/details/109027914