cpp——与c之不同——指针

本文对比了C与C++中void指针的不同,包括void指针的算术运算、解引用操作以及类型转换的支持情况。在C中,void指针允许算术运算,可以被解引用并转换为其他类型指针;而在C++中,void指针不支持算术运算,不能直接解引用,也不允许直接转换为其他类型指针。此外,还探讨了两者的函数指针特性。
摘要由CSDN通过智能技术生成

void*

c

void void_pointer()
{
    int i = 5;
    void* pv = &i;
    int* pi = pv;
    
    printf("sizeof(void) = %ld\n", sizeof(void));
    
    printf("pv = %p, pi = %p, *pi = %d\n", pv, pi, *pi);
    
    pv++;
    printf("pv = %p\n", pv);
    pv += 5;
    printf("pv = %p\n", pv);
    
    *pv;
    //i = *pv;
}
output:
sizeof(void) = 1
pv = 0x7fff5fbff834, pi = 0x7fff5fbff834, *pi = 5
pv = 0x7fff5fbff835
pv = 0x7fff5fbff83a
总结:
  • void指针基础类型为void,而void类型字长为1,因此void指针单位偏移地址为1,因此void指针支持算术运算
  • 支持对void*指针使用*运算(不支持直接使用void类型,因此没有void类型对象)
  • 支持void*类型指针转其他类型指针

c++

void void_pointer()
{
    int i = 5;
    void* pv = &i;
    //int* pi = pv;
    
    //printf("sizeof(void) = %ld\n", sizeof(void));
    
    //printf("pv = %p, pi = %p, *pi = %d\n", pv, pi, *pi);
    
    //pv++;
    printf("pv = %p\n", pv);
    //pv += 5;
    printf("pv = %p\n", pv);
    
    //*pv;
    //i = *pv;
}
总结:
  • void指针基础类型为void,而void类型字长未定义,因此void指针单位偏移地址未定义,因此void指针不支持算术运算
  • 不支持对void*指针使用*运算,因为void字长未定义
  • 不支持void*类型指针转其他类型指针

函数指针

c

c不支持函数重载,因此函数名唯一确定函数,因此如果函数声明omit形参,编译时函数调用会ignore形参检查(形参个数和类型),如果函数运行异常,运行期才能发现,但如果没有omit形参,编译时函数调用会做形参检查(形参个数和类型)
假如feed.c中定义如下函数
void feed(int rice, int meat)
{
    printf("feed rice %d and meat %d\n", rice, meat);
}
在main.c中进行如下函数调用
void feed();

void call_feed()
{
    feed();
    feed(5);
    feed(5, 8);
    feed(5, 8, 58);
}
output:
feed rice 1 and meat 1606416504
feed rice 5 and meat 73832
feed rice 5 and meat 8
feed rice 5 and meat 8
注:feed(),feed(5)实参缺失,函数运行异常,feed(5, 8, 58)传递了多余实参
因为c不支持函数重载,feed()调用link时search _sub_feed_(不包含形参)目标代码入口,而void feed(int rice, int meat)函数定义在目标代码中入口地址为_sub_feed_(不包含形参),因此link时能search到,正确link
函数这个特性相应扩展到了函数指针类型,如果函数指针类型omit形参,编译时函数指针类型ignore形参检查(形参个数和类型),如果函数指针类型运行异常,运行期才能发现,但如果没有omit形参,编译时函数指针类型会做形参检查(形参个数和类型),因此omit形参的函数指针类型(无参函数指针类型)与没有omit形参的函数指针类型(含参函数指针类型)可相互转换(函数返回类型必须一致)
void feed0()
{
    printf("feed none\n");
}

void feed1(int rice)
{
    printf("feed rice %d\n", rice);
}

void feed2(int rice, int meat)
{
    printf("feed rice %d and meat %d\n", rice, meat);
}

void feed3(int rice, int meat, int fruit)
{
    printf("feed rice %d and meat %d and fruit %d\n", rice, meat, fruit);
}

typedef void (*PFeed0)();
typedef void (*PFeed1)(int);
typedef void (*PFeed2)(int, int);
typedef void (*PFeed3)(int, int, int);

