黑马程序员— C语言基础之结构体、枚举、预处理、typedef的使用

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

本章我们主要来学习之前所学的复杂数据类型中的同样也很重要的结构体和枚举的知识,以及C语言中的预处理,typedef的使用,简单介绍一下static和extern等一些比较杂的知识。在开始本章的新知识学习之前首先我们来学习一下根据变量的作用域的不同C语言一般把变量分为两种,局部变量和全局变量。下面我们来分别比较和体会一下这两种不同的变量类型:

根据变量的作用域,可以分为:

1. 局部变量:

a. 定义:在函数(代码块)内部定义的变量(包括函数的形参)

b. 作用域:从定义变量的那一行开始,一直到代码块结束

c. 生命周期:从定义变量的那一行开始分配存储空间,代码块结束后,就会被回收

d.局部变量没有固定的初始值

2. 全局变量

a. 定义:在函数外面定义的变量

b. 作用域:从定义变量的那一行开始,一直到文件结尾(能被后面的所有函数共享)

c. 生命周期:程序一启动就会分配存储空间,程序退出时才会被销毁

d. 全局变量默认的初始值就是0

第一讲     结构体

在上一章我们学习过数组,数组是用来存储数据的,但是数组只能存放一种类型的数据,在实际的应用中往往需要存储一组不同数据类型的数据,这让数组在使用中有一定的局限性,结构体可以解决这类的问题。在定义结构体时,结构体可以由多种不同类型的数据组成。

1. 结构体的定义

定义结构体变量的三种方式:

(1)先定义类型,在定义变量(分开定义)

strcut Student

{

      int age;

};

struct Student stu;

(2) 定义类型的同时定义变量

strcut Student

{

     int age;

}stu;

struct Student stu2;

(3)定义类型的同时定义变量(省略了类型名称)

strcut

{

     int age;

}stu;

下面通过代码来引出结构体,同时要注意结构体定义时的一些规范问题:

#include<stdio.h>
int main()
{
    // 1.定义结构体的类型
    struct Person
    {  // 里面的三个变量可以称为是结构体的成员或者属性
        int age; // 年龄
        double height; // 身高
        char *name; // 姓名
    };
    // 2.根据结构体的类型,定义结构体变量,并在定义时可以进行赋值
    struct Person p = {20 , 1.55, "jack"};
    p.age = 30;
    p.name = "rose";  // 在调用结构体体属性时用"变量名.属性"调用

    /*下面为错误写法,如果要定义直接写struct Person p2 = {30, 1.23, "rose"};
     struct Person p2;
     p2 = {30, 1.23, "rose"}; 这么定义是不对的
     */
    // 在赋值时可以不按定义属性的顺序赋值,调用属性赋值
    struct Person p2 ={.height=1.78,.age = 20, .name="tom"};
    printf("age=%d,height=%f,name=%s\n", p.age,p.height,p.name);

    return 0;
}

2. 结构体的内存分析

(1)结构体的作用域

定义在函数(代码块)外面:从这行开始,一直到文件结尾,都是有效(跟全局变量一样)

在外面定义了结构体类型后,函数内部也可以再次重新定义相同的结构体类型,只是作用域只作用域函数的代码块

定义在函数(代码块)内部:结构体类型也是有作用域的,从定义类型的那一行开始,一直到代码块结束

如果想定义整个程序都可以使用的结构体类型,需要在整个程序外定义,不可在函数内部定义

(2)结构体内存分配

结构体在定义类型时不会分配存储空间,在定义结构体变量时才会真正分配存储空间

struct Date

{

int year;

int month;

int day;

};   //  这是定义结构体类型,并不会分配存储空间

struct Date d1={2011,9,10};

struct Date d2={2015,12,3};  // 定义结构体变量(定义了变量,真正分配存储空间)

d2 = d1;  // 会将d1所有成员的值对应的赋值给d2的所有成员

(3)结构体所占存储空间

结构体所占存储空间是其内部定义的数据类型所占之和

补齐算法(对齐算法):分配结构体内存时,结构体所占用的存储空间,必须是最大成员字节数的倍数

3. 结构体数组

结构体数组是有顺序,多类型的

int main()
{
    struct RankRecord  // 定义结构体
    {
        int no;  // 序号
        char *name;  // 名称
        int score;  // 积分
    };
   /* struct RankRecord r1={1,"jack",5000};
    struct RankRecord r2={2,"jim",500};
    struct RankRecord r3={3,"rose",300};*/
    //结构体数组:有顺序,多类型

    // 定义结构体数组
    struct RankRecord records[3]=
    {
        {1,"jack",5000},
        {2,"jim",500},
        {3,"rose",300}
    };
    // 改结构体的值
    records[0].no=4;
    //records[0] = {2,"tom",200};这么写是不对的,只能在定义结构体类型的时候可以这么写
    return 0;
}

