中午吃饭路上讨论了一下rust,go,c++其实go吧性能并不是这么美好,内存管理也不行,++(个人习惯把c和++说成一样的)又没有什么开发效率,rust主打安全内存虽然难写但好像写嵌入式还挺合适又比c快点,内存管理还不错又不和go一样容易把可怜的性能完爆,不过开发起来有点费劲... 还是在研究要不要学习一下rust....
好了言归正传今天还说c(此篇也是自己学习篇,如果谁感觉触及了谁的利益那就管不了了,最后一遍仅为自己学习)下面说说普通语法吧 确实语言用的比较多东西总忘 鼓励自己学习吧
一、struct
这个go语言的和他的差不多一样把,只是指针不能写在最外面
定义结构体变量
下面举一个例子来说明怎样定义结构体变量。
这个例子定义了一个结构名为string的结构体变量person。还可以省略变量名person,做如下定义:
定义多个具有相同形式的结构变量:
有一种结构体常常出现在函数内部,省略结构名,则称之为无名结构,如下:
结构体成员的获取与赋值
结构是一个新的数据类型,结构成员的表示方式为:结构变量.成员名
如果将"结构变量.成员名"看成一个整体,这样就可以像其他变量那样使用。
下面这个例子定义了一个结构变量stu1,分别给name、age、group赋值,并打印输出。
结构体数组
结构体数组就是具有相同结构类型的变量集合,假如要定义一个班级40个同学 的姓名、性别、年龄和住址, 可以定义成一个结构数组。如下所示:
结构体数组成员的访问是以数组元素为结构变量的, 其形式为:结构数组元素.成员名
例如:
结构体指针
结构体指针由一个加在结构变量名前的*操作符来定义,定义一个结构体指针如下:
使用结构体指针对结构体成员的访问与结构体变量对结构体成员的访问在表达方式不同。结构体指针对结构体成员的访问方式为:结构体指针名->结构体成员
给上面定义的结构体中name和age赋值的语句:
需要指出的是结构体指针是指向结构体的一个指针,即结构体中第一个成员的首地址,因此在使用之前应该对结构体指针初始化,即分配整个结构体长度的字节空间:
malloc()函数定义了一个大小为结构体长度的内存区域,然后将其地址作为结构体指针返回。
位结构
位结构是一种特殊的结构体,位结构定义的一般形式为:
其中数据类型必须是int(unsigned或signed,但当成员长度为1时, 会被认为是unsigned类型),整型常数必须是0~15的非负整数,表示二进制位个数。变量名是选择项,可以不命名,下面定义了一个位结构:
位结构成员的访问与结构体成员的访问相同,访问位结构中的bgcolor成员可写成:ch.bgcolor
举个例子
上面结构体定义了工资的信息,其中有两个只有1位的位结构成员,表示工人的状态以及工资是否已发放。
typedef定义结构体
typedef的作用就相当于给struct person取了一个别名student。whaosoft aiot http://143ai.com
二、enum
这个比较吐槽go竟然都没有。。。
用来同时定义多个常量
如果我们要编程实现一个日历,还用到星期一、星期二、...星期天等,我们可能会这样定义如下:
使用宏定义不是不可以,但这样的变量/宏定义多了之后,就显得代码不简洁、不明了。学习了枚举enum类型之后,我们就可以把以上宏定义如下定义:
这样定义Mon的值为1之后,Tue的值就被默认定义为2,Wed的值为3,依此类推。如果没写Mon=1的话,Mon的默认值就为0。例如:
从中间开始赋值的情况,见如下例子:
用来限定变量的取值范围
有时为了保证程序的健壮性而使用enum。
比如上面例子,枚举类型a的取值被限定在那12个变量中。
enum类型的定义方法
在定义enum的同时声明变量:
定义完enum之后再声明变量:
定义匿名的枚举变量:
enum在定义连续型的变量时非常好用,所以在单片机的头文件中会经常见到
三、C内存管理
C 语言为内存的分配和管理提供了几个函数。这些函数可以在 <stdlib.h> 头文件中找到。
序号 | 函数和描述 |
1 | void *calloc(int num, int size); 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。 |
2 | void free(void *address); 该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。 |
3 | void *malloc(int num); 在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。 |
4 | void *realloc(void *address, int newsize); 该函数重新分配内存,把内存扩展到 newsize。 |
注意:void * 类型表示未确定类型的指针。C、C++ 规定 void * 类型可以通过类型转换强制转换为任何其它类型的指针。
动态分配内存
编程时,如果您预先知道数组的大小,那么定义数组时就比较容易。例如,一个存储人名的数组,它最多容纳 100 个字符,所以您可以定义数组,如下所示:
但是,如果您预先不知道需要存储的文本长度,例如您向存储有关一个主题的详细描述。在这里,我们需要定义一个指针,该指针指向未定义所需内存大小的字符,后续再根据需求来分配内存,如下所示:
当上面的代码被编译和执行时,它会产生下列结果:
上面的程序也可以使用 calloc() 来编写,只需要把 malloc 替换为 calloc 即可,如下所示:
当动态分配内存时,您有完全控制权,可以传递任何大小的值。而那些预先定义了大小的数组,一旦定义则无法改变大小。
重新调整内存的大小和释放内存
当程序退出时,操作系统会自动释放所有分配给程序的内存,但是,建议您在不需要内存时,都应该调用函数 free() 来释放内存。
或者,您可以通过调用函数 realloc() 来增加或减少已分配的内存块的大小。让我们使用 realloc() 和 free() 函数,再次查看上面的实例:
当上面的代码被编译和执行时,它会产生下列结果:
您可以尝试一下不重新分配额外的内存,strcat() 函数会生成一个错误,因为存储 description 时可用的内存不足。