一.结构体

1.1 结构体struct定义及初始化

#include <stdio.h> // 这个头文件在系统目录下
#include <stdlib.h> // 使用了system函数
#include <Windows.h> // 结构体简单使用
void structUseDemo(void);
// 输出student结构体的内容
void print_student(struct student st); // 说明一种结构体类型
struct student { char name[]; // << 姓名
int age; // << 年龄
int sex; // << 性别
int class_id; // << 班级ID }; int main() { structUseDemo(); system("pause");
return ; } void structUseDemo(void) { // 定义结构体变量后赋值
struct student st1;
strcpy(st1.name,"张三");
st1.age = ;
st1.sex = ; // 0代表男,1代表女
st1.class_id = ; print_student(st1); printf("------------------------------------\n"); // 定义一个结构体变量,同时初始化它的内容
struct student st2 = {"奥巴马",,,};
print_student(st2); printf("------------------------------------\n"); struct student st3 = {"希拉里"}; // 只初始化第一个成员,后面都是0
print_student(st3); printf("------------------------------------\n");
struct student st4 = {}; // 所有成员都初始化为0
print_student(st4); printf("------------------------------------\n");
struct student st5 = {.sex = ,.name = "马英九"};
print_student(st5); } void print_student(struct student st){ printf("name=%s\n", st.name);
printf("age=%d\n", st.age); if (st.sex == ) {
printf("sex=%s\n", "男");
}
else {
printf("sex=%s\n", "女");
} printf("class_id=%d\n",st.class_id); }

执行结果:

1.2 结构体的内存对齐

编译器在编译一个结构的时候总是采用内存对齐模式,结构体总是以最大的成员作为对齐单位,以偶数位对齐。

如果结构体的所有成员都是同一种类型,那么这个结构体在内存和数组的存放方式是一样的。

#include <stdio.h> // 这个头文件在系统目录下
#include <stdlib.h> // 使用了system函数
#include <Windows.h> // 结构体的简单使用1
void structUseDemo1(); // 结构体当中的所有成员在内存当中都是连续存放的
struct A { int a1;
int a2; }; struct B { char a2; // 结构体成员是要对齐的
int a1; }; struct C{ char a1;
char a2;
int a3; }; struct D{ char a1;
int a3;
char a2; }; struct F { char a1;
short a2;
char a3;
int a4; }; struct H { char a1;
short a2;
int a3;
short a4;
char a5; }; int main() { structUseDemo1(); system("pause");
return ; } void structUseDemo1(){ struct A a = {,}; // 定义并且初始化
int *p = (int *)&a; printf("%u\n",sizeof(a)); // 输出结果为8
printf("%d\n",*p);
printf("%d\n",p[]); printf("----------- struct B -------------\n"); struct B b = {,};
printf("%u\n",sizeof(b)); // 输出结果为8 printf("------------- struct C -----------\n");
struct C c = { };
printf("%u\n",sizeof(c)); printf("------------ struct D ------------\n");
struct D d = {};
printf("%u\n",sizeof(d)); // 输出结果为12 !!!:因此struct C的写法比struct D的写法更合理 printf("------------ struct F ------------\n");
struct F f = {,,,};
printf("%p\n",&f); printf("%u\n",sizeof(f)); // 输出结果为12,结构体的对齐总是以偶数位进行对齐 }

执行结果:

内存对齐示意图:

1.3 指定结构体元素的位字段

定义一个结构体的时候可以指定具体元素的位长

    struct test{
char a : ;//指定元素为2位长,不是2个字节长
};

1.4 结构体数组

可以使用下列两种形式来定义结构体数组

void structArrayUseDemo() {

    struct student st[]; // 定义一个结构体变量数组
strcpy(st[].name,"张三");
st[].age = ;
st[].sex = ;
st[].class_id = ; strcpy(st[].name, "李四");
st[].age = ;
st[].sex = ;
st[].class_id = ; strcpy(st[].name, "王五");
st[].age = ;
st[].sex = ;
st[].class_id = ; for (int i = ; i < ; i++) {
print_student(st[i]);
printf("--------------------------------\n");
};
} void sturctArrayUseDemo1(){ //struct student st[5] = { 0 }; // 将所有成员都置为0
struct student st[] = { { "张三", , , ,}, { "李四", , , , }, { "王五", , , ,}, { "赵六", , , ,}, { "陈七", , , ,} };
for (int i = ; i < ; i++) {
print_student(st[i]);
printf("--------------------------------\n");
}; }

1.5 结构体嵌套结构体,结构体赋值及结构体指针

例1:结构体嵌套结构体赋值:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h> #pragma warning(disable:4996)

  struct B {

    int a1;
    struct A a2; // 这个结构体的成员是另一个结构体

  };

  struct C {

    int a1;
    struct B a2;

  };

static void structUseDemo();

static void structUseDemo() {

    struct B b;
b.a1 = ;
b.a2.a1 = ; struct C c;
c.a2.a2.a1 = ; printf("%u\n",sizeof(struct B)); }

例2:结构体变量赋值

#include <stdio.h>
#include <stdlib.h>
#include <windows.h> #pragma warning(disable:4996) static void structUseDemo1(); // 结构体变量赋值
static void structUseDemo1() { struct man m1 = {"圣堂刺客",};
struct man m2 = m1;
printf("m1=%s\n",m1.name);
printf("m2=%s\n", m2.name); struct man *p = &m1;
//(*p).age = 100;
//strcpy((*p).name,"风暴之灵"); p->age = ;
strcpy(p->name,"风暴之灵");
printf("m1.name=%s\n",m1.name);
printf("m1.age=%d\n", m1.age); }

例3:结构体指针

#include <stdio.h>
#include <stdlib.h>
#include <windows.h> #pragma warning(disable:4996) static void structUseDemo2(); static void structUseDemo2() { struct man m[] = {};
struct man *p = &m; // p指向了数组m的首元素地址
p[].age = ;
strcpy(p[].name,"帕克");
p++;
p->age = ;
strcpy(p->name,"莉娜");
p++;
p->age = ;
strcpy(p->name, "露娜");
p = m; // 将指针归位
/*for (int i = 0; i < 10;i++) {
printf("name=%s,age=%d\n",m[i].name,m[i].age);
}*/
for (int i = ; i < ;i++) {
printf("name=%s,age=%d\n",p->name,p->age);
p++;
}
}

1.6 在堆中创建结构体

#include <stdio.h>
#include <stdlib.h>
#include <string.h> #pragma warning(disable:4996) void structUseDemo4(void); void structUseDemo4(void) { struct women *p = calloc(, sizeof(struct women));
p->name = calloc(,sizeof(char));
strcpy(p->name,"漩涡鸣人");
p->age = ; printf("当前p的名称为:%s,年龄为:%d\n",p->name,p->age); free(p->name); // 一定要先翻译p->name,如果先释放p,会导致内存泄露
free(p); }

运行结果:

1.7 结构体作为函数的参数

下面有两个方法用于打印结构体成员变量的值

// 结构体作为函数的参数
void structUseDemo5(struct man m) {
//在栈中会有类似这样的代码m = a; printf("%s,%d\n",m.name,m.age); } // 1.不要把结构体作为函数的参数传递进去,因为这涉及到形参的拷贝,推荐传递结构体的指针
// 2.由于传递的是结构体的地址,const可以保护实参的值不被修改

void structUseDemo6(const struct man *m) { printf("%s,%d\n",m->name,m->age); }

二.联合体

联合union是一个能在同一个存储空间存储不同类型数据的类型。

联合体所占的内存长度等于其最长成员的长度,也有叫做共用体。

联合体虽然可以有多个成员,但同一时间只能存放其中一种。

联合体变量的任何一个成员赋值,都会影响到其它成员。

三.枚举

enum mysex { man = , woman }; // 说明了一个枚举 ,可以为其指定一个默认值,man = 5,woman就是6,依此类推

void enumUseDemo1(void) {

    struct man m;
strcpy(m.name,"佐助");
m.age = ;
m.sex = man; printf("%d\n",man); } // 输出为5.

四.typedef

typedef是一种高级数据特性,可以用于定义一个新的数据类型

typedef unsigned char BYTE

1与#define不同,typedef仅限于数据类型,而不是能是表达式或具体的值。

2typedef是编译器处理的,而不是预编译指令

3typedef比#define更灵活

直接看typedef好像没什么用处,使用BYTE定义一个unsigned char。使用typedef可以增加程序的可移植性。

typedef struct man M; // 说明了一个新的数据类型,名字叫M
typedef unsigned char BYTE; // 说明了Byte这种数据类型
typedef short NUM; void typedefUseDemo(void)
{ M m;
m.age = ;
BYTE a; }

C语言基础(19)-结构体,联合体,枚举和typedef的更多相关文章

  1. Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...

  2. GO学习-(13) Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有"类"的概念,也不支持"类"的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. ...

  3. C语言基础 (11) 结构体 ,共用体 枚举 typedef

    1 课堂回顾 作用域与生命周期 2 static 局部变量 2 打字游戏 3 内存分区代码分析 4 结构体基本操作 (复合类型[自定义类型 #include <stdio.h> #incl ...

  4. Go语言基础之结构体(面向对象编程上)

    1 自定义类型和类型别名 1.1 自定义类型 Go语言中可以基于一些基本的数据类型,使用type关键字定义自定义类型的数据 . 自定义类型定义了一个全新的类型,该新类型具有基本数据类型的特性.自定义类 ...

  5. C语言-1.结构体,2.枚举,3.typedef,4.预处理指令的概念,5.条件编译

    1. 结构体数组 定义:由若干个相同类型的结构体变量组成的有序的集合. 定义格式: 1) 定义结构体的同时定义结构体数组 struct Car{ int lunzi; int speed; }cars ...

  6. go语言基础之结构体做函数参数 值传递和地址传递

    1.结构体做函数参数值传递 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...

  7. go语言基础之结构体比较和赋值

    1.结构体比较和赋值 (同类型的结构体可以相互赋值) 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Stud ...

  8. go语言基础之结构体成员的使用指针变量

    1.结构体成员的使用:指针变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct ...

  9. go语言基础之结构体成员的使用普通变量

    1.结构体成员的使用普通变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...

随机推荐

  1. menuStrip鼠标经过自动显示菜单

    //--------------------------------------------------------------------------------- private void For ...

  2. oracle 11g 大量废连接占满数据库连接问题处理

    问题描述: 数据库不断出现大量无用连接,超过数据库最大连接数,导致新的连接无法建立,访问不通数据库 问题分析: 服务器netstat连接数,大量连接来自办公网连接,不断在增加,通过服务器spid查看数 ...

  3. iOS: 格式化新浪微博/QQ说说等等的发布时间

    介绍:对于一些社交工具,我们可以发布一些说说或者心情什么的,如新浪微博,QQ,微信等,发布成功后,上面都会有一个发布的时间. 这个时间并不是具体的NSDate类型,而是经过格式化过的符合一般标准的模式 ...

  4. C#之鼠标模拟技术

    游戏程序的操作不外乎两种——键盘输入控制和鼠标输入控制,几乎所有游戏中都使用鼠标来改变角色的位置和方向,本文主要是讲述如何使用C#调用Windows API函数实现鼠标模拟操作的功能.首先通过结合Fi ...

  5. uCOS-ii笔记

    ucos ii system 文件结构 上层: 应用软件,用户代码 中层: 与处理器无关代码 与应用程序相关配置文件 与处理器有关代码 下层: 硬件(cpu,interupt,timer,gpio,i ...

  6. Less使用说明

    使用koala编译 Koala 是一款由国人开发的开源预处理语言图形编译工具,目前已支持 Less.Sass.Compass 与CoffeeScript. 目前支持以下系统:Windows,Mac, ...

  7. gflops

    这个网站最棒了 http://kyokojap.myweb.hinet.net/gpu_gflops/

  8. 从C转到JAVA学习路之基本知识对比(转)

    转自:http://blog.csdn.net/andywxf01/article/details/53502615 我一直在用C开发,想转到Java时最容易想到的事就是把C里写的代码和功能用JAVA ...

  9. (转)Netty : writeAndFlush的线程安全及并发问题

    rocketmq用netty实现的网络连接,发现它多个线程掉用一个channel连接,所以这个是线程安全的? 使用Netty编程时,我们经常会从用户线程,而不是Netty线程池发起write操作,因为 ...

  10. 2017.11.15 String、StringBuffer、StringBuilder的比较(todo)

    参考来自:http://blog.csdn.net/jeffleo/article/details/52194433 1.速度 一般来说,三者的速度是:StringBuilder > Strin ...