【基础】static搭配inline 味道更佳(explicit_bzero-rawmemchr)

最近在编译ELL,发现两个函数比较有意思,深入了解一下

一、关于这两个函数

/*
    The bzero() function writes len zero bytes	to the string b.  If len is
     zero, bzero() does	nothing.

     The explicit_bzero() variant behaves the same, but	will not be removed by
     a compiler's dead store optimization pass,	making it useful for clearing
     sensitive memory such as a	password.
*/
// 个人理解为:编译使用bzero将是显示变量优化,但是使用explicit_bzero将禁止编译器优化显示变量,比如密码之类的就不允许显示    

#ifndef HAVE_EXPLICIT_BZERO
static inline void explicit_bzero(void *s, size_t n)
{
	memset(s, 0, n);
	__asm__ __volatile__ ("" : : "r"(s) : "memory");
}
#endif
/*
The memchr() function scans the initial n bytes of the memory area pointed to by s for the first instance of c. Both c and the bytes of the memory area pointed to by s are interpreted as unsigned char.

The memrchr() function is like the memchr() function, except that it searches backward from the end of the n bytes pointed to by s instead of forward from the beginning.

The rawmemchr() function is similar to memchr(): it assumes (i.e., the programmer knows for certain) that an instance of c lies somewhere in the memory area starting at the location pointed to by s, and so performs an optimized search for c (i.e., no use of a count argument to limit the range of the search). If an instance of c is not found, the results are unpredictable. The following call is a fast means of locating a string's terminating null byte:
    char *p = rawmemchr(s, '\0');
*/
// 个人理解为:从s开始检索c,检索到了就返回匹配值
#ifndef HAVE_RAWMEMCHR
static inline void *rawmemchr(const void *s, int c)
{
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wstringop-overflow=\"")
	return memchr(s, c, (size_t) -1);
_Pragma("GCC diagnostic pop")
}
#endif

二、关于头文件中调用static inline内联函数

static inline关键字和inline关键字无法决定被关键字所修饰的函数是否最后真正会被内联。我们其实只有建议权,只有armcc编译器才可以决定函数最后是否真正会被内联。

// 这个解释还可以理解一下
By default, an inline definition is only valid in the current translation unit.

If the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.

If the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.

If the storage class is unspecified, the inline definition is only visible in the current translation unit, but the identifier still has external linkage and an external definition must be provided in a different translation unit. The compiler is free to use either the inline or the external definition if the function is called within the current translation unit.

As the compiler is free to inline (and to not inline) any function whose definition is visible in the current translation unit (and, thanks to link-time optimizations, even in different translation units, though the C standard doesn't really account for that), for most practical purposes, there's no difference between static and static inline function definitions.

The inline specifier (like the register storage class) is only a compiler hint, and the compiler is free to completely ignore it. Standards-compliant non-optimizing compilers only have to honor their side-effects, and optimizing compilers will do these optimizations with or without explicit hints.

inline and register are not useless, though, as they instruct the compiler to throw errors when the programmer writes code that would make the optimizations impossible: An external inline definition can't reference identifiers with internal linkage (as these would be unavailable in a different translation unit) or define modifiable local variables with static storage duration (as these wouldn't share state accross translation units), and you can't take addresses of register-qualified variables.

Personally, I use the convention to mark static function definitions within headers also inline, as the main reason for putting function definitions in header files is to make them inlinable.

In general, I only use static inline function and static const object definitions in addition to extern declarations within headers.

附上维基链接:https://en.wikipedia.org/wiki/Inline_function#C99

抛出问题点:

优势:
减少调用函数时的开销,如:
减少传参时可能引起的压栈出栈的开销。
减少PC跳转时对流水线的破坏。

劣势:
代码所占体积会更大。

1,为什么头文件编写内联函数?
实践反汇编证明如果放在.c当中,会根据函数大小来编译为是否为内联函数。如果未编译成内联函数,有悖设计之初的想法。

2,多个头文件调用是否会产生重定义? 如果当前编译器把该函数编译成内联函数是不存在重定义的问题的,毕竟是static修饰,仅在当前文件内生效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Tim-Cheng

你的鼓励是我最大的动力,奥利给

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

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

打赏作者

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

抵扣说明:

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

余额充值