
C
文章平均质量分 87
废言Pro
时间加努力
展开
-
Using GNU C __attribute__
One of the best (but little known) features of GNU C is the__attribute__mechanism, which allows a developer to attach characteristics to function declarations to allow the compiler to perform more error checking. It was designed in a way to be compatible..原创 2021-03-26 09:42:06 · 125 阅读 · 0 评论 -
C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻
一、前言 二、变量与指针的本质 三、指针的几个相关概念 四、指向不同数据类型的指针 五、总结 一、前言如果问C语言中最重要、威力最大的概念是什么,答案必将是指针!威力大,意味着使用方便、高效,同时也意味着语法复杂、容易出错。指针用的好,可以极大的提高代码执行效率、节约系统资源;如果用的不好,程序中将会充满陷阱、漏洞。这篇文章,我们就来聊聊指针。从最底层的内存存储空间开始,一直到应用层的各种指针使用技巧,循序渐进、抽丝剥茧,以最直白的语言进行讲解,让你一..转载 2021-02-04 10:23:26 · 237 阅读 · 0 评论 -
聊聊C语言和指针的本质
很多编程语言都以 “没有指针” 作为自己的优势来宣传,然而,对于C语言,指针却是与生俱来的。那么,什么是指针,为什么大家都想避开指针。很简单, 指针就是地址,当一个地址作为一个变量存在时,它就被叫做指针,该变量的类型,自然就是指针类型。指针的作用就是,给出一个指针,取出该指针指向地址处的值。为了理解本质,我们从计算机模型说起。宏观看来,计算机可以分为两类:存储-执行计算机。这...转载 2020-02-28 17:38:50 · 162 阅读 · 0 评论 -
用户态使用 glibc/backtrace 追踪函数调用堆栈定位段错误
一般察看函数运行时堆栈的方法是使用 GDB(bt命令) 之类的外部调试器, 但是, 有些时候为了分析程序的 BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的.#1 glibc 获取堆栈信息的接口在 glibc 头文件 execinfo.h 中声明了三个函数用于获取当前线程的函数调用堆栈.#1.1#include <execinfo.h...转载 2019-07-10 15:03:43 · 1296 阅读 · 0 评论 -
C语言宏的用法详解
1、简介宏在C语言中是一段有名称的代码片段。无论何时使用到这个宏的时候,宏的内容都会被这段代码替换掉。主要有两种宏,他们的区别主要是在使用上面,一种是在使用时类似于数据对象称为Object-like,另一种在使用时类似于函数调用称为Function-like。在C语言使用#define来定义宏你可以将任意的有效的标识符定义为宏,设置C语言的关键字也可以。但是在C语言中defined不可以作...转载 2019-06-28 08:55:17 · 18990 阅读 · 4 评论 -
Built-in Functions Provided by GCC
Other Built-in Functions Provided by GCCGCC provides a large number of built-in functions other than the ones mentioned above. Some of these are for internal use in the processing of exceptions or...原创 2019-04-09 14:57:40 · 1150 阅读 · 0 评论 -
linux内核C -- 第10课:内联函数探究
属性声明:noinline & always_inline这一节,接着讲 __attribute__ 属性声明,__attribute__可以说是 GNU C 最大的特色。我们接下来继续讲一下跟内联函数相关的两个属性:noinline 和 always_inline。这两个属性的用途是告诉编译器:编译时,对我们指定的函数内联展开或不展开。它们的使用方法如下。static ...原创 2019-02-28 15:18:46 · 893 阅读 · 0 评论 -
linux内核C -- 第09课:链接过程中的强符号和弱符号
属性声明:weakGNU C 通过 __attribute__ 声明weak属性,可以将一个强符号转换为弱符号。使用方法如下。void __attribute__((weak)) func(void);int num __attribte__((weak);编译器在编译源程序时,无论你是变量名、函数名,在它眼里,都是一个符号而已,用来表征一个地址。编译器会将这些...原创 2019-02-25 17:26:29 · 894 阅读 · 0 评论 -
linux内核C -- 第08课:变参函数的格式检查——format
属性声明:formatGNU 通过 __attribute__ 扩展的 format 属性,用来指定变参函数的参数格式检查。它的使用方法如下:__attribute__(( format (archetype, string-index, first-to-check)))void LOG(const char *fmt, ...) __attribute__((forma...原创 2019-02-25 17:24:09 · 649 阅读 · 1 评论 -
linux内核C -- 第07课:地址对齐那些事儿
属性声明:alignedGNU C 通过 __attribute__ 来声明 aligned 和 packed 属性,指定一个变量或类型的对齐方式。这两个属性用来告诉编译器:在给变量分配存储空间时,要按指定的地址对齐方式给变量分配地址。如果你想定义一个变量,在内存中以8字节地址对齐,就可以这样定义。int a __attribute__((aligned(8));通过 ali...原创 2019-02-25 17:20:48 · 1427 阅读 · 1 评论 -
linux内核C -- 第06课:U-boot 镜像自拷贝分析——section 属性
GNU C 的扩展关键字:__attribute__GNU C 增加一个 __atttribute__ 关键字用来声明一个函数、变量或类型的特殊属性。声明这个特殊属性有什么用呢?主要用途就是指导编译器在编译程序时进行特定方面的优化或代码检查。比如,我们可以通过使用属性声明指定某个变量的数据边界对齐方式。__attribute__的使用非常简单,当我们定义一个函数、变量或类型时,直接在...原创 2019-02-25 17:18:38 · 541 阅读 · 1 评论 -
linux内核C -- 第05课:零长度数组
什么是零长度数组顾名思义,零长度数组就是长度为0的数组。ANSI C 标准规定:定义一个数组时,数组的长度必须是一个常数,即数组的长度在编译的时候是确定的。在ANSI C 中定义一个数组的方法如下:int a[10];C99 新标准规定:可以定义一个变长数组。int len;int a[len];也就是说,数组的长度在编译时是未确定的,在程序运行的时候才确...原创 2019-02-25 17:06:10 · 858 阅读 · 4 评论 -
linux内核C -- 第04课:Linux内核第一宏——container_of
typeof 关键字ANSI C 定义了 sizeof 关键字,用来获取一个变量或数据类型在内存中所占的存储字节数。GNU C 扩展了一个关键字 typeof,用来获取一个变量或表达式的类型。这里使用关键字可能不太合适,因为毕竟 typeof 还没有被写入 C 标准,是 GCC 扩展的一个关键字。为了方便,我们就姑且称之为关键字吧。通过使用 typeof,我们可以获取一个变量或表达式...原创 2019-02-25 17:05:10 · 435 阅读 · 0 评论 -
linux内核C -- 第03课:宏构造利器——语句表达式
基础复习:表达式、语句和代码块表达式表达式和语句是 C 语言中的基础概念。什么是表达式呢?表达式就是由一系列操作符和操作数构成的式子。操作符可以是 C 语言标准规定的各种算术运算符、逻辑运算符、赋值运算符、比较运算符等。操作数可以是一个常量,也可以是一个变量。表达式也可以没有操作符,单独的一个常量甚至是一个字符串,也是一个表达式。下面的字符序列都是表达式:2 + 3 2 i ...原创 2019-02-25 17:03:26 · 233 阅读 · 0 评论 -
Linux 内核C -- 第02课:驱动中的指定初始化
什么是指定初始化在标准 C 中,当我们定义并初始化一个数组时,常用方法如下:int a[10] = {0,1,2,3,4,5,6,7,8};按照这种固定的顺序,我们可以依次给 a[0] 和 a[8] 赋值。因为没有对 a[9] 赋值,所以编译器会将 a[9] 默认设置为0。当数组长度比较小时,使用这种方式初始化比较方便。当数组比较大,而且数组里的非零元素并不连续时,这时候再按...原创 2019-02-25 17:01:46 · 179 阅读 · 0 评论 -
Linux 内核C -- 第01课,C 语言语法扩展
Linux 内核驱动中的奇怪语法大家在看一些 GNU 开源软件,或者阅读 Linux 内核、驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来“怪怪的”。说它是C语言吧,貌似又跟教材中的写法不太一样;说它不是 C 语言呢,但是这些程序确确实实是在一个 C 文件中。此时,你肯定怀疑你看到的是一个“假的 C 语言”!比如,下面的宏定义:#define mult_...原创 2019-02-25 17:00:15 · 618 阅读 · 0 评论 -
有关likely和unlikely??
在linux中判断语句经常会看到likely和unlikely,例如:if(likely(value)){}else{}简单从表面上看if(likely(value)) == if(value),if(unlikely(value)) == if(value)。也就是likely和unlikely是一样的,但是实际上执行是不同的,加likely的意识是value的值为真的可能性...转载 2019-01-15 15:13:24 · 310 阅读 · 0 评论 -
printf("%d",5.01)和printf("%f",5)的输出结果
printf("%f\n",5); printf("%d\n",5.01); printf("%f\n", (float)5); printf("%f\n", 5.f); 输出结果:$ ./test0.00000018897856105.0000005.000000看到结果,会感觉非常奇怪。1处怎么会输出0呢?2又为何会显示这转载 2013-09-20 15:34:00 · 927 阅读 · 0 评论 -
字节那些事儿
1、前言 作为一名 C/C++ 程序员,字节是我们天天都要与之打交道的一个东西。我们和它熟稔到几乎已经忘记了它的存在。可是,它自己是不甘寂寞的,或迟或早地,总会在某些时候探出头来张望,然后给你一个腿儿绊。其实,只要你真正了解了它的底细,你就会畅行无阻。在本文中,我们将首先简要了解一下字节的概念,然后着重了解一下字节序问题和字节对齐问题。2、什么是字节 我们知道,二进制计算机(也转载 2013-09-17 23:20:26 · 797 阅读 · 0 评论 -
位域
如下代码[cpp] view plaincopy#include "stdio.h" struct kk { unsigned a:2; unsigned b:3; unsigned c:2; unsigned d:1; } kt; int main() { cha转载 2013-09-17 18:42:20 · 885 阅读 · 0 评论 -
static,inline,volatile的作用
1、static(1)先来介绍它的第一条也是最重要的一条:隐藏。当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。下面是a.c的内容char a = 'A'; // global variable void msg() {转载 2013-09-01 23:17:10 · 643 阅读 · 0 评论 -
创建简单的静态库和动态库
1、vim test.h、test.c和main.c;test.h为该函数库的头文件。test.c是函数库的源程序,其中包含函数test,该函数将在屏幕上输出printf("test for lib.\n");main.c为测试库文件的主程序,在主程序中调用了公用函数test。 2、将test.c编译成test.o文件; 无论静态库,还是动态库,都是由.o文件创建的。因此,原创 2013-07-10 09:36:06 · 672 阅读 · 0 评论 -
C语言中可变参数的宏 __VA_ARGS__
C语言中可变参数的宏 __VA_ARGS__ 1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化成字符串。 例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing).#incldue #define PSQR(x) printf("转载 2013-06-05 20:31:43 · 2791 阅读 · 0 评论