广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C 语言的弱符号与弱引用你了解吗
  • 541
分享到

C 语言的弱符号与弱引用你了解吗

2024-04-02 19:04:59 541人浏览 独家记忆
摘要

目录C语言中的__attribute__((weak)) 与 attribute ((weakref())弱符号弱符号的作用与示例弱引用测试代码1:测试代码2:总

C语言中的__attribute__((weak)) 与 attribute ((weakref())

引言:最近在看 linux 中一些驱动代码。驱动代码中为了实现程序的扩展性和兼容性用了很多 C 语言中的高级特性。本节就来谈一谈 C 语言中的弱符号和弱引用的用法。

弱符号

弱符号是指在定义或者声明一个对象(变量、结构体成员、函数)时,在对象的前面添加 __attribute__((weak)) 标志所得到的对象符号。如下所示函数即为一个弱对象符号 void test_weak_attr(void),或者称该函数是弱函数属性的、虚函数。

__attribute__((weak)) void test_weak_attr(void)
// 或者使用如下样式的定义,两者等效
void __attribute__((weak)) test_weak_attr(void)
{
    printf("Weak Func!\r\n");
}

弱符号的作用与示例

弱符号是相对于强符号而言的,在定义或者声明变量、函数时,未添加 __attribute__((weak)) 标识的就默认为强符号。如下,最普通的函数定义,就是定义了一个强符号 void test_strong_ref(void):

void test_weak_attr(void)
{
    printf("this is a strong func\r\n");
}

驱动程序往往需要考虑兼容性,因为要兼任很多厂商的不同型号的设备。若驱动程序中使用强符号定义一些与适配的设备的特性相关的功能,则下次适配其他设备时,该强符号函数可能需要被修改,以兼容新的设备。当适配的设备很多时,频繁地更改驱动代码将破坏驱动的可维护性。

弱符号的出现可以很好地解决该问题。弱符号的对象具有可以被重定义的功能(即可以被重载)。下面通过测试说明弱符号这种可被重载的特性。

在 test_weak_attr.c 程序中定义如下弱函数:

// test_weak_attr.c
#include <stdio.h>

__attribute__((weak)) void test_weak_attr(void)
{
    printf("this is a weak func\r\n");
}

在 main.c 中定义如下程序:

// main.c
void test_weak_attr(void)
{
    printf("this is a strong func\r\n");
}

void app_main(void)
{
    printf("init done\r\n");
    
    test_weak_attr();
}

编译运行该 main.c 程序,得到的结果是什么样子的呢?

this is a strong func

将 main.c 中的 void test_weak_attr(void) 函数注释掉,再重新编译运行程序得到的结果是:

this is a weak func

小结:在使用弱符号函数时,我们可以重新定义一个同名的强符号函数来替代它;若没有重新定义一个强函数来替换它,就使用弱函数的实现。弱函数就好像是一个可以被替换的“默认函数”。

值得一提的是,旧版本的编译器还可以使用如下方式的定义(仅声明无效)将一个对象定义为一个弱对象:

__weak void f(void)
{
//code
}

在 linux 的一些代码中,__weak 其实就是通过 __attribute__((weak))的重命名,两者等效。

弱引用

弱引用是在声明一个对象时,通过__attribute__ ((weakref()) 定义一个符号的引用关系。如下所示即定义 test_weakref() 函数弱引用 test_weak_ref() 函数。

static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));

弱引用是相对于强引用而言的。未通过 __attribute__ ((weakref()) 的符号和实现代码之间的关系是强引用。如下即为一个强引用函数。它直接给出了 函数 test_strong_ref(void) 的实现。

static void test_strong_ref(void)
{
    printf("this is a strong ref\r\n");
}

在编译程序的时候,我们可以直接使用 test_strong_ref(void) 而不必担心编译不通过。如果,我没有时间去实现 test_strong_ref(void) ,还想在程序里先使用该函数那该如何呢?(是的,就是想白嫖,不想实现,还想先在程序里使用这个函数)。

这个时候弱引用就派上用场了。可以先将该函数定义为弱引用插入到代码中,待后期有时间再慢慢优化代码实现这个函数完整的功能。下面结合测试进行说明。

测试代码1:

static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));
void app_main(void)
{
    printf("init done\r\n");
    if (test_weakref) {
        test_weakref();
    } else {
        printf("There is no weakref\r\n");
    }
}

测试结果:

There is no weakref

测试代码2:

void test_weak_ref(void)
{ 
    printf("this is a weak ref\n");
}
static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));
void app_main(void)
{
    printf("init done\r\n");
    if (test_weakref) {
        test_weakref();
    } else {
        printf("There is no weakref\r\n");
    }
}

