黑马程序员_第五天视频学习其他数据类型及预处理指令

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

一、 其他数据类型:

1、变量类型:根据变量作用域的不同,将变量分为局部变量和全局变量。

       a、局部变量

              (1)、定义:在函数(代码块)内部定义的变量;形参也属于局部变量。

              (2)、作用域:从变量定义的那一行开始,一直到代码块结束;

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

              (4)、不初始化,内部值未知,没有固定的初始值。

       b、全局变量

              (1)、定义:在函数外部定义的变量;

              (2)、作用域:从变量定义的那一行开始,直到源程序结束(能被后面的所有函数共享)

              (3)、生命周期:程序一启动就会分配存储空间,程序退出时才会被销毁;

              (4)、不初始化,默认为0

2、结构体

       属于构造类型

       概念:可以由多个不同类型的数据构成;

       和数组区别:数组只能由多个相同类型的数据构成;

a、  定义:

结构体类型结构体变量名;

1)       定义结构体类型

2)       根据结构体类型,定义结构体变量

#include <stdio.h>

int main()

{

//定义结构体类型Student

       struct Student      //内部的变量,可以称为是结构体的成员或属性

{

       char *name;   //8个字节

       int age;   //4个字节

       double height;      //8个字节

};

//根据结构体类型Student,定义结构体变量stu

struct Student stu = { “张三”, 17, 1.72};

struct Student stu2;

stu2.name = ”李四”;

stu2.age = 19;

printf(“name=%s, age =%d, height=%.2f”, stu.name, stu.age, stu.height);

return 0;

}

错误写法:

        struct Student stu3;

       stu3={“王五”,18,1.66}; //只有定义的时候才能进行初始化;

b、 结构体的内存分析

定义结构体类型的时候,并不会分配存储空间;

定义结构体变量的时候,才真正的分配内存空间,且每个结构体变量分配的是单独的空间, 各成员在内存中按定义的顺序依次排列;

struct Student stu1 = {“张三171.72};

struct Student stu2 = {“李四191.68};

stu1 = stu2 //会将stu2所有成员的值对应的赋值给stu1的所有成员;

stu2.name= ”王五”; //只改stu2name值,与stu1无关;

补齐(对齐)算法,结构体所占用的存储空间必须是最大成员的倍数。

       上面的结构体占用的空间是8+4+8=20,因为最大成员的字节数是8,所以占用的空间应该是24个字节。

c、  结构体的注意点

1)、结构体定义变量的方式:

        a)、先定义类型,再定义变量(分开定义)

struct Student

{

        char *name;  

       int age;  

};

struct Student stu ={“张三”,17,1.72};

        b)、定义类型的同时定义变量;

struct Student

{

       char *name;  

      int age;  

} stu;

//这句代码做了两件事:定义结构体类型;利用新定义好的类型定义结构体变量。

同时可以定义新的变量: struct Student stu1;

       c)、定义类型的同时定义变量,省略类型名称;

struct

{

       char *name;  

int age;  

} stu;//这种定义无法重复使用

              2)、结构体注意点:

                     a)、结构体类型不能重复定义;

struct Student

{

char *name;  

int age;  

} stu;

struct Student

{

char *name;  

int age;  

} stu2;

//这种写法是错误的,结构类型Student重复定义了;

                     b)、结构体类型可以嵌套其他的结构体类型,但不可以嵌套自己;

                            struct Date

{

int year;

int month;

int day;

};

struct Student

{

       char *name;  

       int age;  

       struct Date birthday;//这是可以的

       struct Student stu;//这是错误的

} stu2;

stu2.birthday.month//访问stu2birthdaymonth;

       d、结构体类型的作用域

              从定义类型的那一行开始,一直到代码块结束。

              结构体类型可以定义成全局变量,定义好全局变量,可以从这一行开始,一直到文件结尾都是有效的;在函数体内部再次定义该结构体也是可以的,不过这个函数用的不是全局变量的结构体,而是自己定义的结构体。

              1)、定义在函数外面:全局有效;

              2)、定义在函数(代码块)内部:局部有效。

       e、结构体数组

              structStudent {

                 char *name;

                 int age;

};

