C语言内建函数

一、什么是内建函数(Build-in Function)

内建函数就是编译器内部实现的函数,可直接使用,无需 #include 对应的头文件才能使用。内建函数的函数命名,通常以 __builtin 开头。编译器会尽量使用硬件指令来实现这些内建函数,比如加法后溢出时的条件跳转,携带时的条件跳转等。

二、内建函数的用途

● 用来处理变长参数列表;

● 用来处理程序运行异常;

● 程序的编译优化、性能优化;

● 查看函数运行中的底层信息、堆栈信息等;

● 实现C 标准库的常用函数。

三、执行带有溢出检查的算术操作的内建函数

下列内置函数可以检查简单的算术运算是否会溢出。

bool __builtin_add_overflow_p( type1 a, type2 b, type3 c)
bool __builtin_sub_overflow_p( type1 a, type2 b, type3 c)
bool __builtin_mul_overflow_p( type1 a, type2 b, type3 c)

这些内置函数类似于 __builtin_add_overflow 、 __builtin_sub_overflow 或 __builtin_mul_overflow ,不同之处在于它们不会将算术运算的结果存储在任何地方并且最后一个参数不是指针,而是具有除枚举或布尔类型之外的整数类型的某些表达式.

内置函数将前两个操作数提升为无限精度带符号类型,并对这些提升的操作数执行加法运算。然后将结果转换为第三个参数的类型。如果强制转换结果等于无限精度结果,则内置函数返回 false ,否则返回 true 。将忽略第三个参数的值,仅评估第三个参数中的副作用,并且不对最后一个参数执行积分参数提升。如果第三个参数是位字段,则用于结果强制转换的类型具有给定位字段的精度和正负号,而不是基础类型的精度和正负号。

类似地,还有这些内置函数:

bool __builtin_add_overflow( type1 a, type2 b, type3 * res)
bool __builtin_sadd_overflow(int a,int b,int * res)
bool __builtin_saddl_overflow(long int a,long int b,long int* res)
bool __builtin_saddll_overflow(long long int a,long long int b,long long int * res)
bool __builtin_uadd_overflow(unsigned int a,unsigned int b,unsigned int* res)
bool __builtin_uaddl_overflow(unsigned long int a,unsigned long int b,unsigned long int* res)
bool __builtin_uaddll_overflow(unsigned long long int a,unsigned long long int b,unsigned long long int* res)

这些内置函数将前两个操作数提升为无限精度带符号类型,并对这些提升的操作数执行加法运算。然后将结果强制转换为第三个指针参数指向的类型并存储在那里。如果存储的结果等于无限精度的结果,则内置函数返回 false ,否则返回 true 。由于加法运算以无穷大的符号精度执行,因此这些内置函数对所有参数值具有完全定义的行为。

第一个内置函数允许操作数的任意积分类型,结果类型必须是指向枚举型或布尔型以外的某个积分类型的指针,其余的内置函数都有明确的整数类型。

bool __builtin_sub_overflow( type1 a, type2 b, type3 * res)
bool __builtin_ssub_overflow(int a,int b,int * res)
bool __builtin_ssubl_overflow(long int a,long int b,long int* res)
bool __builtin_ssubll_overflow(long long int a,long long int b,long long int* res)
bool __builtin_usub_overflow(unsigned int a,unsigned int b,unsigned int* res)
bool __builtin_usubl_overflow(unsigned long int a,unsigned long int b,unsigned long int* res)
bool __builtin_usubll_overflow(unsigned long int a,unsigned long int b,unsigned long int* res)

这些内置函数与上面的加法溢出检查内置函数类似,只是它们执行的是减法,从第一个参数中减去第二个参数,而不是加法。

bool __builtin_mul_overflow( type1 a, type2 b, type3 * res)
bool __builtin_smul_overflow(int a,int b,int* res)
bool __builtin_smull_overflow(long int a,long int b,long int* res)
bool __builtin_smulll_overflow(long long int a,long long int b,long long int* res)
bool __builtin_umul_overflow(unsigned int a,unsigned int b,unsigned int* res)
bool __builtin_umull_overflow(unsigned long int a,unsigned long int b,unsigned long int* res)
bool __builtin_umulll_overflow(unsigned long long int a,unsigned long long int b,unsigned long long int * res)

这些内置函数与上面的加法溢出检查内置函数类似,只是它们执行的是乘法,而不是加法。

四、返回地址的内建函数

  1. __builtin_return_address

__builtin_return_address(LEVEL);

该函数用来返回当前函数或调用者的返回地址。函数参数LEVEL表示函数在调用链中不同层级的函数。

  • 0:获取当前函数的返回地址

  • 1:获取上一级函数的返回地址

  • 2:获取上二级函数的返回地址

  • ......

  1. __builtin_frame_address

__builtin_frame_address(LEVEL);

该函数用来查看函数的栈帧地址。

  • 0:查看当前函数的栈帧地址

  • 1:查看上一级函数的栈帧地址

  • ......

五、C标准库的内建函数

不想使用C标准库函数时,可以加一个前缀__builtin,直接使用对应的内建函数。

常见的C标准库函数如下:

  • 与内存相关的函数:memcpy()、memset()、memcpy()。

  • 数学函数:log()、cos()、abs()、exp()。

  • 字符串处理函数:strcat()、strcmp()、strcpy()、strlen()。

  • 打印函数:printf()、scanf()、putchar()、puts()。

六、其他常用内建函数

  1. __builtin_constant_p(n)

