1.全局變量和局部變量
局部變量:
概念:定義函數内部變量
定義格式:變量類型 變量名稱;
作用域:從定義那一行開始到所在代碼塊結束
生命周期:從代碼執行到定義的哪一行開始,到其所在的代碼的結束為止
特點:相同的代碼塊中不可以有同名的變量
不同的代碼塊中可以有同名的變量,内部的變量會覆寫外部定義的變量
全局變量:
概念:定義在函數外部變量
定義:變量類型 變量名稱 = 值;
聲明:變量類型 變量名稱;
特點:1、不可以重複定義,但可以重複聲明
2、局部變量可以與全局變量同名,在局部變量的作用域範圍内,那麼局部變量會覆寫全局變量
3、如果沒有定義僅有聲明,系統自動給它定義并将其初始化為0
作用域:從定義的那一行開始,直到檔案結束
生命周期:從程式啟動開始,直到程式退出才消亡
#include <stdio.h>
int num;//聲明
int main(int argc, const char * argv[]) {
printf("num = %d\n",num);
int num = 20;
printf("num = %d\n",num);
{
num = 40;
int num = 10;
printf("num = %d\n",num);
num = 30;
}
printf("num = %d\n",num);
return 0;
}
2.結構體
構造類型:由已有的資料類型構成類型
1、數組:多個同種類型的資料構成的那麼一種類型
特點:隻能存放一種數類型
2、結構體:從來存放表示某種特定含義的一組資料
它是對資料封裝
函數對功能封裝
好處:提高代碼的可讀性
提高資料易用性
提高代碼可維護性
定義結構體:
1、定義結構類型
struct 結構類型名稱{
成員類型 成員名稱;
...
};//必須加分号
2、通過結構體類型定義結構變量
struct 結構類型名稱 結構體變量名稱;
#include <stdio.h>
int main(int argc, const char * argv[]) {
// int scores[] = {59,60};
// int 年齡 姓名 char * 性别 char 身高 double 體重 double
// int age;
// char sex;
// double height;
// double weight;
// char *name;
//
// int ages[50];
// char sex[50];
// ....
// 定義一個人結構體類型
struct Person{
int age;
char sex;
double height;
double weight;
char *name;
};
// int num;
// int * pointer;
// 定義結構體變量
struct Person person;
// 通路結構體成員
person.age = 10;
person.sex = 'M';
person.weight = 20.2;
person.height = 1.2;
person.name = "小明";
printf("age = %d,sex = %c,weight = %.2lf,height = %.2lf,name = %s\n",person.age,person.sex,person.weight,person.height,person.name);
return 0;
}
3.定義結構體的多種類型
#include <stdio.h>
/*
第一種方式
1、先定義結構體類型
2、定義結構變量
*/
void test()
{
struct Person{
int age;
double height;
};
struct Person p1;
}
/*
第二種方式
定義結構體類型的同時定義結構變量
*/
void test1()
{
struct Person{
int age;
double height;
} p1,p2 = {20,1.75};
p1 =(struct Person){10,1.2};
printf("age = %d,height = %.2lf\n",p1.age,p1.height);
printf("age = %d,height = %.2lf\n",p2.age,p2.height);
// 結構體類型定義是不可以重名的
// struct Person{
// int age;
// double height;
// } p3,p4 = {20,1.75};
}
/*
第三種方式
定義匿名的結構類型的同時定義結構體變量
*/
int main(int argc, const char * argv[]) {
struct{
int age;
char sex;
} p1,p2 = {20,'M'};
p1.age = 10;
p1.sex = 'W';
printf("age = %d,sex = %c\n",p1.age,p1.sex);
p1 = p2;
printf("age = %d,sex = %c\n",p1.age,p1.sex);
//
// p1 = (struct) {10,'w'};
// 1、不支援整體指派
// 2、結構體類型不能重複使用
struct{
int age;
char sex;
} p3,p4 = {20,'M'};
return 0;
}
4.結構體作用域
在函數内部,結構類型作用域就如同局部變量一樣
在外邊定義的結構體類型像全局變量的作用域
作用域:從定義的那一行開始直到檔案的結束
注意點:結構類型不能聲明
結構體類型的作用,除了不能聲明以外,其他與普通變量一樣
#include <stdio.h>
struct Person{
int age;
char sex;
};
int main(int argc, const char * argv[]) {
struct Person p2;
p2.sex = 's';
p2.age = 10;
struct Person{
int age;
};
struct Person p = {10};
printf("age = %d\n",p.age);
{
struct Person p = {20};
struct Monkey{
char *name;
};
}
return 0;
}
5.結構體數組
結構體數組:數組元素為結構體數組
定義結構體數組
結構類型 數組名稱[元素個數];
數組元素的類型 數組名稱[元素個數];
#include <stdio.h>
//一般情況下結構體類型都是定義在函數的外部
struct Dog{
char *name;
int age;
};
void test()
{
// int nums[] = {1,2,3,4};
// 結構體如果沒有初始化,它裡面都是垃圾值
// 第一種方式:向定義結構體數組然後初始化
struct Dog dogs[5];
dogs[0] = (struct Dog){"旺财",1};
dogs[1].age = 1;
dogs[1].name = "大黃";
// 周遊結構體數組
for(int i = 0;i < 5;i++)
{
printf("age = %d,name = %s\n",dogs[i].age,dogs[i].name);
}
}
void test2()
{
// 定義結構體數組的同時進行初始化
// 如果沒有顯式初始化的結構體,那麼這個結構體中所有成員都會被初始化為0
struct Dog dogs[10] = {{"旺财",1},{"大黃",2},{"來福",3},{"小黑",4},{"小白",5}};
// 計算數組的元素個數
int len = sizeof(dogs) / sizeof(struct Dog);
for(int i = 0;i < len ;i++)
{
printf("age = %d,name = %s\n",dogs[i].age,dogs[i].name);
}
}
int main(int argc, const char * argv[]) {
// test();
tset2();
return 0;
}
6.結構體與指針
結構體指針:指向結構體的指針
指針所指向的資料類型 * 指針變量名稱;
結構類型 * 指針變量名稱;
#include <stdio.h>
struct Student{
char *name;//姓名
int no;//學号
double score;//成績
};
int main(int argc, const char * argv[]) {
struct Student stu = {"大木",60,59};
// 定義結構體指針
struct Student *sp1;
sp1 = &stu;
// 定義的同時進行初始化
struct Student *sp = &stu;
// 通過指針通路結構體的成員的第一種方式
(*sp).score = 60;
// 第二種方式(重點)
sp->name = "小木";
sp->no = 59;
printf("name = %s,no = %d,score = %.2lf\n",stu.name,stu.no,stu.score);
return 0;
}
7.結構體嵌套
一個結構體内部可以有其他類型的結構體成員
結構體嵌套的注意點:
1、結構體不可以嵌套自己,不能有位元組這種類型的成員
2、結構體可以嵌套自己類型的指針
#include <stdio.h>
//定義了一個日期的結構體
struct Time{
int hour; // HH
int minute;//mm
int second;//ss
};
struct Date{
int year;
int month;
int day;
struct Time time;
};
struct Employee{
int no;
char name[20];
// 入職日期
// int year;
// int month;
// int day;
struct Date inDate;
// 生日
// int birthyear;
// int birthmonth;
// int birthday;
struct Date birthday;
// 離職日期
// int goyear;
// int gomonth;
// int goday;
struct Date outDate;
};
void test()
{
struct Employee emp = {1,"大幕",{2014,10,14,{12,12,12}},{1990,10,14},{2014,11,14}};
printf("no = %d,name = %s,入職日期 = %d-%d-%d %d:%d:%d\n"
,emp.no,emp.name,emp.inDate.year,emp.inDate.month,emp.inDate.day,
emp.inDate.time.hour,emp.inDate.time.minute,emp.inDate.time.second);
}
struct Person{
char *name;
// struct Person son;
struct Person *son;
};
/*
1.某班有5個學生,三門課。分别編寫3個函數實作以下要求:
(1) 求各門課的平均分;
(2) 找出有兩門以上不及格的學生,并輸出其學号和不及格課程的成績;
(3) 找出三門課平均成績在85-90分的學生,并輸出其學号和姓名
*/
int main(int argc, const char * argv[]) {
struct Person father = {"father"};
struct Person son = {"son"};
father.son = &son;
printf("son name = %s\n",father.son->name);
return 0;
}
8.枚舉
枚舉:一個一個列舉出來
枚舉作用:消除魔法數字
使用場景:當某個東西隻有那麼幾個取值時候就是用枚舉
定義枚舉格式
enum 枚舉類型的名稱{
元素,//逗号
...
};
注意點:
1、枚舉類型定義中,所有元素都是整形常量
2、枚舉類型的本質就是整形
#include <stdio.h>
//定義性别枚舉類型
enum Sex{
Man,
Woman,
Other
};
//int Man = 10;//枚舉定義之後,後面不可定義與成員相同變量
void test()
{
// 在代碼中出現的這種表示特殊含義數字,我們魔法數字
// int sex = 0;
enum Sex sex;
printf("%d\n",Man);
int Man = 10;
printf("%d\n",Man);
// sex = 1;// 這裡不能把要給數字指派給一個枚舉類型的變量,這樣枚舉存在的意義就沒有了
// Man = 1;
}
// 可以指定枚舉中每一個元素值
enum Season{
Spring = 2,
Summer,
Autumn,
Winter,
SOther = 9
};
void PrintSeason(enum Season season)
{
switch (season) {
case Spring: //Case後面的值務必與枚舉中成員一緻,不要出現魔法數字
printf("春季\n");
break;
case Summer:
printf("夏季\n");
break;
case Autumn:
printf("秋季\n");
break;
case Winter:
printf("冬季\n");
break;
case SOther:
printf("不是地球上季節\n");
break;
default:
break;
}
}
int main(int argc, const char * argv[]) {
printf("%d,%d,%d\n",Man,Woman,Other);
printf("%d,%d,%d,%d\n",Spring,Summer,Autumn,Winter);
enum Season season = Summer;
PrintSeason(season);
return 0;
}
9. typedef:
給已有資料類型起别名
基本資料類型
int char float double
結構體
枚舉
指針
1、普通變量的指針
2、結構體指針
3、函數指針
基本資料類型
定義格式:typedef 已有資料類型 别名;
#include <stdio.h>
void testBaseType()
{
typedef int Int;
Int num = 10;
typedef Int Integer;
Integer a = 20;
printf("%d\n",a);
}
/*
給結構體類型起别名
*/
void testStruct()
{
// 第一種方式:先定義結構體類型再給結構體類型起别名
struct _Person{
int age;
char *name;
};
typedef struct _Person Person;
Person p1 = {10,"小紅"};
printf("age = %d,name = %s\n",p1.age,p1.name);
// 第二種方式,定義結構體類型的同時給結構體類型起别名
typedef struct _Dog{
int age;
char *name;
} Dog;
Dog dog = {1,"大黃"};
// 第三種方式:定義匿名結構體類型的同時給結構體起一個别名
typedef struct{
int age;
char * name;
} Cat;
Cat cat = {1,"tom"};
}
//給枚舉起别名
void testEnum()
{
// 1、先定義枚舉類型然後給枚舉起别名
enum _Sex{
Man,
Woman,
Other
};
typedef enum _Sex Sex;
Sex sex = Man;
// 2、定義枚舉類型的同時給枚舉類型起一個别名
typedef enum _Season{
Spring,
Summer
} Season;
Season season = Spring;
// 3、定義匿名枚舉類型同時給枚舉起一個别名
typedef enum {
Cong,
Suan,
Jiang
} TiaoWei;
TiaoWei zuoLiao = Cong;
}
//4、指針類型
//4.1 基本資料類型的指針
void testTypedefBasicPointer()
{
typedef int * IntPointerType;
int a = 10;
IntPointerType p = &a;
*p = 20;
printf("%d\n",a);
}
//4.2 給結構體類型的指針起别名
void testTypedefStructPointer()
{
typedef struct {
char *name;
int age;
} Person;
typedef Person * PersonPointerType;
Person p = {"張三",10};
PersonPointerType pp = &p;
typedef struct _Cat{
char *name;
int age;
} Cat, * CatPointerType;
Cat cat = {"小貓",1};
CatPointerType catPointer = &cat;
printf("name = %s,age = %d\n",catPointer->name,catPointer->age);
}
//4.3 給枚舉類型的指針起别名
void testTypedefEnumPointer()
{
// 先定義枚舉類型
enum _Sex{
Man,
Woman,
Other
};
typedef enum _Sex * SexPointer;
enum _Sex sex = Man;
SexPointer sexPointer = &sex;
*sexPointer = Woman;
printf("%d\n",sex);
}
//4.4 給函數指針起别名
int sum(int num1,int num2){
return num1 + num2;
}
int minus(int num1,int num2){
return num1 + num2;
}
//給函數指針起别名
//typedef 指針所指向的函數的傳回值類型 (*函數指針類型别名)(所指向的函數的形參清單);
void testTypedefMethodPointer()
{
// int (*sumPointer)(int num1,int num2) = sum;
//
// int (*minusPointer)(int num1,int num2) = minus;
typedef int (*MethodPointerType)(int num1,int num2);
MethodPointerType sumPointer = sum;
MethodPointerType minusPointer = minus;
int rs = sumPointer(10,20);
printf("rs = %d\n",rs);
}
//了解
void testTypedefArrayPointer()
{
char names[][10] = {"xtf","zbz","wf"};
char (*arrayPoiner)[10];
arrayPoiner = names;
typedef char (*ArrayPointerType)[10];
ArrayPointerType pointer = names;
printf("%s\n",pointer[0]);
}
int main(int argc, const char * argv[]) {
//
// testBaseType();
// testStruct();
testTypedefBasicPointer();
testTypedefStructPointer();
testTypedefEnumPointer();
testTypedefMethodPointer();
testTypedefArrayPointer();
return 0;
}