struct Student stu[2] =

{

{“张三”,17};

{“李四”,19};

};

for(int i=0; i<2; i++)

{

       printf(“%s\t%d\n”,stu[i].name,stu[i].age);

}

       f、指向结构体的指针

1)、定义:struct 结构体类型 *p = &结构体变量名;

structStudent {

char *name;

int age;

  } stu = {“张三17};

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

  *p = &stu; //指针变量指向stu变量

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

printf(“name = %s,age=%d\n”, stu.name, stu.age);

       a)(*p).成员名称

printf(“name = %s,age=%d\n”,(*p).name, (*p).age);

       b)p -> 成员名称

printf(“name = %s,age=%d\n”, p->name, p->age);

3、枚举

       a、定义枚举类型

              enumSeason {

spring,   //0

summer,  //1

autumn,  //2

winter    //3

};

       b、定义枚举变量

              enumSeason s = autumn;

printf(“%d”,s); //输出是2

       使用场合:变量只有固定常量是,可以使用。

二、预处理指令

       代码被编译之前运行的指令

分为宏定义、条件编译、文件包含

       特点:

              1)、所有的预处理指令都是以”#”开头;

              2)、预处理指令在代码编译成01之前执行;

              3)、预处理的位置是随便写的;

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

1、宏定义

       a、不带参数的宏定义

              #define宏名字符串

              使用注意:

                     (1)、宏名一般用大写字母或以K开头,以便与变量名区别开来,但小写也无语法错误;

                     (2)、对程序中用双引号括起来的字符串内的字符,不进行宏的替换操作;

              作用:在编译预处理时,将源程序中的所有宏名替换成有病的字符串(常用定义常量);

              终止宏定义的作用域用:#undef 宏名;

       b、带参数的宏定义

              #define宏名(参数列表) 字符串

              #definesum(v1,v2) ( (v1) * (v2) )   //每个参数都要用()括起来,结果值也要有();

              作用:在编译预处理时,将源程序中所有宏名替换成字符串,并且将字符串中的参数用宏名右边参数列表中的参数替换;

              与函数的区别:

                     1)、带参数的哄定义效率比函数高;

                     2)、宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题;

2、条件编译

       a、概念:程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才能被执行)

       b、定义:

              #if条件1

执行程序1

#elif条件2

执行程序2

#else

执行程序3

#endif

#if#elif后面的条件一般判断宏定义,不是变量,因为条件编译是在编译之前进行的,而变量是在运行时才产生的、才有使用的意义。

只要写了#if在最后面必须加上#endif(条件判断从这个位置结束)

条件编译与if的区别:

条件编译编译的时候只编译成立的条件语句;if是所有语句都进行编译。

              #ifdefined (宏名) == #ifdef 宏名     判断定义宏

              #if!defined (宏名) == #ifndef 宏名  判断未定义宏

3、文件包含

       #include<>  #include “”

       使用注意

1)       <>表示系统自带的文件,””表示自定义的文件;

2)       不允许循环包含;比如a.h包含b.h,b.h又包含a.h这是错误的

3)       #include指令可能导致多次包含同一头文件,降低编译效率;

可在头文件中加入#ifndef;

如:

      #ifndef HONGMING

             #define HONGMING 1 //可不写1

             int sum(int a, int b)

{

       return a + b;

};

      #endif

       4typedef

              为各种数据类型定义一个新名字(别名)

              typedefint MyInt;

typedef MyInt MyInt2;

int main()

{

//下面的三个是相同的;

       int a=20;

MyInt b=20;

MyInt2 c=20;

//给指针类型char *起一个新类型名称 string;

typedef char * string;

string name = ”张三”;//相当于 char *name=”张三”;

return 0;

}

//结构体起别名

1)

struct Student

{

              int age;

}

typedef struct Student Mystu;

int main()

{

       Mystu stu;

       Struct Student stu1;

return 0;

}

                     2)

                            typedefstruct Student

{

       int age;

} Mystu;

int main()

