1、数据类型
1.1整型(int)
int age = 10;//4 byte
printf("%d\n", age);
1.2长整型(long)
long b = 10;//4/8 byte
printf("%d\n", b);
1.3单精度浮点型(float)
float weight = 55.5;//4 byte
printf("%f\n", weight);
printf("%e\n", weight);//%e 以指数形式输出 float 类型,输出结果中的 e 小写
1.4双精度浮点型(double)
double d_weight = 55.5;//8 byte
printf("%lf\n", d_weight);
printf("%le\n", d_weight);
1.5字符型(char)
char ch1 = 'c';//1 byte
printf("%c\n", ch1);
char arr[] = "apple";//字符串
printf("%s\n", arr);
2、操作符
2.1算数运算符
2.1.1除法
float ans1 = 9 / 2;
float ans2 = 9.0 / 2;
printf("%f\n", ans1);//ans1=4.000000
printf("%f\n", ans2);//ans2=4.500000
2.1.2取余
//取余运算要求左右操作数必须为整数
int ans1 = 9 % 2;
float ans2 = 9 % 2;
printf("%d\n", ans1);//ans1=1
printf("%f\n", ans2);//ans2=1.000000
2.2关系运算符
2.2.1 大于/小于(>/<)
//关系运算符的结果 1 和 0。(1代表true,0代表false)
int ans1 = (10 > 0);
int ans2 = (10 < 0);
printf("%d\n", ans1);//ans1=1
printf("%d\n", ans2);//ans2=0
2.2.2 不等于(!=)
int ans1 = (10 != 0);
int ans2 = (10 != 10);
printf("%d\n", ans1);//ans1=1
printf("%d\n", ans2);//ans2=0
2.3逻辑运算符
2.3.1 逻辑与(&&)
int ans1 = (10 != 0);
int ans2 = (10 != 10);
int ans3 = ans1 && ans2;
int ans4 = ans1 && ans1;
printf("%d\n", ans1);//ans1=1
printf("%d\n", ans2);//ans2=0
printf("%d\n", ans3);//ans3=0
printf("%d\n", ans4);//ans4=1
2.3.2 逻辑或(||)
int ans1 = (10 != 0);
int ans2 = (10 != 10);
int ans3 = ans1 || ans2;
int ans4 = ans1 || ans1;
int ans5 = ans2 || ans2;
printf("%d\n", ans1);//ans1=1
printf("%d\n", ans2);//ans2=0
printf("%d\n", ans3);//ans3=1
printf("%d\n", ans4);//ans4=1
printf("%d\n", ans5);//ans5=0
2.3.3 逻辑非(!)
int ans1 = (10 != 0);
int ans2 = !ans1;
printf("%d\n", ans1);//ans1=1
printf("%d\n", ans2);//ans2=0
2.4位运算符
2.4.1 位与/或/反/异或(&、|、~、^)
int ans1 = 0&3;//
int ans2 =0|3;
int ans3 = (~3);
int ans4 = 3^5;//101^011=110
printf("%d\n", ans1);//ans1=0
printf("%d\n", ans2);//ans2=3
printf("%d\n", ans3);//ans3=-4
printf("%d\n", ans4);//ans3=6
2.4.2 位左移(<<)、位右移(>>)
int ans1 = 4;
int ans2 = 4;
ans1 <<= 1;//ans1=ans1<<1;
ans2 >>= 1;
printf("%d\n", ans1);//ans1=8
printf("%d\n", ans2);//ans2=2
2.4.3 前置/后置++
int ans1 = 10;
int ans2 = ++ans1;//先++,在使用
printf("%d\n", ans1);//ans1=11
printf("%d\n", ans2);//ans2=11
int ans1 = 10;
int ans2 = ans1++;//先使用,再++
printf("%d\n", ans1);//ans1=11
printf("%d\n", ans2);//asn2=10
2.4.4 三目操作符
//exp1?exp2:exp3
int a = 10;
int b = 20;
int max = a > b ? a : b;
printf("%d\n", max);//max=20
int a = 1;
int b = 1;
int c = 1;
int ans = (a = a + 1, b = b + a, c = a + b + c);
printf("%d\n", ans);//ans=6
3、分支语句
3.1选择语句
3.1.1 if...else
int a = 30, b = 20, max = 0;
if (a > b)
{
max = a;
}
else
{
max = b;
}
printf("%d\n", max);
3.1.2 switch
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("实验室搬砖\n");
break;
case 2:
printf("划水摸鱼\n");
break;
default:
printf("出去玩\n");
}
3.2循环语句
3.2.1 while
//while循环中,break用于终止永久的循环
//continue用于跳过本次循环continue后的代码
int i = 0;
while (i<10)
{
printf("%d\n", i);
i++;
}
3.2.2 for
//100-1000的水仙花数
for (int i = 100; i < 1000; i++)
{
int a = 0, b = 0, c = 0;
a = i / 100;//百位
b = i / 10 % 10;//十位
c = i % 10;//个位
int num = a * a * a + b * b * b + c * c * c;
if (num == i)
{
printf("%d\n", i);
}
}
//前n项的阶乘的和
int i = 1, j = 1, num = 0, sum = 0;
scanf("%d", &num);
for (i=1;i<=num;i++)
{
j = j * i;
sum += j;
}
printf("%d\n", sum);
3.2.3 do...while
//n的阶乘
int i = 1, j = 1, num = 0;
scanf("%d", &num);
do
{
j = j * i;
i++;
} while (i <= num);
{
printf("%d\n", j);
}
4、函数
4.1函数的调用
4.1.1值传递
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//在调用函数中将原函数的值拷贝一份过去被调用的函数,在被调用函数中对该值的修改不会影响原函数的值。
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("交换前 a = %d b = %d\n", a, b);
swap(a, b);
printf("交换后 a = %d b = %d\n", a, b);
return 0;
system("pause");
}
4.1.2地址传递
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//交换函数,使用指针
//在调用函数的时将原函数的值所在的地址拷贝一份过去,被调用函数对这个地址所作的修改会影响原来值。
void swap(int* pa, int* pb)
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("交换前 a = %d b = %d\n", a, b);
swap(&a, &b);
printf("交换后 a = %d b = %d\n", a, b);
return 0;
system("pause");
}
4.1.3嵌套调用
#define _CRT_SECURE_NO_WARNINGS 1//取消警告
#include<stdio.h>
int text1() {
printf("text1调用");
return 0;
}
int text2() {
text1();
return 0;
}
int main() {
texr2();
return 0;
}
4.1.4链式访问
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{ //将一个函数的返回值作为另一个函数的一个参数
int len = strlen("abc");
printf("%d\n", len);
//也可以直接写成:
printf("%d\n", strlen("abc"));//链式访问
return 0;
system("pause");
}
4.2函数的参数
4.2.1实参
//调用函数的时候,调用函数时写在函数名小括号后面的参数就叫实参
//实参既可以放常量、变量、表达式
swap(&a, &b);
Max(a,b);
4.2.2形参
//定义函数的时候,写在函数名小括号后面的参数叫形参
//看做是一个占位符,没有数据,只能等到函数被调用时接收传递进来的数据
//交换函数,使用指针
void swap(int* pa, int* pb)
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
4.3函数的递归
4.3.1按序输出
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//函数递归
void print(unsigned int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
unsigned int num = 1234;
print(num);
return 0;
system("pause");
}
4.3.2求字符串长度
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//函数递归
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str+1);
else
return 0;
}
int main()
{
char str[] = "hello";
printf("%d\n", my_strlen(str));
return 0;
system("pause");
}
4.4.3阶乘
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//函数递归
int main()
{
int num = 0, ret = 1;
scanf("%d", &num);
for (int i = 1; i <= num; i++)
{
ret = ret * i;
}
printf("%d", ret);
return 0;
system("pause");
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//函数递归
int Fnc(int n)
{
if (n > 1)
return n * Fnc(n - 1);
else
return 1;
}
int main()
{
int n = 5;
int ret = Fnc(n);
printf("%d", ret);
return 0;
system("pause");
}
4.4.4斐波那契数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//函数递归求斐波那契数
int Fib(int n)
{
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d", ret);
return 0;
system("pause");
}
5、数组
5.1定义
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
//一维数组
int arr1[5] = { 1,2,3,4,5 };
int arr2[] = { 1,2,3 };
char ch1[4] = { 'b','i','t' };//b i t \0
char ch2[] = { 'b','i','t' };//b i t
char ch3[5] = "bit";//b i t \0 0
char ch4[] = "bit";//b i t \0
//二维数组,行可省列不可省
int arr[2][4] = {1,2,3,4,5,6,7,8};
int arr1[2][2] = { {1,2},{1,2} };
return 0;
}
6、指针
6.1指针类型
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
//指针类型的意义
//1、指针类型决定了指针在被解引用的时候访问几个字节
//2、指针的类型决定了指针向前或者向后走一步有多大
//int*指针,解引用访问4个字节;char*指针,解引用访问1个字节
int arr[10] = { 0 };
int *p = &arr;
char *pc = &arr;
printf("%p\n", p);//004FF720
printf("%p\n", p + 1);//004FF724
printf("%p\n", pc);//004FF720
printf("%p\n", pc + 1);//004FF721
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char str1[] = "hello";
char str2[] = "hello";
char* str3 = "hello";
char* str4 = "hello";
printf("str1<==>%s\t*str1<==>%c\tstr1<==>%p\n", str1, *str1, str1);
printf("str2<==>%s\t*str2<==>%c\tstr2<==>%p\n", str2, *str2, str2);
printf("str3<==>%s\t*str3<==>%c\tstr3<==>%p\n", str3, *str3, str3);
printf("str4<==>%s\t*str4<==>%c\tstr4<==>%p\n", str4, *str4, str4);
return 0;
}
习题一、
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> int main() { //1、&a为数组地址 //2、sizeof(a)取数组地址,其余为首元素地址 int a[] = { 1,2,3,4,5 }; int *p = (int*)(&a + 1); int *p1 = (int*)((int)a + 1); printf("%d %d\n", *(a + 1), *(p - 1));//2 5 printf("%x %x\n", p[-1], *p1);//5 2000000 return 0; }
习题二、
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> int main() { //1、&a为数组地址 //2、sizeof(a)取数组地址,其余为首元素地址 int a[] = { 1,2,3,4,5 }; int *p = (int*)(&a + 1); int *p1 = (int*)((int)a + 1); printf("%d %d\n", *(a + 1), *(p - 1));//2 5 printf("%x %x\n", p[-1], *p1);//5 2000000 return 0; }
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { //1、&a为数组地址 //2、sizeof(a)取数组地址,其余为首元素地址 int a[3][2] = { (0,1),(2,3),(4,5) };//逗号表达式,存放的1 3 5 0 0 0 int*p; p = a[0];//首元素的地址 printf("%d\n",p[0] );//1 p[0]==*(p+0) return 0; }
6.2野指针
6.2.1野指针成因
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
//1. 指针未初始化
int*pa;//局部变量指针未初始化,默认为随机值
*pa = 20;
//2. 指针越界访问
int arr[10] = { 0 };
int*p = arr;
int i = 0;
for (i = 0; i <= 10; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
6.2.2如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL,0地址是无法访问的
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
6.3指针运算
6.3.1指针+、-整数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
int*p = arr;
int*pend = arr + 9;
while (p<=pend)
{
printf("%d\n", *p);
p++;
}
return 0;
}
6.3.2指针-指针
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
int*p = arr;
//相减前提指向同一空间
printf("%d\n", arr[9]-arr[0]);//9
printf("%d\n", sizeof(arr));//40
printf("%d\n", sizeof(arr)/sizeof(arr[0])); //10
return 0;
}
6.3.3关系运算
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5 };
int *p;
for (p = &arr[0]; p < &arr[5]; p++)
{
*p = 0;
printf("%d\n", *p);
}
return 0;
}
6.4指针与数组
6.4.1数组名
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
//数组名代表数组首元素的地址
int arr[] = { 1,2,3,4,5 };
int *p = arr;
for (int i=0;i<5;i++)
{
printf("%p<==>%p\t", &arr[i], p + i);
printf("%d<==>%d\n", arr[i], *(p + i));
}
return 0;
}
6.4.2指针数组
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
//存放指针的数组
int arr[5] = { 1,2,3,4,5 };
int* parr[5] = { 0 };
for (int i = 0; i < 5; i++)
{
parr[i] = &arr[i];
printf("%d<==>%p\n", *parr[i],parr[i]);
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int a[] = { 0,1,2,3,4 };
int b[] = { 0,1,2,3,4 };
int c[] = { 0,1,2,3,4 };
int *arr[] = { a,b,c };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", *(arr[i] + j));
}
printf("\n");
}
return 0;
}
6.4.3数组指针
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5 };
int*p1 = arr;//值相同,类型不同
int(*p2)[5] = &arr;
for (int i = 0; i < 5; i++)
{
printf("%d ", *p1+i);
}
printf("\n");
for (int i = 0; i < 5; i++)
{
printf("%d ", *((*p2) + i));
}
printf("\n");
printf("p1<==>%p\t p1+1<==>%p\n", p1, p1 + 1);
printf("p2<==>%p\t p2+1<==>%p\n", p2, p2 + 1);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[3][5] =
{ {1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5} };
int(*p)[5] = arr;//数组名代表首元素地址,首元素为第一行
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d", *(*(p + i) + j));//p+i为第i行arr[i][5];
}
printf("\n");
}
return 0;
}
6.5函数指针
6.5.1函数指针
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
//函数名==&函数名
//Add==&Add=*p==p
int(*p)(int, int) = &Add;
printf("%d %d", p(3,5),(*p)(3, 5));
return 0;
}
6.5.2函数指针数组
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("*************************\n");
printf("******1.Add 2.Sub******\n");
printf("******3.Mul 4.Div******\n");
printf("******* 0.exit ********\n");
printf("*************************\n");
}
int main()
{
int input = 0;
do
{
menu();
int(*Arr[5])(int, int) = { NULL,Add,Sub,Mul,Div };
int x, y, ans = 0;
printf("请选择:\n");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入两个数:\n");
scanf("%d%d", &x, &y);
ans = (Arr[input])(x, y);
printf("ans=%d\n", ans);
}
else if(input==0)
{
printf("退出\n");
break;
}
else
{
printf("请重新选择:\n");
}
} while (input);
return 0;
}
6.5.3回调函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("*************************\n");
printf("******1.Add 2.Sub******\n");
printf("******3.Mul 4.Div******\n");
printf("******* 0.exit ********\n");
printf("*************************\n");
}
//回调函数
//int(*p)(int,int)=Add函数指针
int Calc(int(*p)(int, int))
{
int x, y = 0;
printf("请输入两个数:\n");
scanf("%d%d", &x, &y);
return p(x, y);
}
int main()
{
int input = 0;
do
{
menu();
int ans = 0;
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case 1:
ans = Calc(Add);
printf("ans=%d\n", ans);
break;
case 2:
ans = Calc(Sub);
printf("ans=%d\n", ans);
break;
case 3:
ans = Calc(Mul);
printf("ans=%d\n", ans);
break;
case 4:
ans = Calc(Div);
printf("ans=%d\n", ans);
break;
case 0:
printf("退出\n");
break;
default:
printf("请重新选择:\n");
break;
}
} while (input);
return 0;
}
6.5.4模拟qsort
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void Swap(char*buf1, char*buf2, int width)
{
for (int i = 0; i < width; i++)
{
char temp = *buf1;
*buf1 = *buf2;
*buf2 = temp;
buf1++;
buf2++;
}
}
//模拟qsort
void bubble_sort(void* base, int len, int width, int(*cmp)(const void*e1, const void*e2))
{
for(int i=0;i<len-1;i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (cmp((char*)base + j * width, (char*)base + (j + 1)*width) > 0)
{
Swap((char*)base + j * width, (char*)base + (j + 1)*width, width);
}
}
}
}
void print_arr(int arr[], int len)
{
for (int i = 0; i < len; i++)
{
printf(" %d", arr[i]);
}
printf("\n");
}
int cmp_int(const void *e1, const void *e2)
{
return *(int*)e1 - *(int*)e2;
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int len = sizeof(arr) / sizeof(arr[0]);
int width = sizeof(arr[0]);
print_arr(arr, len);
bubble_sort(arr, len, width, cmp_int);
print_arr(arr, len);
return 0;
}
6.6二级指针
int a = 10;
int* pa = &a;//*pa==a
int** ppa = &pa;//*ppa=pa,**ppa==*pa==a
printf("%d %d %d\n", a, *pa,**ppa);//10 10 10
7、自定义类型
7.1结构体
7.1.1结构体创建
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
struct Stu
{
char name[20];
int id;
int age;
int scores;
};
void print1(struct Stu s)
{
printf("%s %d %d %d\n", s.name, s.id, s.age, s.scores);
}
void print2(struct Stu *p)
{
printf("%s %d %d %d\n", p->name, p->id, p->age, p->scores);
}
int main()
{
Stu s = { "jack",2022204309,20,98 };
Stu*p = &s;
printf("%s %d %d %d\n", s.name, s.id, s.age, s.scores);
printf("%s %d %d %d\n", p->name, p->id, p->age, p->scores);
print1(s);//值传递
print1(*p);//地址传递
return 0;
}
7.1.2结构体内存对齐
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//结构体内存对齐
//让占用空间小的成员尽量集中在一起
struct S1
{
char a;
char b;
int i;
};
struct S2
{
char a;
int i;
char b;
};
int main()
{
struct S1 s1 = { 0 };
struct S2 s2 = { 0 };
printf("%d\n", sizeof(s1));//8
printf("%d\n", sizeof(s2));//12
return 0;
}
7.1.3修改默认对齐数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//结构体内存对齐
//默认对齐数为8
//把对齐数改为1
#pragma pack(1)
struct S1
{
char a;
char b;
int i;
};
#pragma pack()//只有s1对齐数为1
struct S2
{
char a;
char b;
int i;
};
int main()
{
struct S1 s1 = { 0 };
struct S2 s2 = { 0 };
printf("%d\n", sizeof(s1));//6
printf("%d\n", sizeof(s2));//8
return 0;
}
7.2位段
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//位段的声明与结构体类似
//1.位段成员必须是int/ unsigend int /signed int/char
//2.成员名后有冒号和数字
struct A
{
//4个字节--32bit
int _a : 2;//占2bit
int _b : 5;//5bit
int _c : 10;//10bit
//4个字节--32bit
int _d : 30;//30bit
};
int main()
{
printf("%d\n", sizeof( struct A));//8
return 0;
}
7.3枚举
7.4联合体
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//联合体成员共用一块内存空间
int check_sys1()
{
int a = 1;
if (*(char*)&a == 1)
{
return 1;
}
else
{
return 0;
}
}
int check_sys2()
{
union Un
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}
int main()
{
int ret1 = check_sys1();
int ret2 = check_sys2();//利用联合体判断大小端
if (ret1 == 1)
printf("小端\n");
else
printf("大端\n");
if (ret2 == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
8、内存函数
8.1 memcpy
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, int num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
char ch1[] = "abbbcdef";
char ch2[] = "bbc";
char* ret = my_memcpy(ch2, ch1,3);
printf("%s\n", ret);
return 0;
}
8.2动态内存开辟
8.2.1 malloc
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
int main()
{
//开辟10个整型空间,存放在栈区
int arr[10] = { 0 };
//动态内存开辟
int* p = (int*)malloc(10 * sizeof(int));
//如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL
if (p == NULL)
{
perror("main");
return 0;
}
for (int i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d ", p[i]);
}
//使用完成一定要释放空间,否则会造内存泄漏。
free(p);//作用:释放给指针变量分配的内存空间。
p = NULL;//使用后该指针变量一定要重新指向NULL,防止悬空指针(失效指针),规避错误操作。
return 0;
}
8.2.3 realloc
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
int main()
{
//开辟10个整型空间,存放在栈区
int arr[10] = { 0 };
//动态内存开辟
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
perror("main");
return 0;
}
for (int i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d ", p[i]);
}
//这里需要p指向更大的空间,20个int
int *ptr=realloc(p, 20 * sizeof(int));
//如果原空间之后有足够的空间就可以直接追加,然后返回调整之后的空间的起始位置地址
//如果没有足够的空间,重新找一个新的内存区域,将原数据拷贝过去再追加,返回新空间的起始位置地址
if (ptr != NULL)
{
p = ptr;
}
free(p);//释放内存空间。
p = NULL;//防止悬空指针
return 0;
}
9、文件
9.1读写文件
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* pf = fopen("test_9.2.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
fputc('t', pf);
fputc('j', pf);
fputc('u', pf);
fputc('\n', pf);
fputs("Tianjin University\n", pf);
fputs("Peiyang University\n", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct S
{
char arr[10];
int num;
float fn;
};
int main()
{
struct S s1 = { "Tiangjin",125,9.2f };
FILE* pf = fopen("test_9.2.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//对格式化数据进行写文件
//fprintf(pf, "%s %d %f", s1.arr, s1.num, s1.fn);
// 二进制写入
fwrite(&s1, sizeof(struct S), 1, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct S
{
char arr[10];
int num;
float fn;
};
int main()
{
struct S s1 = { "Tiangjin",125,9.2f };
struct S s2 = { 0 };
char ch[100] = { 0 };
//把格式化数据改成字符串
sprintf(ch, "%s %d %f", s1.arr, s1.num, s1.fn);
printf("%s\n", ch);
//逆过程,还原
sscanf(ch, "%s %d %f\n", s2.arr, &(s2.num), &(s2.fn));
printf("%s %d %f\n", s2.arr,s2.num,s2.fn);
return 0;
}
9.2随机读写
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读取文件
int ret = fgetc(pf);
printf("%c ", ret);//a
ret = fgetc(pf);
printf("%c ", ret); //b
//文件随机读写
//调整文件指针
fseek(pf, 2, SEEK_CUR);//当前位置后偏移2byte
ret = fgetc(pf);
printf("%c\n", ret);//e
int ret1 = ftell(pf);//告知偏移量
printf("%d\n", ret1);//5
//文件指针回到起始位置
rewind(pf);
ret1 = ftell(pf);
printf("%d\n", ret1);//0
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}