9:c语言结构体、共同体、位运算、typedef/const

目录

 

1.结构体

结构体变量:

成员的获取和赋值

2.c结构体数组

3.c语言结构体类型的指针

通过结构体指针获取结构体成员

结构体数组 = 指针

结构体指针作为函数参数

4.c枚举类型 enum

5.C语言共用体(Union)

6.C语言位域

7.c语言位运算

8.C语言typedef:给类型起一个别名

按照类似的写法,还可以为函数指针类型定义别名,其实我不太清楚?:

typedef 和 #define 的区别

9.C语言const:禁止修改变量的值

const 和指针



1.结构体

在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体的定义形式为:

struct 结构体名{
    结构体所包含的变量或数组
};

注意大括号后面的分号;不能少,这是一条完整的语句。

 

像 int、float、char 等是由C语言本身提供的数据类型,不能再进行分拆,我们称之为基本数据类型;而结构体可以包含多个基本类型的数据,也可以包含其他的结构体,我们将它称为复杂数据类型或构造数据类型。

结构体变量:

既然结构体是一种数据类型,那么就可以用它来定义变量。例如:

struct stu stu1, stu2;

stu 就像一个“模板”,定义出来的变量都具有相同的性质。也可以将结构体比作“图纸”,将结构体变量比作“零件”,根据同一张图纸生产出来的零件的特性都是一样的。

//你也可以在定义结构体的同时定义结构体变量:

struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在学习小组
    float score;  //成绩
} stu1, stu2;
//无结构体名称,这样此后无法再定义结构体变量
struct{  //没有写 stu
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在学习小组
    float score;  //成绩
} stu1, stu2;

成员的获取和赋值

结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[ ]获取单个元素,结构体使用点号.获取单个成员。获取结构体成员的一般格式为:

结构体变量名.成员名;

除了可以对成员进行逐一赋值,也可以在定义时整体赋值,不过整体赋值仅限于定义结构体变量的时候,在使用过程中只能对成员逐一赋值,这和数组的赋值非常类似。整体赋值是默认值。

struct stu stus[10];会初始化stus数组,把模板stu放在stus为首的空间;而int arr[10];不会初始化,是因为,arr里直接是int字节数;

数组如果初始化,内部的值就是默认值。int arr[10] = {};相当于初始化

struct{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组
    float score;  //成绩
} stu1, stu2 = { "Tom", 12, 18, 'A', 136.5 };

需要注意的是,结构体是一种自定义的数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据,需要内存空间来存储。

 

9:c语言结构体、共同体、位运算、typedef/const_第1张图片

2.c结构体数组

定义结构体数组和定义结构体变量的方式类似:

#include
  2 int main(){
  3         struct teacher{
  4                 char *name;
  5                 int age;
  6         }class[]={
  7                 {"yz",20},
  8                 {"zzq",12}
  9         };
 10 
 11         printf("%d\n",class[0].age);
 12 
 13         struct teacher school[2];
 14         struct teacher ly,yyk;
 15         ly.age = 100;
 16         yyk.age = 200;
 17         ly.name = "ly";
 18         yyk.name = "yyk";
 19         school[0] = ly;
 20         school[1] = yyk;
 21         printf("%d\n",school[0].age);
 22 
 23 }
~           

3.c语言结构体类型的指针

指针也可以指向一个结构体,定义的形式一般为:

struct 结构体名 *变量名;

可以先定义结构体,再定义结构体的指针;也可以定义结构体的同时定义结构体指针;eg:

 1 #include
  2 int main(){
  3         struct stu{
  4                 char *name;
  5                 int age;
  6         }stu2,stu3 = {"yz",12},*pstu = &stu3;
  7 
  8         struct stu *stu1;
  9         struct stu s;
 10         s.name = "yz";
 11         s.age = 100;
 12 
 13         stu1 = &s;
 14 
 15         printf("%d\n",(*stu1).age);
 16         printf("%s\n",stu1->name);
 17         printf("pstu3.name=%s\n",pstu->name);
 18 }

注意,结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加&.

还应该注意,结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间,就像 int、float、char 这些关键字本身不占用内存一样;结构体变量才包含实实在在的数据,才需要内存来存储。

通过结构体指针获取结构体成员

(*ptr).name 或者 ptr->name

结构体数组 = 指针

 

结构体指针作为函数参数

结构体变量名代表的是整个集合本身,作为函数参数时传递的整个集合,也就是所有成员,而不是像数组一样被编译器转换成一个指针。如果结构体成员较多,尤其是成员为数组时,传送的时间和空间开销会很大,影响程序的运行效率。所以最好的办法就是使用结构体指针,这时由实参传向形参的只是一个地址,非常快速。