{

       Mystu stu;

       Struct Student stu1;

return 0;

}

        3) 、相较于 2) ,无法这么写: Struct Studentstu1;

                            typedefstruct

{

       int age;

} Mystu;

int main()

{

       Mystu stu;

return 0;

}

              //枚举起别名:

                     1)enum Sex {Man,Women};

                            typedefenum Sex MySex;

                            MySexs = Man;

                     2)typedef enum Sex{Man,Women} MySex;  //Sex可忽略;

              //指向函数的指针改名:

                           typedefint (*MyPoint) { int, int};

int sum(int a, int b)

{

       return a + b;

}

int minus(int a, int b)

{

       return a - b;

}

                     intmain()

{

       MyPoint p = sum;

       MyPoint p2 = minus;

       (*p)(4, 5);

       (*p2)(8, 5);

       return 0;

}

              //指向结构体的指针改名

1)

struct Person

{

              int age;

}

typedef struct Person * PersonPoint;

       int main()

       {

              struct Person p = {20};

              PersonPoint p2 = &p;//相当于struct Person*p2=&p;

}

2)typedef struct Person

{

intage;

} * PersonPoint;

int main()

{

struct Person p = {20};

PersonPoint p2 =&p;//相当于struct Person *p2=&p;

}

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

              注意点:

                     typedef#define在某些场合可以互换,但有些场合不能互换;

                            typedefchar * string;

                            strings1,s2; //相当于 char *s1,*s2;

                            #definestring char *

                            strings3,s4; //相当于 char *s3,s4;

       5static extern

              astatic extern对函数的作用

函数分两种:

                     1)、外部函数:定义的函数允许本文件和其他文件访问、调用;

                     2)、内部函数:定义的函数不允许其他文件访问、调用,只能在本文件内部使用。

                     外部函数和内部函数的区别:

                            外部函数:默认情况下的所有的函数都是外部函数,不允许有同名的外部函数;

                            内部函数:允许不同文件中有同名的内部函数。

                     extern对函数的作用:

                            1)、完整的定义外部函数:extern voidtest(){}; //extern可以省略;

                            2)、完整的声明外部函数:extern voidtest(); //extern可以省略;

                     static对函数的作用:

                            1)、定义内部函数:static void test(){};

                            2)、声明内部函数:static voidtest();

                     其他文件想调用test.c里的内部函数,可以在文件中先调用test.c的一个外部函数,用这个外部函数间接调用这个内部函数。

              bstatic extern对全局变量的作用

                     全局变量分两种:

                     1)、外部变量:定义的变量允许本文件和其他文件访问、调用;

                     2)、内部变量:定义的变量不允许其他文件访问、调用,只能在本文件内部使用。

                     默认情况下的所有的全局变量都是外部变量;

                     不同文件中的同名外部变量都代表同一个变量;

                     定义一个外部变量:int a;

                     定义一个内部变量:static int a;

                     static对全局变量的作用:定义内部变量;

extern对全局变量的作用:声明外部变量;

内部变量的作用:不同文件中的同名内部变量互不影响。

              cstatic对局部变量的作用

                     static修饰局部变量: static int b;

1)       延长局部变量的生命周期,程序结束的时候,局部变量才会被销毁;

2)       并没有改变局部变量的作用域;

3)       所有的test函数都共享这一个变量b

#include <stdio.h>

void test()

{

      int a = 1;

      static int b = 1;

      printf(“a = %d\n”,a++);

      printf(“b = %d\n”,b++);

}

int main()

{

      test();

test();

return 0;

}

输出结果是 a=1 b=1 a=1 b=2;

                     使用场合:

                            1)、如果某一个函数的调频率特别高;

                            2)、这个函数内部的某个变量值是固定不变的;

       6、递归

              递归的两个条件:

                     1)、函数自己调用自己;

                     2)、必须有个明确的返回值;

              设计一个函数,用来计算bn次方

                     intpows(int b, int n)

                     {

if(n < = 0) return 1;

return pows(b, n-1) * b;

}

int main()

{

int c = pows(3,5);
printf(“%d\n”,c);
return 0;

}

 

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值