测试结果:

this is a weak ref

小结: 强引用,在未定义该强引用的实现时,编译会报错误:未定义的引用。弱引用允许定义一个未实现(未实例化)的对象,这在编译的时候会将该对象处理成 NULL,编译器并不会报错。通过使用弱引用可以实现后期优化代码的功能。而避免改动使用该函数的地方。使用弱函数可以实现类似“钩子(hook)"函数的功能。

实际上,包括C、pythonGo 编程语言在内的很多语言 都有类似用法,本篇文章叙述的方法同样适用于这些语言的相关开发

注意:弱引用仅在静态编译中有效,动态链接中可能无效。

总结

弱符号、弱引用都是增强程序的可维护性的方法。弱符号通过可以被重定义的特性,实现可以被替换实现。弱引用通过可以暂时使用一个未定义的函数的功能,实现允许后期再实现该函数具体功能,而不必担心编译不通过。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!    

--结束END--

本文标题: C 语言的弱符号与弱引用你了解吗

本文链接: https://www.lsjlt.com/news/144094.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C 语言的弱符号与弱引用你了解吗
    目录C语言中的__attribute__((weak)) 与 attribute ((weakref())弱符号弱符号的作用与示例弱引用测试代码1:测试代码2:总...
    99+
    2022-11-13
  • 关于C语言中弱符号与弱引用的实际应用问题
    最近在学习《程序员的自我修养——链接、装载与库》时,get到了一个新的知识点:弱符号与弱引用。书中简短的介绍,让我了解到弱符号的含义以及使用方式。了解我的朋友,应该知道我喜欢将知识...
    99+
    2022-11-12
  • C语言的运算符你了解吗
    目录前言一、算数运算符(数学运算) + -* / %二、逻辑运算符(判断真假)|| &&> >= < <=!? : ...
    99+
    2022-11-12
  • C语言的字符空间与非字符空间你了解吗
    目录前言一、字符空间与非字符空间概念二、字符空间三、非字符空间四、void * 非字符空间形参化总结前言 自学笔记,没有历史知识铺垫(省略百度部分)C语言字符空间与非字符空间 一、字...
    99+
    2022-11-12
  • 你真的了解PHP中的引用符号(&)吗
    引言 最近接手了五六年前的老项目,用的是CI2.0框架,在看框架源码的时候有个地方让我楞了一下,于是有了这篇文章。 字符&的最早历史可以追溯到公元1世纪,最早是拉丁语et ...
    99+
    2022-11-12
  • C语言的函数概念与规则你了解吗
    目录一、函数概念1.传入参数2.返回值二、函数参数三、指针函数-函数名指针化1.指针指向其他函数的函数名(标签)效果2.指针指向其他函数的地址效果3.通过二级指针,将一组函数线性化四...
    99+
    2022-11-12
  • C语言的模板与泛型编程你了解吗
    目录模板与泛型编程浅谈摘要(Effective C++):模板与泛型编程简单介绍函数模板模板编译类模板为什么我们需要模板特例化?总结模板与泛型编程浅谈 摘要(Effective C+...
    99+
    2022-11-13
  • C语言简明讲解单引号与双引号的使用
    目录一、单引号和双引号二、小贴士三、程序实例分析1四、程序实例分析2五、容易混淆的代码六、小结一、单引号和双引号 C语言中的单引号用来表示字符字面量C语言中的双引号用来表示字符串字面...
    99+
    2022-11-13
  • C语言的常量,字符串,转义字符,注释你都了解吗
    目录四种常量:字符串:转义字符注释总结四种常量: 1.字面常量 如数字100,‘a’ 2.const修饰的常变量 const int n = 10 //常变量...
    99+
    2022-11-13
  • C语言的程序环境与预处理你真的了解吗
    目录1.翻译环境2.运行环境3.预处理详解3.1#define定义的符号3.2#define定义的宏3.3#define的替换规则3.4#与##4.宏与函数对比5.#undef6.条...
    99+
    2022-11-13
  • 一文带你了解C++中的右值引用与移动语义
    目录意义左值右值值类别左值纯右值将亡值左值引用右值引用std::move()移动构造&移动赋值运算符重载测试&验证意义 充分利用临时对象,避免拷贝。 左值右值 值类别...
    99+
    2023-05-13
    C++右值引用 移动语义 C++右值引用 C++ 移动语义
  • 一篇文章带你了解C语言的一些重要字符串与内存函数
    目录一.字符串函数1. 求字符串长度的strlen2.比较字符串大小的strcmp3.复制字符串的strcpy4.追加字符串的strcat5.查找字符串函数的strstr二、内存函数...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作