中午吃饭路上讨论了一下rust,go,c++其实go吧性能并不是这么美好,内存管理也不行,++(个人习惯把c和++说成一样的)又没有什么开发效率,rust主打安全内存虽然难写但好像写嵌入式还挺合适又比c快点,内存管理还不错又不和go一样容易把可怜的性能完爆,不过开发起来有点费劲... 还是在研究要不要学习一下rust....
好了言归正传今天还说c(此篇也是自己学习篇,如果谁感觉触及了谁的利益那就管不了了,最后一遍仅为自己学习)下面说说普通语法吧 确实语言用的比较多东西总忘 鼓励自己学习吧
一、struct
这个go语言的和他的差不多一样把,只是指针不能写在最外面
定义结构体变量
下面举一个例子来说明怎样定义结构体变量。
struct string
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
}person;
这个例子定义了一个结构名为string的结构体变量person。还可以省略变量名person,做如下定义:
struct string
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
};
struct string person; //定义结构名为string的结构体变量person
定义多个具有相同形式的结构变量:
struct string Liming, Liuqi, ...;
有一种结构体常常出现在函数内部,省略结构名,则称之为无名结构,如下:
struct
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
} Liming, Liuqi;
结构体成员的获取与赋值
结构是一个新的数据类型,结构成员的表示方式为:结构变量.成员名
如果将"结构变量.成员名"看成一个整体,这样就可以像其他变量那样使用。
下面这个例子定义了一个结构变量stu1,分别给name、age、group赋值,并打印输出。
#include <stdio.h>
int main()
{
struct
{
char *name; //姓名
int age; //年龄
char group; //所在小组
} stu1;
//给结构体成员赋值
stu1.name = "Tom";
stu1.age = 18;
stu1.group = 'A';
//读取结构体成员的值
printf("%s的年龄是%d,在%c组\n", stu1.name, stu1.age, stu1.group);
return 0;
}
结构体数组
结构体数组就是具有相同结构类型的变量集合,假如要定义一个班级40个同学 的姓名、性别、年龄和住址, 可以定义成一个结构数组。如下所示:
struct
{
char name[8];
char sex[2];
int age;
char addr[40];
}student[40];
结构体数组成员的访问是以数组元素为结构变量的, 其形式为:结构数组元素.成员名
例如:
student[0].name
student[30].age
结构体指针
结构体指针由一个加在结构变量名前的*操作符来定义,定义一个结构体指针如下:
struct string
{
char name[8];
char sex[2];
int age;
char addr[40];
}*student;
使用结构体指针对结构体成员的访问与结构体变量对结构体成员的访问在表达方式不同。结构体指针对结构体成员的访问方式为:结构体指针名->结构体成员
给上面定义的结构体中name和age赋值的语句:
strcpy(student->name, "acket"); //student->name就是(*student).name
student->age=18;
需要指出的是结构体指针是指向结构体的一个指针,即结构体中第一个成员的首地址,因此在使用之前应该对结构体指针初始化,即分配整个结构体长度的字节空间:
student=(struct string*)malloc(size of (struct string));
//size of (struct string)是自动求取string结构体的字节长度
malloc()函数定义了一个大小为结构体长度的内存区域,然后将其地址作为结构体指针返回。
位结构
位结构是一种特殊的结构体,位结构定义的一般形式为:
struct 位结构名
{
数据类型 变量名: 整型常数;
数据类型 变量名: 整型常数;
}位结构变量;
其中数据类型必须是int(unsigned或signed,但当成员长度为1时, 会被认为是unsigned类型),整型常数必须是0~15的非负整数,表示二进制位个数。变量名是选择项,可以不命名,下面定义了一个位结构:
struct
{
unsigned incon: 8; /*incon占用低字节 的0~7共8位*/
unsigned txcolor: 4;/*txcolor占用高字节的0~3位共4位*/
unsigned bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/
unsigned blink: 1; /*blink占用高字节的第7位*/
}ch;
位结构成员的访问与结构体成员的访问相同,访问位结构中的bgcolor成员可写成:ch.bgcolor
举个例子
struct info
{
char name[8];
int age;
struct addr address;
float pay;
unsigned state: 1;
unsigned pay: 1;
}workers;
上面结构体定义了工资的信息,其中有两个只有1位的位结构成员,表示工人的状态以及工资是否已发放。
typedef定义结构体
typedef struct person
{
int age ;
char *name;
char *sex;
}student;
student stu1; //此处可以用student来定义一个结构体变量
typedef的作用就相当于给struct person取了一个别名student。whaosoft aiot http://143ai.com
二、enum
这个比较吐槽go竟然都没有。。。
用来同时定义多个常量
如果我们要编程实现一个日历,还用到星期一、星期二、...星期天等,我们可能会这样定义如下:
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
使用宏定义不是不可以,但这样的变量/宏定义多了之后,就显得代码不简洁、不明了。学习了枚举enum类型之后,我们就可以把以上宏定义如下定义:
#include<stdio.h>
enum week {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
int main()
{
printf("%d",Tue);
return 0;
}
这样定义Mon的值为1之后,Tue的值就被默认定义为2,Wed的值为3,依此类推。如果没写Mon=1的话,Mon的默认值就为0。例如:
enum color {red,blue,green,yellow}; //red的值默认为0
从中间开始赋值的情况,见如下例子:
enum color {red,blue,green=5,yellow}; //red、bule、green、yellow的值依次为0、1、5、6
用来限定变量的取值范围
有时为了保证程序的健壮性而使用enum。
#include<stdio.h>
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec};
int main()
{
enum Month a = Feb;
printf("%d",a);
return 0;
}
比如上面例子,枚举类型a的取值被限定在那12个变量中。
enum类型的定义方法
在定义enum的同时声明变量:
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} a,b;
//这样就声明了两个枚举类型a和b
定义完enum之后再声明变量:
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec};
enum Month a = Feb;
定义匿名的枚举变量:
enum {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} a;
//这样就只能使用a这一个枚举类型的变量,不能再定义其他枚举类型了
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 个字符,所以您可以定义数组,如下所示:
char name[100];
但是,如果您预先不知道需要存储的文本长度,例如您向存储有关一个主题的详细描述。在这里,我们需要定义一个指针,该指针指向未定义所需内存大小的字符,后续再根据需求来分配内存,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{ char name[100];
char *description; strcpy(name, "Zara Ali"); /* 动态分配内存 */ description = (char *)malloc( 200 * sizeof(char) );
if( description == NULL ) { fprintf(stderr, "Error - unable to allocate required memory\n");
} else { strcpy( description, "Zara ali a DPS student in class 10th");
} printf("Name = %s\n", name );
printf("Description: %s\n", description );
}
当上面的代码被编译和执行时,它会产生下列结果:
Name = Zara Ali Description: Zara ali a DPS student in class 10th
上面的程序也可以使用 calloc() 来编写,只需要把 malloc 替换为 calloc 即可,如下所示:
calloc(200, sizeof(char));
当动态分配内存时,您有完全控制权,可以传递任何大小的值。而那些预先定义了大小的数组,一旦定义则无法改变大小。
重新调整内存的大小和释放内存
当程序退出时,操作系统会自动释放所有分配给程序的内存,但是,建议您在不需要内存时,都应该调用函数 free() 来释放内存。
或者,您可以通过调用函数 realloc() 来增加或减少已分配的内存块的大小。让我们使用 realloc() 和 free() 函数,再次查看上面的实例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{ char name[100];
char *description; strcpy(name, "Zara Ali"); /* 动态分配内存 */ description = (char *)malloc( 30 * sizeof(char) );
if( description == NULL ) { fprintf(stderr, "Error - unable to allocate required memory\n");
} else { strcpy( description, "Zara ali a DPS student.");
} /* 假设您想要存储更大的描述信息 */ description = realloc( description, 100 * sizeof(char) );
if( description == NULL ) { fprintf(stderr, "Error - unable to allocate required memory\n");
} else { strcat( description, "She is in class 10th");
} printf("Name = %s\n", name );
printf("Description: %s\n", description ); /* 使用 free() 函数释放内存 */ free(description);
}
当上面的代码被编译和执行时,它会产生下列结果:
Name = Zara Ali Description: Zara ali a DPS student.She is in class 10th
您可以尝试一下不重新分配额外的内存,strcat() 函数会生成一个错误,因为存储 description 时可用的内存不足。