![](https://img-blog.csdnimg.cn/20201214182742903.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
C语言基础
主要是分享一些在实战中的常用知识点,还有就是自己读《C和指针》的阅读笔记,非常好的一本书,有些讲解非常到位我就照搬了,有些加入一些自己的理解
一叶知秋@qqy
这个作者很懒,什么都没留下…
展开
-
C语言面向对象思维
分享一篇写得挺好的C语言面向对象的文章:https://blog.csdn.net/lzs940320/article/details/109216659转载 2021-02-08 16:20:16 · 154 阅读 · 0 评论 -
C语言结构体字节对齐
前言对C语言结构体进行字节对齐的合理排列并不仅仅可以节省非常大的空间,最重要的是体现个人编程的良好习惯。以N对齐方式所谓的以N对齐方式纯属我瞎掰的,哈哈。所有的结构体成员在定义结构体分配内存时都要与所有成员中占内存最多的数据类型所占内存空间的字节数对齐。**假如这个字节数为 N,**那么对齐的原则是:理论上所有成员在分配内存时都是紧接在前一个变量后面依次填充的,但是如果是“以 N 对齐”为原则,那么,如果一行中剩下的空间不足以填充某成员变量,即剩下的空间小于某成员变量的数据类型所占的字节数,则该成原创 2021-02-08 14:56:09 · 231 阅读 · 0 评论 -
C语言中三目运算符? :的使用
在C语言编程中擅长使用三目运算是可以使代码极大地清爽简洁的。三目运算符由?和:组成,在实际使用中常可以简化为:b ? x : y,其含义为先判断表达式b是否成立,注意:这里说的是表达式b,而不是b,举个例子Int result = 0;result = (10 < 20)? 1:0;如果换成通俗点的写法就是:Int result = 0;if (10 < 20) result = 1;else result = 0;在编程中涉及到运算符比较多的场合不要太吝啬使用小括号(原创 2021-02-08 13:42:29 · 3886 阅读 · 0 评论 -
C语言a=b==c的使用
前言C语言有着许许多多的运算符,一不注意可能就见到个奇奇怪怪看不懂的东西,例如下面这个:set_result = AstPmmRestoreParam(kAstPmmAuthRoot) == 0;如果简化一下大概就是如标题所示a=b==c,其实现在看着也还是比较可爱的了,但是依稀记得第一次见时,快挠破了头。阐述a=b==c观察结构,可以发现a和b之间存在运算符=,那么同理b和c之间肯定也是一个运算符,总不能变出来个新品种吧。既然也是运算符,而且中间是连接的,就说明肯定是双等号运算符==,那就好分原创 2021-02-08 13:16:06 · 14666 阅读 · 2 评论 -
C/C++ 动态库(dll)与静态库(lib)
前言在编写程序时,或者细心的话,都会发现见过一些后缀名为lib和dll的文件,这些文件其实就是所谓的静态库和动态库。静态库静态库在windows平台的后缀名如标题所示为**.lib**,在linux平台则为**.a**。静态库是在静态编译时由编译器到指定目录寻找并且进行链接的软件库,一旦链接完成,最终的可执行程序中就包含了该库文件中的所有有用信息,包括代码段、数据段等。动态库动态库在windows平台的后缀名为标题所示为**.dll**,在linux平台则为**.so**。动态库是在应用程序运原创 2021-02-08 11:14:18 · 593 阅读 · 1 评论 -
C语言动态内存分配,malloc、free
前言涉及到分配动态内存时,往往是应用在数组上,也会在结构体上应用。说下为什么在数组上比较常用吧。在定义数组时,必须要指定大小,而且其所有元素在内存上是连续存储的。可是我们所要存储的目标数据经常是在程序运行起来之后才会知道具体大小,这也就导致了经常在定义数组时,选择直接定义一个比较大的size,可是往往伴随而来的就是内存空间的浪费。还有就是如果数组的实际存储数据超过数组的空间大小,会直接引发异常。malloc和free函数原型:void *malloc( size_t size );void f原创 2020-12-21 22:29:10 · 504 阅读 · 0 评论 -
C语言的联合体与变体记录
结构体是将一个对象(内存空间)解释为C语言中多种类型的综合.联合是将一个对象(内存空间)在不同时候解释为C语言中不同的类型.// 联合typedef union FirstUnionTag FirstUnionunion FirstUnion{ float f; int i;} ;FirstUnion myunion;使用 myunion.f 时, fi所占内存中的内容将被解释为一个float数; 当使用 myunion.i 时, fi所占内存中的内容将被解释为一个int原创 2020-12-21 21:54:44 · 336 阅读 · 1 评论 -
C语言联合体UNION
结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员。在C语言中,还有另外一种和结构体非常类似的语法,叫做联合体(Union),它的定义格式为:union 联合体名{成员列表};结构体和联合体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而联合体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。结构体占用的内存大于等于所有成员占用的内存的总和(成员之间因为格式对齐的原因),联合体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一原创 2020-12-21 08:35:28 · 277 阅读 · 0 评论 -
结构的存储分配
结构的存储分配:结构在内存中是如何实际存储的呢?编译器按照成员列表的顺序- 一个接-一个地给每个成员分配内存。只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。即以成员最大的字节为准,从第一个开始往后分配内存空间,当成员小于最大类型字节时,就补齐至最大的成员字节数。下面的一个例子:#include<stdio.h> typedef struct node{ char a; //1字节 float b; //4字节 doubl.原创 2020-12-14 19:51:05 · 151 阅读 · 0 评论 -
结构体(基础知识)
结构声明:方式:struct tag { member-list } variable-list;例子:struct { int a; char b; float c;} x;声明了一个名叫x的变量,包含三个成员:一个整数、一个字符、一个浮点数。struct { int a; char b; float c;} y[2], *z;创建了y和z,y是一个数组,包含20个结构。z原创 2020-12-14 15:24:02 · 762 阅读 · 0 评论 -
字符串函数strcpy、strcat、strcmp、strncpy、strncat、strncmp、strchr、strrchr、strpbrk、strstr、strspn、strcspn等
复制字符串:strcpy原型:char *strcpy( char *dst, char const *src );作用:把参数src字符串复制到dst参数。注意:参数src和参数dst在内存中如果出现重叠,其结果是未定义的,可能会有意想不到的错误。由于dst参数将进行修改,所以他必须是字符串数组或者是一个指向动态分配内存的数组的指针,不能使用字符串常量。目标参数以前的内容将被覆盖丢失。即使新的字符串比dst原先的内存更短,因为新字符串是以NUL字节结尾,所以老字符串最后剩余的几个字符原创 2020-12-13 21:31:02 · 796 阅读 · 0 评论 -
register关键字
以前觉得程序能用就成,但是现在才意识到,在保证良好的可读性的前提下,程序的效率依然很重要。register是一个很棒的关键字,可以请求编译器尽可能的将变量存在CPU内部寄存器中,而非通过内存寻址访问,这样做的话有利有弊。使用register声明的变量,必须是单个的值,且长度绝对不可以大于整形的长度,因为变量是直接存贮在CPU中,所以可能不能像普通变量那样使用寻址符&来获取register变量的地址。但是register就是快啊!!!他是存储在CPU寄存器中的,速度远快于内存,所而且他小啊,换原创 2020-12-13 13:58:59 · 231 阅读 · 1 评论 -
深究C语言数组那点事(一维数组)
数组名和指针的相似:在C语言中,几乎所有的数组在使用时,数组名都是作为一个指针常量,即数组第一个元素的地址,来使用的。其类型,完全取决于数组元素的类型,如果他们是int类型,那么数组名的类型就是指向“int的常量指针”,如果是其他类型,那么数组名就是指向其他类型的常量指针。如此看来是不是二者非常相似。数组名与指针的不同:如果仅以他俩的相似点就一概而论说他俩是一个玩意那就大错特错了,他们的不同点也非常干脆。例如数组具有确定数量的元素,可能你想说我可以定义一个不定长的数组啊,但是想一下,你在使用它时原创 2020-12-12 22:26:13 · 233 阅读 · 0 评论 -
C语言函数传递参数的总结
在C语言中,函数传递的方式是以传值的方式进行传递的,实际所传递的是实参的一份拷贝。所以函数可以自由的修改他的形参(实参的拷贝),而不会对程序传递的参数造成改变。在传递数组时,数组名其实也是通过传值的方式进行传递的,但是传递给函数的是一个指向数组的指针的拷贝,即使你对这个指针进行N多份的拷贝,每份的指针也只指向一个地址,所以在函数中如果在数组的形参中使用下标操作,也会改变数组实际的值,这是因为出发了间接访问操作。所以在函数中修改数组的元素实际上修改的就是调用程序的数组,这个行为就是传址调用,如果同时也希望传递原创 2020-12-12 15:47:05 · 350 阅读 · 0 评论 -
C语言定义可变参数函数
stdarg宏可变参数列表是通过stdarg.h头文件内的stdarg宏来实现的,stdarg.h头文件是标准库的一部分。在头文件中声明了一个va_list类型,还有三个宏--va_start、va_arg和va_end,在使用时需要先定义一个类型为va_list的变量,与这几个宏配合使用,访问参数值。在函数内需要声明一个叫var_arg的变量,用于访问参数列表的未确定部分。这个变量是通过调用va_start来初始化的。其第一个参数是va_list变量的名字,第2个参数是省略号前最后一个有名字的参数原创 2020-12-12 15:28:47 · 1341 阅读 · 0 评论 -
static的妙处
最近公司改革,提倡模块化编程,其实早就有这个概念了,在大学期间使用python时经常将不同的子功能或者通用的代码封装成模块库,有时为了加密,只开放访问接口,然后将内部数据和函数都不允许外部访问,当时最常见的做法是打包成pyc文件,可以调用,但是无法查看内部结构。而在嵌入式方面当时只是将各个功能对应的封装成C文件和H文件,只是做了功能的模块化,而还是将所有秘密呈现出来。static关键字为实现模块间的独立性私密性创造了可能,由它定义的变量、参数、函数都只归当前代码块所有,最后的结果就是,我可以对外开放接口原创 2020-12-12 11:10:51 · 242 阅读 · 1 评论 -
C语言运算时自动转换类型
最近在使用C语言做开发时遇见一些之前没注意过的问题,例如在做运算时,假设从内存(或者其他方式)中获取一个四字节的int数据,假设他是xxx乘10的7次方,而我需要的是10的6次方,即需要对获取的数据进“/10”操作。当时最大的疑问是我取得的数据是一个十六进制,而“/10”操作貌似是十进制的。这其实涉及到了运算时的自动类型转换,我猜想很多人这样使用过。int main(){ int int_num = 50; float float_num = 0.0; float_num =原创 2020-12-10 20:40:54 · 1983 阅读 · 0 评论 -
return不带参数的使用
return在使用时主要有两种形式:1、一种是带参数的,即return xxx;,一种是不带参数的,即return;带参数时的作用是结束当前函数,不再向下运行,且返回参数值。2、而不带参数时也是结束当前函数,但是不同点在于,没有返回值,只是单纯的结束此函数。在不同的场景下,我们可以根据需要进行选择,例如执行一个函数,此函数没有返回值,但是当触发某一条件时,函数剩余语句就没有运行的必要了。此时可以使用return在此处结束函数。...原创 2020-12-10 20:05:35 · 2487 阅读 · 0 评论 -
memcpy()用法
函数原型:void * memcpy ( void * dest, const void * src, size_t num );函数方法所在的头文件为:#include <string.h>在使用memcpy()时,只针对src指针所指的内部数据,按照一个字节一个字节的复制,共复制num个字节到dest指针所指的内存地址上,由于memcpy()只是针对内存的字节,而非数据的类型,所以在使用时非常灵活。但是在使用memcpy()时也要注意给dest分配足够大的空间,至少不原创 2020-12-10 19:59:55 · 2082 阅读 · 1 评论 -
c_str()方法解析
偶然之间看见这样一条语句,源自师傅给的一个以前C++项目中,str.c_str(),经过百度和多位大佬的博客得知,c_str()方法是返回一个C语言字符串的指针常量(即可读不可改变),内容与调用此方法的原字符串相同。即通过c_str()方法,补充C中没有string类型的问题,,通过STRING类对象的成员函数c_str()把string对象转换为c中字符串的样式。其函数原型为:const char *c_str();通过观察不难发现,c_str()是一个指针(实际上是一个临时指针),指向一个字符.原创 2020-12-10 19:36:36 · 13410 阅读 · 0 评论 -
C语言相关不能使用BOOL强转!!!
在编程过程中有时会涉及到类型转换问题,例如8位的0x63,转为32位时,会自动在前方补0,即变成0x00000063,不会涉及到丢精度或者其他危险。而在涉及32位转8时则要特别注意,因为以0x12345678为例,转为uint8时则变为0x78,剩余高位精度丢失,由于数据丢失可能使程序发生无法想象的问题。标准的做法是:ret_data[0] = (UInt8)longitude&0xFF;ret_data[1] = (UInt8)(longitude >> 8)&原创 2020-12-07 23:51:58 · 902 阅读 · 0 评论 -
数组做函数参数时的使用
在函数需要将数组作为参数传入时,数组是传址调用,即将数组作为实参时,传入的其实是数组的首地址,实质上是一个指针。在定义函数时可以定义一个指针,然后去调用数组,此时在函数内部的操作会直接修改数组的实际对应元素。因为传输进函数的数组的本质就是数组的首元素地址,函数内部按照地址去修改当然相当于直接操作数组。在需要一个函数返回数据时也可以用定义指针,然后传入数组,将需要传回的数据放进数组内,在函数结束调用后,去相应的数组内取回数据。但是需要注意的是,数组传入函数时只有当传入的是一个数组名时才是传址调用,原创 2020-12-06 21:10:39 · 3979 阅读 · 0 评论 -
sizeof、strlen、OF_OFFSET_OF、CONTAINER_OF的区别
sizeof()功能:计算数据空间的字节数1.与strlen()比较 strlen()计算字符数组的字符数,以"\0"为结束判断,不计算为'\0'的数组元素,因为字符串都是以‘\0’结尾。 而sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示。 举个例子就明白了,int i。可以用sizeof i或者sizeof(i),求得的是i这个对象所占用空间字节数,显然是4;sizeof(int),求得的是这个object类型的空间大小。比如...原创 2020-12-06 19:13:42 · 173 阅读 · 0 评论 -
大小端知识
大端和小端(Big-Endian和Little-Endian):1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。以多位字节数据0x12345678为例:1)大端模式:高地址-----------------> 低地址0x12 | 0x34 | 0x56 | 0x782)小端模式:低地址 ------------------...转载 2020-12-06 17:16:28 · 1107 阅读 · 0 评论