void fun_pointer()
{
    PFeed0 pfeed0 = feed0;
    PFeed1 pfeed1 = feed1;
    PFeed2 pfeed2 = feed2;
    PFeed3 pfeed3 = feed3;
    
    pfeed0 = feed1;
    pfeed0 = feed2;
    pfeed0 = feed3;
    
    pfeed0();
    pfeed0(5);
    pfeed0(5, 8);
    pfeed0(5, 8, 58);
    
    pfeed1 = feed0;
    pfeed2 = feed0;
    pfeed3 = feed0;
    
    //pfeed1();
    pfeed1(5);
    //pfeed2();
    pfeed2(5, 8);
    //pfeed3();
    pfeed3(5, 8, 58);
    
    //pfeed1 = feed2;
    //pfeed2 = feed1;
    
    //pfeed1 = feed3;
    //pfeed3 = feed1;
    
    //pfeed2 = feed3;
    //pfeed3 = feed2;
}
output:
feed rice 0 and meat 0 and fruit 0
feed rice 5 and meat 0 and fruit 0
feed rice 5 and meat 8 and fruit 0
feed rice 5 and meat 8 and fruit 58
feed none
feed none
feed none
注:通过omit形参的函数指针类型(无参函数指针类型)调用函数时,ignore形参检查(形参个数和类型)

c++

c++支持函数重载,因此函数名+形参(形参个数和类型)唯一确定函数,omit形参的函数声明仅仅表示无参函数声明,没有多余其他含义,编译时函数调用无论如何都会做形参检查(形参个数和类型)
假如feed.cpp中定义如下函数
void feed(int rice, int meat)
{
    printf("feed rice %d and meat %d\n", rice, meat);
}
在main.cpp中进行如下函数调用
void feed();

void call_feed()
{
    feed();
    //feed(5);
    //feed(5, 8);
    //feed(5, 8, 58);
}
注:编译时,feed(5),feed(5, 8),feed(5, 8, 58)与函数声明void feed()形参不匹配,而feed()尽管与函数声明void feed()匹配,但link error
因为c++支持函数重载,feed()调用link时search _sub_feed_目标代码入口(包含形参,表示无参),而void feed(int rice, int meat)函数定义在目标代码中入口地址为_sub_feed_int_int_(包含形参,两个形参int,int),因此link时search不到,link error
函数这个特性相应扩展到了函数指针类型,因此c++支持函数重载,因此omit形参的函数指针类型仅仅表示无参函数指针类型,没有多余其他含义,编译时函数指针类型无论如何都会做形参检查(形参个数和类型),因此omit形参的函数指针类型(无参函数指针类型)与没有omit形参的函数指针类型(含参函数指针类型)不可相互转换(函数返回类型必须一致)
void feed0()
{
    printf("feed none\n");
}

void feed1(int rice)
{
    printf("feed rice %d\n", rice);
}

void feed2(int rice, int meat)
{
    printf("feed rice %d and meat %d\n", rice, meat);
}

void feed3(int rice, int meat, int fruit)
{
    printf("feed rice %d and meat %d and fruit %d\n", rice, meat, fruit);
}

typedef void (*PFeed0)();
typedef void (*PFeed1)(int);
typedef void (*PFeed2)(int, int);
typedef void (*PFeed3)(int, int, int);

void fun_pointer()
{
    PFeed0 pfeed0 = feed0;
    PFeed1 pfeed1 = feed1;
    PFeed2 pfeed2 = feed2;
    PFeed3 pfeed3 = feed3;
    
    //pfeed0 = feed1;
    //pfeed0 = feed2;
    //pfeed0 = feed3;
    
    pfeed0();
    //pfeed0(5);
    //pfeed0(5, 8);
    //pfeed0(5, 8, 58);
    
    //pfeed1 = feed0;
    //pfeed2 = feed0;
    //pfeed3 = feed0;
    
    //pfeed1();
    pfeed1(5);
    //pfeed2();
    pfeed2(5, 8);
    //pfeed3();
    pfeed3(5, 8, 58);
    
    //pfeed1 = feed2;
    //pfeed2 = feed1;
    
    //pfeed1 = feed3;
    //pfeed3 = feed1;
    
    //pfeed2 = feed3;
    //pfeed3 = feed2;
}
output:
feed none
feed rice 5
feed rice 5 and meat 8
feed rice 5 and meat 8 and fruit 58
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值