Day9.指針和結(jié)構(gòu)體
指針補(bǔ)充
1挤茄, 指針+1, 并不是真實(shí)的+1, 而是+4
2, 指針類型的兩個(gè)用途:
第一個(gè)用途, 取值的時(shí)候, 會(huì)根據(jù)指針類型所占用的字節(jié)去取出對(duì)應(yīng)字節(jié)的數(shù)據(jù)
第二個(gè)用途, 用于做加法運(yùn)算, 指針+1, 其實(shí)是加上指針類型所占用的長(zhǎng)度 , 如果當(dāng)前指針類型是int, 那么+1本質(zhì)上是加上4個(gè)字節(jié)
3记餐,只要一個(gè)指針指向了數(shù)組, 那么訪問數(shù)組就有3種方式:
1. : ages[0];
2. : p[0];
3. : *(p + 0);
4驮樊,指針字符串
// 通過數(shù)組保存字符串和通過指針保存字符串的區(qū)別
// 如果通過數(shù)組來保存字符串, 那么字符串是一個(gè)變量 str 可以修改
// 如果通過指針來保存字符串, 那么字符串是一個(gè)常量 str2 不能修該
// 數(shù)組保存的字符串存儲(chǔ)在內(nèi)存的棧中, 而通過指針保存的字符串存儲(chǔ)在常量區(qū)
// 存儲(chǔ)在棧中的變量有一個(gè)特點(diǎn), 當(dāng)作用域結(jié)束系統(tǒng)會(huì)自動(dòng)釋放該變量
// 存儲(chǔ)在常量區(qū)中的值有一個(gè)特點(diǎn), 不會(huì)被釋放, 而且多個(gè)相同的值對(duì)應(yīng)的地址相同
// 利用指針保存字符串的應(yīng)用場(chǎng)景
for (int i = 0; i < 100; i++) {
// 意味著會(huì)開辟100塊存儲(chǔ)空間來保存xmg這個(gè)字符串
// 并且會(huì)釋放100次
// char str5[] = "xmg";
char *str6 = "xmg";
printf("str5 = %s\n", str6);
}
/*
保存字符串的兩種方式:
char str[] = "lnj";
存儲(chǔ)的位置: 棧
特點(diǎn): 相同的字符串會(huì)重復(fù)的分配存儲(chǔ)空間
字符串可以修改
char *str = "lnj"
存儲(chǔ)的位置: 常量區(qū)
特點(diǎn): 相同的字符串不會(huì)重復(fù)的分配存儲(chǔ)空間
字符串不可以修改
*/
5,指向函數(shù)的指針
指向函數(shù)的指針的定義格式
void (*funtionP) ();
* : 代表是一個(gè)指針
funtionP : 代表指針變量的名稱, 區(qū)分
(*funtionP) : 代表將來指向一個(gè)函數(shù)
void : 代表將來指向的函數(shù)沒有返回值
() : 代表將來指向的函數(shù)沒有參數(shù)
int (*ageP)();
ageP = getAge;
printf("age = %i\n", ageP());
// void (*sumP)(int v1, int v2);
void (*sumP)(int, int);
sumP = sum;
sumP(10, 20);
int (*sumP2)(int , int);
sumP2 = sum2;
printf("sum = %i\n", sumP2(10, 20));
結(jié)構(gòu)體
// 1.定義結(jié)構(gòu)體類型
struct Person
{
// char name[20];
char *name;
int age;
double height;
};
// 2.定義結(jié)構(gòu)體變量
// int num;
struct Person p;
// 注意: 數(shù)組不能先定義再進(jìn)行一次性的初始化, 所有下面的寫法是錯(cuò)誤的
// p.name = "lnj"; // name = {'l', 'n', 'j', '\0'};
// 可以使用 結(jié)構(gòu)體變量名稱.屬性的方式給結(jié)構(gòu)體變量賦值
p.name = "lnj";
p.age = 30;
p.height = 1.75;
/*
int nums[] = {1, 3, 5};
int nums[3];
nums[0] = 1;
nums[1] = 3;
nums[2] = 5;
int nums[3];
nums = {1, 3, 5}; // 錯(cuò)誤
int nums[3] = {[1] = 2};
printf("nums[0] = %i\n", nums[0]);
*/
struct Dog
{
char *name;
int age;
double height;
};
// 1.定義的同時(shí)初始化
struct Dog sd = {"wc", 13, 5.0};
// 2.先定義再初始化(逐個(gè)初始化)
struct Dog sd1;
sd1.name = "ww";
sd1.age = 5;
sd1.height = 10.9;
// 3.先定義再初始化(一次性初始化)
struct Dog sd2;
// 特別注意: 結(jié)構(gòu)體和數(shù)組有一點(diǎn)區(qū)別, 數(shù)組不能先定義再進(jìn)行一次性的初始化, 而結(jié)構(gòu)體可以
// 只不過需要明確的告訴系統(tǒng){}中是一個(gè)結(jié)構(gòu)體
sd2 = (struct Dog){"xq", 8, 8.8}; // 數(shù)組? 結(jié)構(gòu)體?
// 4.指定將數(shù)據(jù)賦值給指定的屬性
struct Dog sd3 = {.height = 1.77, .name = "ww", .age = 33};
printf("name = %s, age = %i, height = %lf\n", sd3.name, sd3.age, sd3.height);
枚舉
// 1.定義枚舉類型
// 定義枚舉類型的規(guī)范
// 枚舉類型的取值一般以k開頭 后面跟上枚舉類型的名稱 跟上當(dāng)前取值的含義
// 和結(jié)構(gòu)體一樣, 枚舉類型的名稱首字母大寫
enum Season
{
kSeasonSpring,
kSeasonSummer,
kSeasonAutumn,
kSeasonWinter
};
enum Gender
{
kGenderMale,
kGenderFemale
};
enum Season es;
es = kSeasonAutumn;
enum Gender eg;
eg = kGenderFemale;
局部和全局變量
/*
局部變量
概念: 局部變量就是定義在函數(shù), 代碼塊和函數(shù)形參列表中的變量, 我們就稱之為局部變量
作用范圍: 從定義的那一行開始一直直到遇到大括號(hào)結(jié)束或者遇到return為止
特點(diǎn):
相同作用域范圍內(nèi)不能出現(xiàn)同名的局部變量
不同作用域范圍內(nèi)出現(xiàn)同名的局部變量, 內(nèi)部的局部變量會(huì)覆蓋外部的局部變量
注意:
局部變量沒有固定的初始化值, 如果沒有對(duì)局部變量進(jìn)行初始化, 那么局部變量中是一些隨機(jī)的值, 所以在開發(fā)中千萬不要使用未初始化的局部變量
存儲(chǔ)位置:
局部變量存儲(chǔ)在棧中, 當(dāng)作用域結(jié)束系統(tǒng)會(huì)自動(dòng)釋放棧中的局部變量
全局變量
概念: 寫在函數(shù),代碼塊,形參列表外的變量, 我們就稱之為全局變量
作用范圍: 從定義的那一行開始一直直到文件末尾(暫時(shí)這樣認(rèn)為)
特點(diǎn):
全局變量和局部變量可以同名
如果存在和全局變量同名的局部變量, 那么局部變量會(huì)覆蓋全局變量
注意:
全局變量如果沒有進(jìn)行初始化, 那么系統(tǒng)默認(rèn)會(huì)將全局變量初始化為0
存儲(chǔ)位置:
全局變量存儲(chǔ)在靜態(tài)區(qū)中, 他會(huì)隨著程序的啟動(dòng)而創(chuàng)建, 隨著程序的結(jié)束而結(jié)束
int num; // 全局變量 num = 0;
/*
static應(yīng)用場(chǎng)景":
當(dāng)某個(gè)方法的調(diào)用頻率非常高, 而該方法中更有些變量的值是固定不變的
那么這個(gè)時(shí)候就可以使用static來修飾該變量, 讓該變量只開辟一次存儲(chǔ)空間
這樣可以提高程序的效率和性能
*/
static double pi = 3.1415926; // 固定
宏
宏定義在什么時(shí)候替換
源代碼 --> 預(yù)處理 -->匯編 -->二進(jìn)制 -->可執(zhí)行程序
規(guī)范:
一般情況宏名都大寫, 多個(gè)單詞之間用_隔開, 并且每個(gè)單詞全部大寫
有得公司又要求宏名以k開頭, 多個(gè)單詞之間用駝峰命名
#define CLASS_COUNT 100
#define kClassCount 100
帶參數(shù)
#define PF(v1) ((v1)*(v1))
// 提前結(jié)束宏定義的作用域
//#undef COUNT
typedef起別名
/*
什么是typedef, 它有什么作用
typedef可以給一個(gè)已知的數(shù)據(jù)類型起別名 (外號(hào))
利用typedef給數(shù)據(jù)類型起別名的格式:
typedef 原有的數(shù)據(jù)類型 別名(外號(hào));
注意:
1. typedef不僅能給系統(tǒng)原有的數(shù)據(jù)類型起別名, 也可以給一個(gè)自定義的數(shù)據(jù)類型起別名
2. 利用typedef給數(shù)據(jù)類型起別名, 并不會(huì)生成一個(gè)新的數(shù)據(jù)類型, 僅僅是給原有的類型起了一個(gè)別名而已
*/
int sum(int v1, int v2)
{
return v1 + v2;
}
int minus(int v1, int v2)
{
return v1 - v2;
}
// 注意: 如果是給指向函數(shù)的指針起別名, 那么指向函數(shù)的指針的指針名稱就是它的別名
// functionPotinter == int(*functionPotinter)(int , int)
typedef int(*functionPotinter)(int , int);
int main(int argc, const char * argv[]) {
// 9如何定義變量 : 數(shù)據(jù)類型 變量名稱;
// int (*sumP)(int , int ) = sum;
functionPotinter sumP = sum;
printf("sum = %i\n", sumP(10 , 20));
// int (*minusP)(int, int) = minus;
functionPotinter minusP = minus;
printf("minus = %i\n", minusP(20, 10));
return 0;
}
// ----------------------------給指針起別名----------------------------
// String == char *
typedef char * String;
void test4()
{
// char *name = "lnj";
// 注意: 如果給指針起別名之后, 那么以后利用別名定義變量就不用再加*了
String name = "lnj";
printf("name = %s\n", name);
}
// ----------------------------給枚舉類型起別名----------------------------
// 1.先定義枚舉類型, 再給枚舉類型起別名
/*
enum Gender
{
kGenderMale,
kGenderFemale
};
typedef enum Gender SEX;
*/
// 2.定義枚舉類型的同時(shí)給枚舉類型起別名
/*
typedef enum Gender
{
kGenderMale,
kGenderFemale
} SEX;
*/
// 3.定義枚舉類型的同時(shí)給枚舉類型起別名, 并且省略枚舉原有類型名稱
typedef enum
{
kGenderMale,
kGenderFemale
} SEX;
void test3()
{
// 給枚舉起別名
// enum Gender sex;
SEX sex;
sex = kGenderMale;
/*
定義枚舉變量有3種方式
1.先定義枚舉類型, 再定義枚舉變量
2.定義枚舉類型的同時(shí)定義枚舉變量
3.定義枚舉類型的同時(shí)定義枚舉變量, 并且省略枚舉類型名稱
*/
/*
enum Gender2
{
kGenderMale2,
kGenderFemale2
} sex2;
sex2 = kGenderFemale2;
enum
{
kGenderMale3,
kGenderFemale3
} sex3;
sex3 = kGenderFemale3;
*/
}
// ----------------------------給結(jié)構(gòu)體類型起別名----------------------------
// 1.先定義結(jié)構(gòu)體類型, 再給類型起別名
/*
struct Person
{
int age;
double height;
char *name;
};
// SPerson == struct Person
typedef struct Person SPerson;
*/
// 2.定義結(jié)構(gòu)體類型的同時(shí), 給結(jié)構(gòu)體類型起別名
/*
typedef struct Person
{
int age;
double height;
char *name;
} SPerson;
*/
// 3.定義結(jié)構(gòu)體類型的同時(shí), 給結(jié)構(gòu)體類型起別名, 并且省略掉原有類型的名稱
typedef struct
{
int age;
double height;
char *name;
} SPerson;
void test2()
{
/*
// 給構(gòu)造類型起別名
struct Person
{
int age;
double height;
char *name;
};
*/
// struct Person sp0;
SPerson sp;
SPerson sp1;
SPerson sp2;
SPerson sp3;
SPerson sp4;
/*
結(jié)構(gòu)體變量的定義方式
1.先定義類型再定義變量
2.定義類型的同時(shí)定義變量
3.定義類型的同時(shí)定義變量, 并且省略類型名稱
*/
}
// ----------------------------給基本數(shù)據(jù)類型起別名----------------------------
// Integer == int
typedef int Integer;
typedef Integer myInt;
// int float doulbe char
void test1()
{
int num = 10;
printf("num = %i\n", num);
Integer age = 30;
printf("age = %i\n", age);
myInt score = 99;
printf("score = %i\n", score);
}
// 一般情況下如果要給數(shù)據(jù)類型起一個(gè)名稱建議用typedef, 不要用define