---------------------- 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 = {“张三”,17,1.72};
struct Student stu2 = {“李四”,19,1.68};
stu1 = stu2 //会将stu2所有成员的值对应的赋值给stu1的所有成员;
stu2.name= ”王五”; //只改stu2的name值,与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//访问stu2的birthday的month;
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)、预处理指令在代码编译成0和1之前执行;
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
4、typedef
为各种数据类型定义一个新名字(别名);
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;
5、static 和 extern
a、static 和 extern对函数的作用
函数分两种:
1)、外部函数:定义的函数允许本文件和其他文件访问、调用;
2)、内部函数:定义的函数不允许其他文件访问、调用,只能在本文件内部使用。
外部函数和内部函数的区别:
外部函数:默认情况下的所有的函数都是外部函数,不允许有同名的外部函数;
内部函数:允许不同文件中有同名的内部函数。
extern对函数的作用:
1)、完整的定义外部函数:extern voidtest(){}; //extern可以省略;
2)、完整的声明外部函数:extern voidtest(); //extern可以省略;
static对函数的作用:
1)、定义内部函数:static void test(){};
2)、声明内部函数:static voidtest();
其他文件想调用test.c里的内部函数,可以在文件中先调用test.c的一个外部函数,用这个外部函数间接调用这个内部函数。
b、static 和 extern对全局变量的作用
全局变量分两种:
1)、外部变量:定义的变量允许本文件和其他文件访问、调用;
2)、内部变量:定义的变量不允许其他文件访问、调用,只能在本文件内部使用。
默认情况下的所有的全局变量都是外部变量;
不同文件中的同名外部变量都代表同一个变量;
定义一个外部变量:int a;
定义一个内部变量:static int a;
static对全局变量的作用:定义内部变量;
extern对全局变量的作用:声明外部变量;
内部变量的作用:不同文件中的同名内部变量互不影响。
c、static对局部变量的作用
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)、必须有个明确的返回值;
设计一个函数,用来计算b的n次方
intpows(int b, int n)
{
if(n < = 0) return 1;
return pows(b, n-1) * b;
int c = pows(3,5);}
int main()
{
printf(“%d\n”,c);
return 0;
}
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------