该函数主要用来判断参数n在编译时是否为常量。如果是常量,则函数返回1,否则函数返回0。该函数常用于宏定义中,用来编译优化。

  1. __builtin_expect(exp,c)

该函数有2个参数,返回值就是其中一个参数,仍是exp。该函数主要用来告诉编译器:参数exp的值为c的可能性很大,然后编译器可以根据这个提示信息,做一些分支预测上的代码优化。

参数c与这个函数的返回值无关,无论c为何值,函数的返回值都是exp。

例如:

int main(void)
{
    int a;
    a = __builtin_expext(3, 1);
    printf("a = %d\n", a);

    int a;
    a = __builtin_expext(3, 10);
    printf("a = %d\n", a);

    int a;
    a = __builtin_expext(3, 100);
    printf("a = %d\n", a);
}

程序运行结果如下:

a = 3
a = 3
a = 3

在Linux内核,我们使用__builtin_expect()内建函数,定义了两个宏。

#define likely(x) __builtin_expext(!!(x), 1)
#define unlikely(x) __builtin_expext(!!(x), 0)

这两个宏的主要作用就是告诉编译器:某个分支发生的概率很高,或者很低,基本不可能发生。编译器根据这个提示信息,在编译程序时就会做一些分支预测上的优化。

在这里对宏的参数x做两次取非操作,就是为了将参数x转换为布尔类型,然后直接与1和0作比较,告诉编译器x为真或为假的可能性很高。

七、参考资料

GCC - 6.56 内建函数执行带有溢出检查的算术操作 以下内置函数允许执行简单的算术运算,同时检查是否溢出。 (runebook.dev)

嵌入式C语言自我修养 11:有一种函数,叫内建函数 - 知乎 (zhihu.com)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Simulink是一个基于模型的设计工具,它可以帮助用户在图形化界面下进行系统建模和仿真。而C语言是一种通用的编程语言,它可以用于开发各种类型的软件,包括嵌入式系统的控制程序。 在Simulink中,用户可以使用Stateflow来进行C语言代码的集成。Stateflow是一个可视化的状态机工具,它可以将用户定义的状态机模型转换为C语言代码,并与Simulink模型进行整合。用户可以在Stateflow中使用基本的C语言语法,如if语句、for循环、函数调用等。 另外,在Simulink中还有一些针对嵌入式系统开发的工具箱,如Embedded Coder和Simulink Coder。这些工具可以将Simulink模型自动转换为C语言代码,并提供了一些优化选项,以帮助用户生成高效的嵌入式软件。 ### 回答2: Simulink是由MathWorks开发的一种模块化仿真环境,用于建立、模拟和分析动态系统。它允许工程师和科学家通过图形化界面来设计、测试和验证各种系统的行为。而C语言是一种通用的编程语言,用于开发各种类型的软件和应用程序。 Simulink与C语言可以结合使用,通过Simulink中的Stateflow和Embedded Code功能,可以将C代码嵌入到模型中,实现更复杂的仿真和控制系统设计,以及对实时应用程序的开发。这为工程师提供了更高的灵活性和可扩展性,以满足不同的设计和开发需求。 Simulink在C语言开发中具有以下几个优点: 1. 简化开发:Simulink提供了丰富的图形化界面和预定义的模块库,让用户可以直观地设计系统模型。这样可以大大简化C语言开发的过程,使代码编写更加高效和易于维护。 2. 仿真与验证:Simulink能够将C代码直接转换为仿真模型,并提供完整的仿真和验证功能。可以通过观察系统响应、调整参数和验证设计来优化C代码,以实现更好的系统性能。 3. 自动生成可执行代码:Simulink可将模型转换为C代码,并自动生成可执行文件,实现快速展示和验证系统功能。这样可以加快开发速度,降低出错概率。 4. 支持庞大的C语言库:C语言具有丰富的库函数,可以实现各种功能。通过Simulink与C语言的结合,可以利用已有的C语言库,提高开发效率和功能实现。 因此,通过结合Simulink与C语言,工程师可以更加高效地进行系统设计和开发,实现各种应用程序和控制系统,提升工程质量和生产效率。 ### 回答3: Simulink是一种用于模拟和建模动态系统的工具,而C语言是一种广泛使用的编程语言。结合Simulink和C语言可以实现复杂系统的模拟和控制设计。 首先,Simulink提供了一个图形化界面,用户可以通过拖放和连接各种模块来创建一个系统模型。这些模块可以代表各种不同类型的元件,例如传感器、执行器、控制器等。组合这些模块可以生成一个动态系统的模型。 然后,用户可以使用Simulink内建的仿真器来验证系统模型的行为。仿真器可以根据所设置的输入条件和参数对模型进行仿真,以获得系统在不同情况下的动态响应。这样可以帮助用户评估和优化系统的性能。 C语言是一种功能强大且广泛使用的编程语言,可以与Simulink结合使用以实现更复杂的系统功能。通过使用Simulink的C语言代码生成器,用户可以将Simulink模型转化为C语言代码,并将其嵌入到具体的硬件平台或嵌入式系统中。这样可以实现对系统的精确控制和实时反馈。 Simulink的C语言生成器还可以生成可执行代码或库文件,这样用户可以直接在C语言开发环境中进行进一步的调试和优化。同时,用户还可以使用C语言编写自定义的功能模块,这些模块可以通过Simulink中的S-Function进行集成和调用。 综上所述,通过Simulink和C语言的结合,用户可以实现复杂系统的建模、仿真和控制设计,以及与具体硬件平台的集成。这种组合使得系统开发和优化更加高效和灵活,并可以应用于各种工程和科学领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趣多多代言人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值