//输入字符串的案例
char chs[10];
int index = 0;
char ch;
while((ch = getchar()) !='\n' && index < 256 -1) {
chs[index ++] = ch;
}
// 如果 ch == '\n' ch != '\n'
if(ch != '\n') {
while(getchar() !='\n');
}
//内存有时会浪费, 有时又会不够用
//数组是存储的数据
//需要可以动态伸缩的内存
// 什么是内存管理
// 对程序运行中申请的内存进行维护与销毁的过程
// 栈内存, 由系统申请并维护,函数一执行就有栈内存, 函数结束,内存回收
// 堆内存, 程序运行过程中,由程序员申请的内存, 内存的回收与管理由程序员来维护
// 如果程序员没有回收不用的内存, 容易造成内存泄露
malloc 函数
向操作系统申请指定字节数的内存,如果申请成功,
返回内存的首地址, 如果失败返回 NULL
语法:
void *malloc(unsigned long size);
返回 void 类型的指针
void 是 C89 提出的概念, 目的是用来表示通用指针类型
calloc 函数
realloc 函数
free 函数
回收申请的内存,注意申请的内存变量不要随意的修改
void free(void *);
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char *argv[]) {
int *p = (int *)malloc(40);// 不写 (int *) 也是默认转成 int 指针
//此时我实际上声明了一个长度为 10 的 int数组
char *str = (char *)malloc(10);// 长度为 40 的字符串(char 数组)
// int 数组
// int *temp = p;
// int *temp = NULL;
// temp = p;
// // temp 和 p 都是指针类型的变量, 都指向刚刚创建的 40 个字节的内存
//
// for (int i = 0; i < 10; i++) {
// scanf("%d", temp++);
// // scanf("%d", p++);
// }
//
// printf("==========\n");
// temp = p;
// // p -= 10;
// for (int i = 0; i < 10; i++) {
// printf("%d\n", *temp++);
// // printf("%d\n", *p++);
// }
// ==============================================
// char 数组
int index = 0;
char ch;
while ((ch = getchar()) !='\n' && index < 10 -1) {
str[index++] = ch;// index 表示将要添加字符是位置
}
// 如果 ch == '\n' ch != '\n'
char tempChar;
if (ch != '\n') {
while ((tempChar = getchar()) != '\n') {
// printf("%c\n", tempChar);
}
}
str[index] = '\0';// 在字符串结尾加一个 \0 表示字符串结束
printf("=====\n");
printf("%s\n", str);
char c = getchar();// 为什么?
//检验是否已经清空缓存中的数据
// 如果清空了, getchar 会阻塞
//如果没有, getchar 会从缓存中直接去数据,而不会阻塞
// 使用 free 函数回收内存
free(p);
free(str);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void *czalloc(int size1,int size2) { returnmalloc(size1 * size2); }
int main(int argc,const char *argv[]) {
// // malloc 是申请指定长度的内存
// int *p = (int *)malloc(4000);
//
// // 首地址 calloc(单位长度, 多少个单位);
// int *p1 = (int *)calloc(4, 1000);
//
// // 在功能上, malloc 与 calloc 是一样的, 为了申请内存
// //申请后的内存是需要回收的, 但是他们的区别在内存数据上
// // malloc 申请的内存里面是垃圾数
// // calloc 申请的内存会全部清零
//
//
// for (int i= 0; i< 1000; i++) {
// printf("%d ", p1[i]);
// if(i % 20 == 0) printf("\n");
// }
//
// re- 英文词缀, 重复
int *p = malloc(10);// 十个字节
printf("%p\n", p);
p =realloc(p, 20);// 扩充为二十个字节
printf("%p\n", p);
p =realloc(p, 5);
printf("%p\n", p);
// p修改大小以后的地址的值不一定是一样的
//如果是扩容, 系统会检查原来的内存中是否可以容得下这些字节
free(p);
return 0;
}
/*
指针函数
就是返回指针类型数据的函数,其语法
数据类型 *函数名(...) { ... }
写一个函数,返回用户输入的字符串
*/
#include <stdio.h>
#include <stdlib.h>
char *inputString() {
// char str[10];
int length = 10;
char *str = malloc(length);// 内存的管理必须由程序员自己完成
int index = 0;
char ch;
while ((ch = getchar()) !='\n' && index < length - 1) {
str[index++] = ch;
}
char tempChar;
if (ch != '\n') {
while ((tempChar = getchar()) != '\n')
;
}
str[index] ='\0';
printf("%p\n", str);
return str;
}
int main(int argc,const char *argv[]) {
// insert code here...
// printf("Hello, World!\n");
char *str = inputString();
printf("%p\n", str);
printf("|%s|\n", str);
printf("|%c|\n", *(str +0));
printf("|%c|\n", *(str +1));
printf("|%c|\n", *(str +2));
printf("|%c|\n", *(str +3));
printf("|%c|\n", *(str +4));
printf("|%c|\n", *(str +5));
printf("|%c|\n", *(str +6));
printf("|%c|\n", *(str +7));
printf("|%c|\n", *(str +8));
printf("|%c|\n", *(str +9));
free(str);
return 0;
}
函数指针, 就是指函数的地址
函数指针变量,就是一个存储函数首地址的变量
函数名, 表示的就是函数的首地址
函数指针变量如何定义:
int *p;
char *p;
char (*p)[10];
void (*p)(); // 指向一个无参无返回值的函数,变量是 p
int (*p)(int num1, int num2);
函数指针如何使用:
1, 语法用法
p = 函数名;
p() 来调用该函数, 好比 p 就是函数的别名一样
如何使用如何调用即可
2, 实际用法
函数指针可以让函数作为变量来使用,
最大的优势是可以作为参数在函数间进行传递
void func(int num) { ... }
void func( int (*p)() ) { ... }
*/
#include <stdio.h>
void func1() {printf("func被打印了\n"); }
void func2() {printf("这里是func2函数\n"); }
void func3(int num) {printf("num的两倍是 %d\n",2 * num); }
void func4(int num) {printf("%d\n", num); }
int func5(int num) {return 2 * num; }
int func6(int num) {return num * num; }
int main(int argc,const char *argv[]) {
// printf("%p\n", func);
// printf("%p\n", main);
// //定义了一个指向无参无返回的函数指针变量
// void (*p)();
//
// // 让这个函数指针变量, 指向函数 func
// p = func1;
//
//
// // 使用 p 就可以调用 func 了
// p(); // func()
//
//
// p = func2;
//
// p();
// void (*p1)(int num);
//
// p1 = func3;
//
// p1(13);
//
// p1 = func4;
//
// p1(5);
int (*p2)(int);
p2 =func5;
int res1 = p2(5);
printf("%d\n", res1);
p2 =func6;
int res2 = p2(5);
printf("%d\n", res2);
return 0;
}
#include <stdio.h>
void func() {printf("打印测试\n"); }
void _0卖1() {printf("用第一种方法卖房子\n"); }
void _0卖2() {printf("用第二种方法卖房子\n"); }
void invokeFunc(void (*p)()) { p(); }
void _0我要卖房子(void (*中介)()) {
if (中介 ==NULL) {
printf("没有找到好中介\n");
}else {
中介();
}
}
int main(int argc,const char *argv[]) {
// invokeFunc(func);
_0我要卖房子(_0卖2);
return 0;
}
#include <stdio.h>
int czCompare1(int num1,int num2) { return num1 - num2; }
int czCompare2(int num1,int num2) { return num2 - num1; }
void sort(int nums[],int length, int (*compare)(int,int)) {
for (int i =0; i < length - 1; i++) {
for (int j =0; j < length - i - 1; j++) {
if (compare(nums[j], nums[j + 1]) > 0) {
int temp = nums[j];
nums[j] = nums[j +1];
nums[j +1] = temp;
}
}
}
}
int main(int argc,const char *argv[]) {
int nums[] = {1, -2,4, -1234, 1234, 34, -2321,0};
// sort(nums, 8, czCompare1);
sort(nums, 8, czCompare2);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char *argv[]) {
// while(1);
/*
int *p;
for (int i = 0; i < 200; i++) {
p = malloc(1024 * 1024);
// 不断的申请内存,但是又不去释放那么内存会变得非常的大,
而且无法再使用这段内存
// 那么内存就有可能无故的被占用,其他的程序也无法访问这段内存
// free(p);
}
while (1) {
}
*/
// int *p; // p 的 值为什么是 NULL
// // p 到底指向的是什么?
//
// scanf("%d", p);
//
//
// // p 不知道指向的是谁
int *p = malloc(4);
scanf("%d", p);
free(p);
printf("%p\n", p);
//内存已经被回收, 但是 p依旧指向这个内存, 容易造成使用非法的内存数据
scanf("%d", p);
// 野指针
// 声明指针变量后,初始化为 NULL int *p = NULL
// 使用 free 回收内存后, 一定要设置变量为 NULL
// if(p == NULL)
return 0;
}
定义一个结构体
struct 结构体类型的名字 {
// 成员
int age;
char name[10];
...
};
结构体类型的定义应该写在哪里呢?一般写成全局的, 实际开发中,常常写在头文件中
如何使用
1, 先利用结构体类型定义该类型的变量
struct 结构体类型名 变量名;
2, 初始化(先定义再初始化)
变量名.成员名 =值;
3, 使用结构体成员
结构体成员的时候与直接使用成员类型的变量的方法一模一样
1, 声明结构体类型
先声明类型, 再定义变量
声明了类型的同时,定义变量
struct 结构体类型名 {
// 成员
} 变量名1, 变量名1, ..., 变量名N;
声明匿名类型的同时,定义变量
struct {
// 成员
} 变量1, 变量2, ..., 变量n;
2, 声明结构体类型变量的同时进行初始化
struct 结构体名 变量名 = { 按照定义的顺序排列数据即可 };
使用结构体变量作为结构体成员的结构体变量
结构体不允许是自己的成员, 但是使用结构体指针可以作为自己的成员
// 结构体作为函数参数语法
// 返回类型 函数名 (struct 结构类型名 形式参数名) { ... }
#include <stdio.h>
#include <string.h>
// 定义的结构
struct Score {
int chineseScore;
int mathScore;
int englishScore;
};
struct Student {
char name[20];
int age;
char gender;
// 分数
struct Score score;
};
structScore initScore(int cScore,int mScore, int eScore) {
struct Score score;
score.chineseScore = cScore;
score.mathScore = mScore;
score.englishScore = eScore;
return score;
}
structStudent initStudent(char *name,int age, char gender,int cScore, int mScore,int eScore) {
struct Student stu;
strcpy(stu.name, name);
stu.age = age;
stu.gender = gender;
stu.score =initScore(cScore, mScore, eScore);
// struct Student stu1 = { name, age, gender , .... };
return stu;
}
void printScore(structScore score) {
printf("chinese = %d\n", score.chineseScore);
printf("math = %d\n", score.mathScore);
printf("english = %d\n", score.englishScore);
}
void printStudent(structStudent stu) {
printf("name = %s\n", stu.name);
printf("age = %d\n", stu.age);
printf("gender = %s\n", stu.gender =='f' ? "女" :"男");
printScore(stu.score);
}
int main(int argc,const char * argv[]) {
struct Student s1 =initStudent("张晓艺",10, 'm', 90, 85, 90);
struct Student s2 =initStudent("李狗蛋",3, 'f', 100, 80, 45);
printStudent(s1);
printf("==============\n");
printStudent(s2);
return 0;
}