怎么给指针分配一个地址_C语言中一个分号的奇迹(预处理、指针、结构体、内存分配)——一段暗藏玄机的代码...

点击上方公众号名称关注,获得更多内容

235c3866b4c7f3ab4574f6724d170bf9.gif ✎ 编 者 悟 语

      “看热闹”只能是置身事外!

文 章 导 读

    今天给大家拼凑一个超经典的程序实例,从这个实例中大家能体会到C语言的玄妙,小伙伴们一定要自己撸一撸代码好好替换哈,希望对大家有所帮助哈,bdc7e735f465bbf2dd6bc99ae9b1af25.png

1你见过下面这样的C代码吗

    看看下面的代码?你见过吗?


#include 
#include int main(int argc, char *argv[]) {
     ;
     ;
     ;
     ;
     printf("\n我运行到这啦哈!!!\n");return 0;
}

    说实在的上面的代码,你确实是见不到的,并不是它有什么问题,而是,你用得时候只有将形式影藏起来才能见到它的威力。

    上面代码的运行结果如下:

82c80618ea91bd5e21a07832ac5bbd3a.png

    从上面的结果中我们可以得出一个结论和两个推测。

结论:C语言中支持由单个分号构成的语句。

推测1:单独的分号语句,在编译的时候可能会被编译器优化掉,而不占用空间和运行速度。

推测2:单独的分号语句,没有被编译器优化掉,它可能占空间,也可能占运行速度。

    上面的推测没有经过验证,所以我在这里并不能下结论,如果感兴趣,小伙伴们可以去测试一下。

    我写上面那段代码的目的,不是为了唬人,而是想说,这个单独的分号语句,也是很有用处的,它结合预处理(这里主要用到宏定义+分支)、指针、结构体、内存分配会发挥意想不到的效果。

重要提醒:下面的代码不长,但能让你get到n多个具有深度的知识点。

2代码功能说明

    大家在看我下面的实例代码的时候,要注意下面4个点,只有将这4个点看到心里有数,才算领会到了实例代码的精髓。

    1)宏开关的位置

    可以有一个开关,统一动作,也可以将一个开关放到多个位置。

    2)利用宏开关,批量开启关闭功能块

    可以将不同功能的模块或这说函数等放到一起,用宏开关开启关闭相应的功能。

    3)给结构体指针变量和结构体内部的指针变量分配空间

    凡是指针都要指向特定的位置,不然就是空指针,也容易造成野指针,造成程序崩溃,很多时候不分配空间直接使用都会报错的。

    4)利用宏替换,将函数调用失效

    用宏替换将函数名及括号参数替换为空格,函数就是失效了,函数调用不用时都不用注释。

    5)在主函数中只是调用,可不可以去掉宏分支

    当只是将函数失效,没有变量操作时,宏分支是可以去掉的,这个点大家自己去尝试吧!

3实例代码

    代码分为三个函数,主要目的是模块化,名字起得比较随意大家多担待,看内容吧。

    1)struct_test.h


#ifndef STRUCT_TEST_H
#define STRUCT_TEST_H
#endif 

#define OPERATIN_ON

#ifdef OPERATIN_ON

// 定义两个结构 
typedef struct _with_para
{

     int p; 
     int w_val1;
     int w_val2;
    
}with_para_t;


typedef struct _without_para
{

     with_para_t *wp; 
     int stu_val1;
     int stu_val2;
    
}without_para_t;

// 定义结构体变量及指针 
without_para_t test_para;
with_para_t with_test;
without_para_t *pp;

// 函数声明 
int test_fun1(void);
int test_fun2(int val1,int val2);


#else  //将两个函数替换为空格,函数调用处只剩分号,即可取消函数调用             

#define test_fun1(void)          
#define test_fun2(val1,val2)
#endif

    2)struct_test.c

#include
#include
#include"struct_test.h"
#ifdef OPERATIN_ON  //此宏没定义,下面的函数定义就失效了,不用注释定义和调用就可以用宏批量取消掉某种功能的函数 // 此函数适合用于初始化,初始值用结构指定,并返回给结构中的指针变量 int test_fun1(void){
     with_test.p = 3;
     with_test.w_val1 = 4;
     with_test.w_val2 = 5;
}// 此函数适合带参初始化 int test_fun2(int val1,int val2){
     pp->stu_val1 = val1;
     pp->stu_val2 = val2;
     pp->wp = &with_test;
}
#endif

    3)main.c

#include 
#include 
#include"struct_test.h"
#ifdef OPERATIN_ON// 声明外部结构变量 
extern without_para_t test_para;
extern with_para_t with_test;
extern without_para_t *pp;
#endifint main(int argc, char *argv[]) {
#ifdef OPERATIN_ON  // 宏定义起作用的分支 
     printf("宏开启啦!\n"); // 指向结构的指针需要分配空间,结构中的指针也要分配空间 
     test_para.wp = (with_para_t *)malloc(sizeof(with_para_t));
     pp = (without_para_t *)malloc(sizeof(without_para_t));// 函数起作用 
     test_fun1();
     test_fun2(1,2);// 打印信息
     printf("\n打印函数信息如下:\n\n"); 
     printf("pp->stu_val1 = %d\n",pp->stu_val1);
     printf("pp->stu_val2 = %d\n",pp->stu_val2);
     printf("pp->wp->p = %d\n",pp->wp->p);
#else              //将宏定义OPERATIN_ON注释掉,宏失效运行此分支, test_fun1();被替换为;,即不再调用这两个函数。 
     printf("宏关闭啦!\n"); // 函数调用被替换为分号,函数失效 
     printf("\n函数调用被替换为分号,失去调用意义啦!\n");
     test_fun1();       
     test_fun2(1,2);
#endifprintf("\n我运行到这啦哈!!!\n");return 0;
}

    当宏OPERATIN_ON打开(定义)时,运行结果如下:

c15ecdb3075c75a4bc5a907b85d0294a.png

    当宏OPERATIN_ON关闭(注释)时,运行结果如下:

654a61aad55323f5ea563275a8861ca6.png

提示:上面的代码,大家可以建立一个工程去试试,只是看是不太好体到它的应用价值的。

4宏替换的延伸扩展

    宏替换不仅可以换函数,还可以换变量是否复制,相关内容请看我的另一篇文章——宏分类的妙用(排版开始用模板)。

总结

    今天这篇文章是时分实用的,这里只是抛砖引玉,并没有结合实际的应用,但小伙伴们还是会有不小的收获的,要自己把代码拿下来撸一撸哈,看热闹只能是置身事外哈,小伙伴们敬请期待哈,7ae66a3c426115e75ebc473f3ba364a9.png

    有问题可以后台留言交流,公众号18年后新申请的,文章后不支持留言功能的。

相关文章:

宏分类的妙用(排版开始用模板)

内存分配函数malloc、calloc、realloc的功能测试

static关键字的3种特性

用结构体和指针模拟配置芯片引脚输出高低电平

C标准库函数sprintf和sscanf的使用

用Dev-C++生成dll动态链接库文件并用C代码调用

进化论——从函数指针到被结构封装的函数指针及参数的应用举例

专辑推荐:

Python技能专辑

C语言专辑

IDE调试专辑

软件推荐专辑

软实力专辑

Linux专辑

扫码关注我们

94c6a2fb455700310b8e375ed122c681.png

769f7f3b1fdcb7541d746388fa218569.gif Game Over!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值