笔记:指针,结构体,枚举

#mark- 01-指针和数组

//问题:指针类型的用途是什么?

答:

第一个用途, 取值的时候, 会根据指针类型所占用的字节去取出对应字节的数据

第二个用途, 用于做加法运算, 指针+1, 其实是加上指针类型所占用的长度 , 如果当前指针类型是int, 那么+1本质上是加上4个字节

#mark- 02-指针和字符串

//问题1.通过数组保存字符串和通过指针保存字符串的区别?

答:

1)如果通过数组来保存字符串, 那么字符串是一个变量 str  可以修改

如果通过指针来保存字符串, 那么字符串是一个常量 str2 不能修该

2)数组保存的字符串存储在内存的栈中, 而通过指针保存的字符串存储在常量区

//问题2:字符串存储在栈中和存储在常量区中有什么区别?

答:

存储在栈中的变量有一个特点, 当作用域结束系统会自动释放该变量

存储在常量区中的值有一个特点, 不会被释放, 而且多个相同的值对应的地址相同

char str3[] = "lnj";

printf("str = %p\n", str);

printf("str3 = %p\n", str3);

char *str4 = "lmj";

printf("str2 = %p\n", str2);

printf("str4 = %p\n", str4);

//问题3:保存字符串的方式有哪些?

答:

char str[] = "lnj";

存储的位置: 栈

特点: 相同的字符串会重复的分配存储空间

字符串可以修改

char *str = "lnj"

存储的位置: 常量区

特点: 相同的字符串不会重复的分配存储空间

字符串不可以修改

#mark- 03-指针和字符串注意点

//问题:指针保存字符串有什么注意点?

答:

//1.指针没有被初始化不能随便使用, 野指针

int *p;

printf("*p = %i\n", *p);

//2.scanf不能用指针接收字符串,只能用数组接收(指针指向的字符串是一个常量,不能被修改)

char str[10];

scanf("%s", str);

printf("str = %s\n", str);

指针没有初始化, 是野指针

char *str;

scanf("%s", str);

printf("str = %s\n", str);

//注意: 用指针来保存字符串不可以被修改

// 指针没有初始化不能随便使用

#mark- 04-指针数组

//问题:指针数组的本质是什么?

答:指针数组中保存的每一个元素都是指针

//也叫字符串数组

// 定义数组的格式: 元素类型 数组名称[元素的个数]

char *names[4] =

{

"lnj",

"lmj",

"jjj",

"lk"

};

for (int i = 0; i < 4; i++) {

printf("names[%i] = %s\n", i , names[i]);

}

#mark- 05-指针变量的作用

//问题:数据类型可以做哪3件事?

//数组作为函数参数,专业做法用指针接收

1.可以用来定义变量

2.可以用来作为形参的类型

3.作为返回值

//问题2:指针保存字符串和数组字符串,作为函数返回值有什么区别?

char *name = demo();

printf("name = %s\n", name);

char *name2 = demo2();

printf("name2 = %s\n", name2);

char *demo2()

{

char name[]= "lnj";

return name;

}

char *demo()

{

char *name = "lnj";

return name;

}

#mark- 06-指针综合练习

//问题:这一节使用了哪些知识点?

答:

// 自己可以尝试实现strlen函数

函数运用的知识:

1.任何数值都有真假性

2.++ 在前,在后区别

3.指针+1, 其实是加上指针类型所占用的长度

4.循环语句省略大括号,只会执行最近的一行语句

char *name = "lnj";

int size =myStrlen3(name);

printf("size = %i\n", size);

int myStrlen3(char *str)

{

int count = 0;

// \0 ascii 0 // 0代表假 1真

while (*str++)count++;

return count;

}

#mark- 07-指向函数的指针基本概念

//问题:指向函数的指针的格式?指向函数的指针有几种类型?

//1.指向函数的指针的定义格式

void (*funtionP) ();

*    : 代表是一个指针

funtionP    : 代表指针变量的名称, 区分

(*funtionP) : 代表将来指向一个函数

void : 代表将来指向的函数没有返回值

()  : 代表将来指向的函数没有参数

//2.指向函数的指针第一种方式

void (*funtionP) ();

funtionP = test; // 注意: 千万不能写成test()

test(); // 0x100000f00();

(*funtionP)(); // 0x100000f00()

// test == funtionP

funtionP();

//3.四种函数类型 的指针

//没有返回值没有参数

void test()

{

printf("哥被执行了\n");

}

//有返回值没有参数

int getAge()

{

return 30;

}

//没有返回值有参数

void sum(int v1, int v2)

{

int res = v1 +  v2;

printf("res = %i\n", res);

}

//有返回值有参数

int sum2(int v1 , int v2)

{

int res = v1 + v2;

return  res;

}

