1.先讲一下weak的使用
在阅读代码过程中会发现一些奇怪的代码,比如attribute((weak)),就会很疑惑这个weak有啥用?带着好奇去了解一下。
在这篇博客中可以了解到强弱符号的知识C语言中的强符号和弱符号_乐行僧丶的博客-CSDN博客
他的文章中说明,强弱符号针对的是处于同一工程下在不同源文件下定义的全局变量符号,链接器只处理global的符号而不处理local的符号。
强符号:函数和初始化的全局变量所生成的符号。
弱符号:未初始化的全局变量所生成的符号。
连接器处理优先级:
(1)如果出现多个强符号,最终会出现链接错误即符号的重定义。
(2)如果出现强符号和弱符号,编译器最终会选择强符号。
(3)如果出现多个同名弱符号,编译器最终会选择内存占用量最大的那个符号。
我根据上述博客也做了个小实验,具体看下图
b.c文件:
a.c文件:
执行结果:
x = 21, y = 0
x size = 2
从结果引发的思考:由于两个文件的x都是全局非静态变量所以共用了地址?只是操作的长度不同
如果将一边的x修饰为static则不会出现这样的情况。
...原来图片可以直接拖过来
2.attribute的使用
__attribute__((name(arg))):name 可以是 section("存储区域")放在特定区域保存
还有上面提到的weak等,但是weak没有参数。unused 是用来修饰函数的,使用之后就不会报那种未使用的错误。还有很多参数放在下面链接里了。
还有一种用法就是修饰函数。
一个比较好用的dbug函数参数是否错误的方法。
void myprint(const char *format,...)
__attribute__((format(printf,1,2)));//(printf,m,n) m是format出现的位置,n是...出现的位置
void myprint(const char *format,...)
{
}
void test()
{
myprint("i=%d\n",6);
myprint("i=%s\n",6);
myprint("i=%s\n","abc");
myprint("%s,%d,%d\n",1,2);
}
int main(int agc,char * agv[])
{
test();
return 0;
}
//编译之后报的警告 如果把format属性去掉那么它将没有warning
attribute.c: In function ‘test’:
attribute.c:23:18: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
myprint("i=%s\n",6);
~^
%d
attribute.c:25:16: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
myprint("%s,%d,%d\n",1,2);
~^
%d
attribute.c:25:22: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat=]
myprint("%s,%d,%d\n",1,2);
使用gcc -Wall 来编译 会打印格式化参数是否匹配错误。
format(printf, m, n), m是格式化的字符串位置就是那个"%s %d"这个字符串是第几个参数,从1开始数,n就是可变参数是第几个,可变参数就是那个... 三个点来表示的那个。
arrtibute详细说明可以参考:Function Attributes - Using the GNU Compiler Collection (GCC)