4.c枚举类型 enum

些数据的取值往往是有限的,只能是非常少量的整数.

定义:enum 类型名{值名字1=1,值名字2};enum 类型名{值名字1,值名字2}a,b;enum 类型名 a,b;

5.C语言共用体(Union)

通过前面的讲解,我们知道结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员。在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union),它的定义格式为:

union 共用体名{
    成员列表
};

共用体有时也被称为联合或者联合体,这也是 Union 这个单词的本意。

结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。

共用体也是一种自定义类型,可以通过它来创建变量

9:c语言结构体、共同体、位运算、typedef/const_第2张图片9:c语言结构体、共同体、位运算、typedef/const_第3张图片

 

6.C语言位域

在结构体定义时,我们可以指定某个成员变量所占用的二进制位数(Bit),这就是位域。请看下面的例子:

C语言标准还规定,只有有限的几种数据类型可以用于位域。在 ANSI C 中,这几种数据类型是 int、signed int 和 unsigned int(int 默认就是 signed int);到了 C99,_Bool 也被支持了。

struct bs{

unsigned m;

unsigned n: 4;

unsigned char ch: 6;

}

C语言标准规定,位域的宽度不能超过它所依附的数据类型的长度。通俗地讲,成员变量都是有类型的,这个类型限制了成员变量的最大长度,:后面的数字不能超过这个长度。


7.c语言位运算

 

C语言提供了六种位运算符:

运算符 & | ^ ~ << >>
说明 按位与 按位或 按位异或 取反 左移 右移

C语言中不能直接使用二进制,&两边的操作数可以是十进制、八进制、十六进制,它们在内存中最终都是以二进制形式存储,&就是对这些内存中的二进制位进行运算。其他的位运算符也是相同的道理。

8.C语言typedef:给类型起一个别名

C语言允许为一个数据类型起一个新的别名,就像给人起“绰号”一样。

起别名的目的不是为了提高程序运行效率,而是为了编码方便。例如有一个结构体的名字是 stu,要想定义一个结构体变量就得这样写:

struct stu stu1;

struct 看起来就是多余的,但不写又会报错。如果为 struct stu 起了一个别名 STU,书写起来就简单了:

STU stu1;

这种写法更加简练,意义也非常明确,不管是在标准头文件中还是以后的编程实践中,都会大量使用这种别名。

使用关键字 typedef 可以为类型起一个新的别名,语法格式为:

typedef  oldName  newName;

数组也是有类型的。例如char a1[20];定义了一个数组 a1,它的类型就是 char [20],

由上句可见,我认为:类型就是对这种类型数据占据大小的约束;

需要强调的是,typedef 是赋予现有类型一个新的名字,而不是创建新的类型。为了“见名知意”,请尽量使用含义明确的标识符,并且尽量大写。

再如,为指针类型定义别名:

typedef int (*PTR_TO_ARR)[4];//int  *ptr;

表示 PTR_TO_ARR 是类型int * [4]的别名,它是一个二维数组指针类型。

按照类似的写法,还可以为函数指针类型定义别名,其实我不太清楚?:

typedef int (*PTR_TO_FUNC)(int, int);
PTR_TO_FUNC pfunc;

typedef 和 #define 的区别

typedef 在表现上有时候类似于 #define,但它和宏替换之间存在一个关键性的区别。正确思考这个问题的方法就是把 typedef 看成一种彻底的“封装”类型,声明之后不能再往里面增加别的东西。

9.C语言const:禁止修改变量的值

有时候我们希望定义这样一种变量,它的值不能被改变,在整个作用域中都保持固定。例如,用一个变量来表示班级的最大人数,或者表示缓冲区的大小。为了满足这一要求,可以使用const关键字对变量加以限定:

const int MaxNum = 100; //班级的最大人数

创建常量的格式通常为:

const type name = value;

const 和指针

const 也可以和指针变量一起使用,这样可以限制指针变量本身,也可以限制指针指向的数据。const 和指针一起使用会有几种不同的顺序,如下所示:

 
  1. const int *p1;
  2. int const *p2;
  3. int * const p3;

在最后一种情况下,指针是只读的,也就是 p3 本身的值不能被修改;在前面两种情况下,指针所指向的数据是只读的,也就是 p1、p2 本身的值可以修改(指向不同的数据),但它们指向的数据不能被修改。

 

 

 

 

 

你可能感兴趣的:(语言篇-c++)