4. 指向结构体的指针

(1)指向结构体的指针的定义

struct Student *p; 这么定义了之后表示指针变量p将来指向struct Student类型的数据

(2)利用指针访问结构体的成员

(*p).成员名称

p->成员名称

     结构体变量名.成员名称

struct Student  // 定义一个结构体
    {
        int no;   // 学号
        int age; // 年龄
    };
    //结构体变量
    struct Student stu = {1,20};

    //指针变量p将来指向struct Student类型的数据
    struct Student *p;

    //指针变量p指向了stu变量
    p=&stu;
    p->age=30; // 利用指针访问结构体成员并改值 

5. 结构体和函数

结构体作为函数参数,只是将实参结构体所有成员的值一一赋值给了形参结构体所有成员,修改函数内部结构体成员不会影响外面实参结构体成员。而如果指向结构体的指针作为函数参数,则会影响外面实参结构体的成员。

第二讲     枚举、预处理

1. 枚举

枚举是C语言中的一种基本数据类型,并不是构造类型,它可以用于声明一组常数,枚举的一般使用场合是:当一个变量只允许有固定几个取值时用枚举

(1)定义枚举类型

enum Season

{

spring,      // 0

summer,   // 1

autumn,   // 2

winter      // 3

};

(2)定义枚举变量

enum Season s = summer;

枚举元素的值取决于定义时各枚举元素排列的先后顺序。默认情况下,第一个枚举元素的值为0,第二个为1,依次顺序加1。