int main(int argc, const char * argv[]) {

printf("test = %p\n", test);

//1).指向 没有返回值没有参数的指针

void (*funtionP) ();

funtionP = test; // 注意: 千万不能写成test()

test(); // 0x100000f00();

(*funtionP)(); // 0x100000f00()

// test == funtionP

funtionP();

//2).指向 有返回值没有参数的指针

int (*ageP)();

ageP = getAge;

printf("age = %i\n", ageP());

//3).指向 没有返回值有参数的指针

//    void (*sumP)(int v1, int v2);

void (*sumP)(int, int); //形参名可以省略

sumP = sum;

sumP(10, 20);

//4).指向 有返回值有参数的指针

int (*sumP2)(int , int);

sumP2 = sum2;

printf("sum = %i\n", sumP2(10, 20));

}

#mark- 08-指向函数的指针应用场景

//问题:指向函数的指针应用场景是什么?

答:通过指向函数的指针将函数作为函数的参数传递

// 定义一个方法, 给你两个数, 用户要求你做加法你就做加法, 用户要求你做减法, 那你就做减法

int sum(int v1, int v2)

{

return v1 + v2;

}

int minus(int v1, int v2)

{

return v1 - v2;

}

// 以后我们只需要给demo函数传递对应的指针, 那么函数内部就可以调用不同的函数

int demo3(int v1, int v2, int (*p)(int, int))

{

return p(v1, v2);

}

int main(int argc, const char * argv[]) {

printf("mins = %i\n", demo3(20, 10, minus));

printf("sum = %i\n", demo3(20, 10, sum));

return 0;

}

#mark- 09-指向函数的指针练习

void ts(char *temp, void (*funtionP)(char *))

{

// 1.先将第一个字母转换为大写

upperCase(temp);

// temp == &str[0]

while (*temp != '\0') { // h e l l o 空格 w

// 2.1取出当前的字符, 判断是否等于 空格, 如果等于空格就需要将下一个字符转换为大写

if ((*temp) == ' ') {

// 2.2将下一个字符转换为大写

funtionP(++temp);

}else

{

temp++; // temp == &str[7];

}

}

}

//小写转换为大写

void upperCase(char *p)

{

// 1.判断是否是小写字母

if (*p >= 'a' && *p <= 'z') {

// 2.将小写字母转换为大写字母

*p = *p - ('a'  - 'A'); // 32 小写的ascii大于大写

}

}

#mark- 10-结构体基本概念

//问题:如何定义结构体变量?结构体的格式?如何给结构体的属性赋值?

答:

数组: 是用于保存一组相同类型的数据

结构体: 是用于保存一组不同类型的数据

//1.定义一个结构体变量

1).定义结构体类型

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

定义结构体类型的格式:

struct 结构体类型名称

{

属性;

};

//2.可以使用 结构体变量名称.属性的方式给结构体变量赋值

// 1.定义结构体类型

struct Person

{

char *name;

int age;

double height;

};

// 2.定义结构体变量

struct Person p;

// 注意: 数组不能先定义再进行一次性的初始化, 所以结构体中字符串用指针接收

p.name = "lnj";

p.age = 30;

p.height = 1.75;

#mark- 11-结构体初始化

//问题:结构体初始化的几种方式?如何从结构体中获取数据?

答:

注意和数组的对比学习

struct Dog

{

char *name;

int age;

double height;

};

// 1.定义的同时初始化

struct Dog sd = {"wc", 13, 5.0};

// 2.先定义再初始化(逐个初始化)

struct Dog sd1;

sd1.name = "ww";

sd1.age = 5;

sd1.height = 10.9;

// 3.先定义再初始化(一次性初始化)

struct Dog sd2;

// 特别注意: 结构体和数组有一点区别, 数组不能先定义再进行一次性的初始化, 而结构体可以

// 只不过需要明确的告诉系统{}中是一个结构体

sd2 = (struct Dog){"xq", 8, 8.8}; // 数组? 结构体?

// 4.指定将数据赋值给指定的属性

struct Dog sd3 = {.height = 1.77, .name = "ww", .age = 33};

printf("name = %s, age = %i, height = %lf\n", sd3.name, sd3.age, sd3.height);

#mark- 12-结构体内存分配

//问题:结构体变量是如何分配内存空间的?

答:

1.定义结构体类型并不会分配存储空间

2.只有定义结构体变量才会真正的分配存储空间

3.结构体第0个属性的地址就是结构体的地址

4.和数组一样, 结构体内存寻址从大到小, 存储数组是从小到大(先存储第0个属性, 再一次存储其它属性)

//问题2.结构体如何开辟存储空间?

答:

结构体分配存储空间本质上并不是将所有属性占用的存储空间的总和加在一起后再分配,

而是会获取结构体类型中占用内存最大的属性的大小, 然后取该大小的倍数

特例:

如果剩余的存储空间"不够"存储将要存储的数据, 那么就会重新开辟8个字节的存储空间, 并且将需要存储的数据放到新开辟的存储空间中

如果剩余的存储空间"够"存储将要存储的数据, 那么就不会开辟了

#mark- 13-结构体类型定义方式

//问题:结构体类型有几种定义方式?

答:

// 1.先定义结构体类型, 再定义结构体变量

struct Person

{

int age;

char *name;

double height;

};

struct Person sp;

// 2.定义结构体类型的同时定义结构体变量

struct Person

{

int age;

char *name;

double height;

} sp;

// 数据类型 变量名称

sp.age = 30;

printf("age = %i\n", sp.age);

struct Person  sp1;

sp1.name = "lnj";

printf("name = %s\n", sp1.name);

// 3.定义结构体类型的同时定义结构体变量, 并且省略结构体名称

// 如果在定义结构体类型的同时定义结构体变量, 那么可以省略结构体类型名称

// 弊端: 由于结构体类型没有名称, 所以以后就不能使用该结构体类型

// 优点: 如果结构体类型只需要使用一次, 那么可以使用该方式

struct

{

int age;

char *name;

double height;

} sp;

sp.age = 55;

printf("age = %i\n", sp.age);

#mark- 14-结构体类型作用域

//问题:结构体类型的作用域的注意点有哪些?

答:

1.在不同的作用域中可以有同名的局部变量, 如果访问采用就近原则

2.在不同的作用域中可以定义同名的结构体类型, 如果使用同名的结构体类型定义结构体变量, 采用就近原则

3.如果将结构体类型写在函数或者代码块外面, 那么结构体类型的作用域和全局变量一样, 从定义的那一行开始一直直到文件末尾

4.相同作用域不能有同名的结构体类型

#mark- 15-指向结构体的指针

//问题1.如何定义指向结构体变量的指针?

答:

1.拷贝结构体类型 和 结构体变量名称

2.在类型和名称中间加上一颗心

struct Person

{

int age;

char *name;

double height;

};

struct Person sp = {30, "lnj", 1.75};

sp.name = "lnj";

sp.age = 30;

sp.height = 1.75;

// 定义了一个指向结构体的指针

// *sip == sp

struct Person *sip;

sip = &sp;

//问题2.当指针指向结构体之后如何利用指针访问结构体?

答:

结构体变量名称.属性;

(*结构体指针变量名称).属性;

结构体指针变量名称->属性;

#mark- 16-结构体数组

//问题:结构体数组格式是什么?如何获取结构体数组中的属性?

答:

// 元素类型 数组名称[元素个数];

struct Bumen bumens[3] =

{

{"iOS", 20, 100.0}, // 0

{"Andoird", 10, 99.0},

{"php", 500, 88.0}

};

//    bumens[0] == ios

bumens[0].name = "iOSv587";

bumens[0].count = 99;

bumens[0].kpi = 100.0;

printf("name = %s, count = %i, kpi = %lf\n", bumens[0].name, bumens[0].count, bumens[0].kpi);

#mark- 17-结构体嵌套

//问题:结构体如何进行嵌套?如何给结构体中嵌套的结构体赋值或者访问?

答:

//赋值

如果结构体类型中的属性又是一个结构体, 那么赋值时候通过{}赋值

//访问

如果结构体的属性又是一个结构体, 那么可以通过连续.的方式, 访问结构体属性中的属性

#mark- 18-结构体和函数

//问题:结构体作为函数的参数如何传递?结构体之间赋值是如果传递的?

答:

1.将结构体的属性传递给函数, 在函数中修改形参不会影响到实参

2.将结构体名称作为参数传递, 在函数中修改形参不会影响到实参

结构体之间赋值是值传递, 系统会将A结构体的值 拷贝一份到 B结构体中

#mark- 19-枚举基本概念

//问题:什么是枚举类型?枚举类型的格式?定义枚举的规范有哪些?

答:

//1.枚举就是专门用于表示几种固定类型的取值

枚举的本质就是基本数据类型, 就是整形

//2.枚举类型定义的格式

enum 枚举类型名称

{

取值,

};

//3.通过枚举类型定义枚举变量

定义枚举变量和定义结构体变量一样, 直接将数据类型拷贝过来, 空格之后写上变量名称即可

//4.注意点:

由于枚举类型的本质是整型, 所以枚举类型除了可以接收枚举的固定的取值以外, 还可以接收其它整型的值

也就是枚举类型的变量可以当做int类型的变量来使用

//5.定义枚举类型的规范

枚举类型的取值一般以k开头 ,后面跟上枚举类型的名称 , 跟上当前取值的含义

和结构体一样, 枚举类型的名称首字母大写

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容