2. 预处理(所有的预处理指令都是#开头)

C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译。

(1)宏定义

#define宏名 字符串 宏定义开始

#undef 宏名 字符串 宏定义失效

简单地带参数的宏定义比函数效率高

定义宏定义时,参数和结果值都用加上小括号

(2)条件编译

#ifdef

#elif

#endif//只要写了#if,在后面必须加上#endif

(3)文件包含

#include

<>表示系统自带的文件,""表示自定义的文件

不允许循环包含,比如a.h包含b.h,b.h又包含a.h

(4)预处理几项注意总结

所有的预处理指令都是以#开头

预处理指令一共三种:宏定义,条件编译,文件包含

预处理指令在代码翻译成0跟1之前执行

预处理的位置是随便写的

预处理指令的作用域:从编写指令的那一行开始,一直到文件的结尾

宏名一般用大写或者以k开头,变量名一般用小写

3. typedef关键字

使用typedef为已经存在的各种数据类型定义一个新的类型名。

typedef  类型名  新的类型名

使用场合:基本数据类型、指针、结构体、枚举、指向函数的指针、指向结构体的指针

下面通过代码来体会一下typedef的使用:

struct Student   // 定义一个结构体
{
    int age;
};

typedef struct Student MyStu; // 这是第一种做法

typedef struct Student
{
    int age;
} Mystu;   //  这是第二种做法

typedef struct
{
    int age;
} Mystu;   //  这是第三种做法

typedef的使用可以让一些复杂的类型定义为自己设定的简易的新类型,特别在枚举类型,指向函数的指针,指向结构体的指针等较为复杂的类型

// 指向结构体的指针
struct Person
{
    int age;
};

typedef struct Person * PersonPoint;  // 利用typedef定义新的类型
int main()
{
    struct Person p = {20};
    struct Person *p2 = &p;

    PersonPoint p2 = &p;  // 这一句跟上一句是相同的效果
    return 0;
}

4. static和extern

static:声明、定义内部函数(允许不同文件中有同名的内部函数);定义一个内部变量

extern:完整地声明、定义外部函数(不允许有同名的外部函数),默认情况下,声明和定义的函数都是外部函数,可省略extern;声明一个外部变量

总结:本章学习的知识可能有点零散,但在C语言的学习中也都是需要注意和掌握的。其中本章的第一讲主要讲述了结构体的相关知识,结构体在C语言的学习包括今后的OC学习中都会经常用到,因此也是非常重要的一部分,第一讲主要学习了结构体的定义,其中定义结构体变量有三种不同的方式,还学习了结构体的内存分析,包括结构体的作用域,内存分配和所占存储空间,结构体跟之前所学复杂数据类型数组,指针等有密切的联系和应用,结构体也重点讲述了结构体和数组,指向结构体的指针,同时了解了结构体和函数的关系,当结构体作为函数参数的一些注意点。第二讲主要学习了我们枚举数据类型,C语言的预处理和C语言中比较好用的typedef关键字,同时了解了一下static和extern。枚举enum和typedef在使用上有一定类似的地方,可以比较着学习,一个是基本数据类型,用来定义只允许有几个固定取值的变量,另一个是将一些已经存在的数据类型定义新的类型名。而C语言的预处理是在C语言代码翻译成0跟1之前执行的,主要包括宏定义,条件翻译和文件包含,注意预处理都是以#开头的,需要了解预处理的执行过程以及其作用域。

时间: 2024-10-11 05:37:47

黑马程序员— C语言基础之结构体、枚举、预处理、typedef的使用的相关文章

黑马程序员——c语言基础:结构体和枚举---typedef的使用

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.什么是结构体 当一个整体由多个数据构成时,我们可以用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据. 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名.年龄.身高等数据构成,这些数 据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型. 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它

黑马程序员--C语言中的结构体

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 结构(struct)      结构是由基本数据类型构成的.并用一个标识符来命名的各种变量的组合.  结构中可以使用不同的数据类型.      1. 结构说明和结构变量定义      在Turbo C中, 结构也是一种数据类型, 可以使用结构变量, 因此,  象其它  类型的变量一样, 在使用结构变量时要先对其定义.      定义结构变量的一般格式为:       struct 结构名   

黑马程序员-c语言基础:各种数据类型的输出占位符

c语言中的输出操作相对java来说是比较麻烦的,每种数据类型的输出都有各自的占位符: 下面是各种数据类型的输出占位符: short/int : %d int a = 1; printf("这个整数是:%d", a); long: %ld; (long 是int得修饰,不能算是一种单独的数据类型,只是比int多了四个字节的存储空间) long long: %lld char : %c float/double : %f  float默认是6位小数输出:可以在%f中控制:例如:%.2f:输

黑马程序员-C语言基础:指针类型与指针和数组、字符串的关系

//指针变量就是用来存储地址的,只能存储地址 格式:  int  *p;  这个p为指针变量:指针变量占8个字节 类型是用来说明这个指针指向的类型: 比如上边的int代表这个指针变量会指向int类型的存储空间: int *p = &a;//这样一句可以写,此时的*只是一个标志,表示这个*只是表示p是个指针: *p = &a;//这样写就错了:此时*p表示取p指向的空间的值: 指针疑问:指针既然都占据8个字节,那么为什么要划分类型, 是因为当用*p指针取值或者赋值的时候,知道该取几个字节,比

黑马程序员-C语言基础:数组和字符串

数组:数组的定义注意点 数组初始化正确写法: int args[5] = {1,23,32,4,5}; int args[5] = {12,23}; int args[5] = {[3]=23, [4]=13};//这种写法也可以,直接给其中角标为3和4的赋值 int args[] = {12,23,32};//中括号中没写数组大小,在大括号中一定要写具体数值 int args['A'] = {2,34,5}; 错误写法: int args[];//这样编译器不知道给你开辟多大的内存空间 int

黑马程序员_01_Java语言基础部分(数据类型与表达式、流程控制语句、数组与方法)

------- android培训.java培训.期待与您交流! ---------- Java语言主要由5中符号组成 标识符:数字.字母.美元符.下划线(注意不能数字开头) 关键字:goto和const保留了它们,但是Java没有使用. 运算符:注意运算符优先级(左结合和右结合要注意) 分隔符:注意+号可以分割字符串. 注释:三种注释. 数据类型与变量 常量: 整型 浮点型 字符:注意后面跟三个八进制(\ddd)和 四位unicode码(\u8bf7) (不区分大小写) 字符串 布尔型 变量:

黑马程序员---C语言基础---结构体

------iOS培训.Java培训.Android培训, iOS学习型技术博客,期待与您交流------ C语言基础---结构体 一.什么是结构体 介绍结构体之前,我想先简单介绍下数组.我想大家对数组都再熟悉不过了,顾名思义,数组就是将一些数据(元素)组合在一起,作为一个整体.使用数组需要注意的是这些元素必须是相同类型.而结构体和数组类似,也是将一些数据组合在一起作为一个整体,但是这些元素可以是不同类型.可以这么理解:结构体是更加灵活的数组,因为它允许元素是不同的类型. 实际生活中,如果我们要

黑马程序员--C语言基础之--变量、内部函数与外部函数

------- IOS培训期待与您交流! ---------- 一.变量 变量代表着一个有名字的.具有特定属性的一个存储单元,运行期间,变量的值是可以改变的.变量必须先定义,后使用.定义时,指定该变量的名字与类型.变量名实际上是以一个名字代表的一个存储地址:而从变量中取值,实际上是通过变量名找到相对应的内存地址,再从该存储单元中读取相对应的数据. 刚刚提到了变量定义这个词,我们知道,在定义函数的时候,我们都会先对函数进行一个声明,这就又引用了一个概念:声明.那么我们先来理解一下什么是声明和定义:

黑马程序员——C语言——基础语法

首先学的是C语言的基础语法,主要分为关键字.标示符.注释.数据.常量.变量. 一.关键字 1   关键字是指在C语言中系统默认的有特殊意义的字符 2   关键字全部是小写字母表示,总共32个关键字(主函数[main]中int .return),如下: auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned