学习资源来自b站逊哥带你学计算机
视频链接:https://www.bilibili.com/video/BV1tNpbekEht/?vd_source=21986a5c5d1c6c1a3a0e2e0f6e6cd097
1.学什么?

2.C语言前置内容
函数,数组,字符串,指针,内存解析,结构体
2.1函数

2.1.1函数的四种形式
无参数,无返回值案例:函数/test3.c
无参数,有返回值案例:函数/test4.c
有参数,无返回值案例:函数/test5.c
有参数,有返回值案例:函数test6.c
2.1.2`int fun` vs `void fun` 的区别
**`int fun`**: – 这种函数会返回一个整数值 – 在函数体中通常包含 `return` 语句来返回结果 – 调用该函数时,可以将返回值赋给一个变量或用于表达式中
**`void fun`**: – 这种函数不返回任何值 – 函数执行完后不会向调用者传递数据 – 通常用于执行某些操作、打印输出等任务
2.1.3日常写代码什么时候加参数?什么时候加返回值?
看需求!
实际应用:以计算1+2+……+100为例编写代码test3-6,代码如下
//test3
#include <stdio.h>
void fun()
{
int sum=0;
for(int i = 1;i<=100;i++)
{
sum+=i;
}
printf("sum=%d\n",sum);
}
int main()
{
fun();
return 0;
}
//test4
#include <stdio.h>
int fun()
{ int sum=0;
for(int i=0;i<=100;i++)
{
sum+=i;
}
return sum;
}
int main()
{
int s=fun();
printf("sum=%d\n",s);
}
//test5
#include <stdio.h>
void fun(int n)
{
int sum =0;
for(int i=1;i<=n;i++)
{
sum+=i;
}
printf("sum=%d\n",sum);
}
int main()
{
fun(100);
return 0;
}//test6
#include <stdio.h>
int fun(int n)
{
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=i;
}
return sum;
}
int main()
{
int n =fun(100);
printf("%d\n",n);
}
运行结果
5050
2.2字符串

2.3虚拟内存地址
内存条、显卡、各种适配卡都有其各自的存储地址空间。
操作系统将这些设备的存储地址空间抽象成一个巨大的一维数组空间。
对于内存的每一个字节会分配一个32位或64位的编号,这个编号称为内存地址。

代码中变量地址是分配示例
int main
{
int a =10;//int4个字节
int b =5;
return 1;
}
2.4数组
2.4.1数组的定义
int main()
{
int a[]={16,47,89,42,38};
for (int i=0;i<5;i++)
{
printf ("%d\n",a[i]);
}
}
2.4.2获取数组地址
获取数组地址,其实是取数组第一个元素的地址
补充:&取地址符,%p输出地址
#include <stdio.h>
int main()
{
int a [] = {16,47,89,42,38};
printf("%p\n",a);
printf("%p\n",&a);//获取数组地址
printf("%p\n",&a[0]);//获取数组第一个元素的地址
printf("%p\n",&a[1]);//获取数组第二个元素的地址
return 0;
}
结果输出
00000000005FFE30
00000000005FFE30
00000000005FFE30
00000000005FFE342.4.3数组与sizeof
sizeof 函数可以获取变量字节长度
#include <stdio.h>
int main()
{
int a = 5;
printf("%zu\n",sizeof(a));//int4字节
printf("%zu\n",sizeof(int));
printf("%zu\n",sizeof(3.14));//double8字节
return 0;
}
结果
4
4
8可利用sizeof函数获取数组元素个数
#include <stdio.h>
int main()
{
int a[]={16, 17, 18, 19, 20};
for(int i=0;i<sizeof(a)/sizeof(a[0]);i++)
{
printf("%d\n",a[i]);
}
printf("数组大小%zu\n",sizeof(a));//获取数组大小
printf("数组元素大小%zu\n",sizeof(a[0]));//获取数组元素大小
printf("数组个数%d\n",sizeof(a)/sizeof(a[0]));//获取数组元素个数
return 0;
}
结果
16
17
18
19
20
数组大小20
数组元素大小4
数组个数52.5指针
C程序员新手和老手的其中之一差别在于是否对指针有深刻的理解、高效的使用指针。
理解指针的关键在于理解C程序如何管理内存。
2.5.1指针的定义
指针是用来存放内存地址的变量。

指针的使用

代码输出示例
#include <stdio.h>
int main()
{
int a=5;
int *p=&a;
printf("a的地址为:%p,a的值为%d\n",&a,a);
printf("p的地址为:%p,p的值为%p\n",&p,p);
return 0;
}
结果
a的地址为:00000000005FFE4C,a的值为5
p的地址为:00000000005FFE40,p的值为00000000005FFE4C//p存放的是a的地址2.5.2间接引用操作符
在指针定义外使用的*都为间接引用操作符

代码示例
#include <stdio.h>
int main()
{
int a=5;
int *p=&a;
printf("a的地址为:%p,a的值为%d\n",&a,a);
printf("p的地址为:%p,p的值为%p\n",&p,p);
printf("*p的为%d\n",*p);
//修改a的值
*p=10;
printf("a的修改后的值为%d\n",a);
return 0;
}
结果
a的地址为:00000000005FFE4C,a的值为5
p的地址为:00000000005FFE40,p的值为00000000005FFE4C
*p的为5
a的修改后的值为102.5.3指针与函数
示例1:设计一个函数,传入两个int参数,并交换这两个参数的值。
不使用指针
#include <stdio.h>
void swap(int a,int bn)
{
int temp;
temp = a;
a=b;
b=temp;
printf("a=%d,b=%d\n",a,b);
}
int main()
{
int m=10,n=20;
swap(m,n);
printf("m=%d,n=%d\n",m,n);
return 0;
}
结果
a=20,b=10
m=10,n=20使用指针
指针和地址可以简单理解为相互绑定的关系,提到指针就得想到地址,提到地址就得想到指针

#include <stdio.h>
void swap(int *a,int *b)//a和b为指针得传入地址
{
int temp;
temp = *a;
*a=*b;
*b=temp;
printf("a=%d,b=%d\n",*a,*b);
}
int main()
{
int m=10,n=20;
swap(&m,&n);
printf("m=%d,n=%d\n",m,n);
return 0;
}
结果
a=20,b=10
m=20,n=102.5.4指针与数组
在C语言中,指针与数组的关系十分密切。
通过数组下标能完成的操作都可以通过指针完成。
一般来说,用指针编写的程序比用数组下标编写的程序执行速度快。
案例
#include <stdio.h>
int main()
{
int a[] = {15, 20, 25, 30, 35};
int *p;
p =a;//数组可以直接赋给指针
printf("%p\n",a);
printf("%p\n",p);
printf("%d\n",*p);
}
结果
00000000005FFE30
00000000005FFE30
15给指针加上一个整数,实际上加的是这个整数和指针数据类型对应字节数的乘积
//案例遍历输出数组
#include <stdio.h>
int main()
{
int a[] = {15, 20, 25, 30, 35};
int *p;
p =a;//数组可以直接赋给指针
for(int i =0;i<sizeof(a)/sizeof(a[0]);i++)
{
printf("%d\n",a[i]);
}
for(int i =0;i<sizeof(a)/sizeof(a[0]);i++)
{
printf("%d\n",*(p+i));//指针p+1=p+1*4
}
结果
15
20
25
30
35
15
20
25
30
352.6结构体
2.6.1结构体的声明

2.6.2结构体的初始化和调用

示例代码
#include <stdio.h>
struct point
{
int x,y;
};
int main()
{
struct point p;
p.x=5;
p.y=10;
printf("x = %d, y = %d",p.x,p.y);
}
结果
x = 5, y = 102.6.4结构体构造函数
#include <stdio.h>
struct point//point是取的标签名可修改
{
int x;
int y;
};
struct point createPoint(int x,int y)
{
struct point temp;
temp.x=x;
temp.y=y;
return temp;
}
int main()
{
struct point p;
p=createPoint(10,20);
printf("(%d,%d)",p.x,p.y);
return 0;
}
结果
(10,20)2.6.5结构体与指针

#include <stdio.h>
struct test3
{
int x;
int y;
};
int main()
{
struct test3 t;
t.x = 10;
t.y = 20;
struct test3 *pp;
pp = &t;
/*
第二种写法
pp->x = 30; // 等价于 (*pp).x,是简写形式
pp->y = 40; // 专业代码都用这种写法
*/
(*pp).x = 30;
(*pp).y = 40;
printf("x = %d, y = %d\n", t.x, t.y);
printf("x = %d, y = %d\n", pp->x, pp->y);
return 0;
}
结果
x = 30, y = 40
x = 30, y = 402.7类型定义tepydef
2.7.1如何使用

#include <stdio.h>
typedef int myType;
typedef char myChar;
int main()
{
myType a = 10;
myChar b = 'a';
printf("a = %d\n", a);
printf("b = %c\n", b);
return 0;
}
结果
a = 10
b = a2.7.2定义结构体

#include <stdio.h>
typedef struct {
int a;
int b;
}s1;
int main()
{
s1 s;
s.a = 1;
s.b = 2;
printf("%d %d\n", s.a, s.b);
return 0;
}
结果
1 22.8动态内存分配
内存分类
C程序编译后,会以三种形式使用内存:
静态/全局内存
静态声明的变量和全局变量使用这部分内存,这些变量在程序开始运行时
分配,直到程序终才消失。
自动内存(栈内存)
函数内部声明的变量使用这部分内存,在函数被调用时才创建。
动态内存(堆内存)
根据需求编写代码动态分配内存,可以编写代码释放,内存中的内容直到
释放才消失。
| 特性 | int a; | int arr[10]; | malloc |
|---|---|---|---|
| 分配位置 | 栈区 | 栈区 | 堆区 |
| 大小 | 编译时固定 | 编译时固定 | 运行时确定 |
| 生命周期 | 随代码块结束 | 随代码块结束 | 手动控制 |
| 最大限制 | 栈空间小(几MB) | 栈空间小 | 堆空间大(几GB) |
| 灵活性 | 低 | 低 | 高 |
| 风险 | 无 | 无 | 内存泄漏/悬空指针 |
动态内存分配
在C语言中,动态分配内存的基本步聚:
1.使用malloc(memory allocate)
函数分配内存
void*malloc(size_t)
如果成功,会返回从堆内存上分配的内存指针
如果失败,会返回空指针
2.使用分配的内存
3.使用free函数释放内存
malloc函数
#include <stdlib.h> // 必须包含!
void* malloc(size_t size);| 部分 | 含义 |
|---|---|
返回值 void* | 返回申请到的内存起始地址,失败返回 NULL |
参数 size_t size | 需要申请的字节数 |
void* | 通用指针,需要强制转换成具体类型 |
示例1
基本数据类型
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int *p;
p = (int *) malloc (sizeof(int));
*p = 10;
printf ("%d\n", *p);
free (p);
return 0;
}
运行结果
10示例2:maloc/test1
字符串
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *str;
str = (char *)malloc(12 * sizeof(char)); // 分配12个字符的内存空间,足够容纳"Hello World"字符串和结束符'\0'
strcpy(str, "Hello World");
printf("%s\n", str);
free(str);
return 0;
}
运行结果
Hello World示例3:数组/test2.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *arr = (int *)malloc(sizeof(int) * 10);
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
for (int i = 0; i < 10; i++)
{
printf("%d\n", arr[i]);
}
}
运行结果
1
2
3
4
5
6
7
8
9示例4:结构体 /test3.c
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
}po;
int main()
{
po *p;
p=(po*)malloc(sizeof(po));
p->x=1;
p->y=2;
printf("%d %d",p->x,p->y);
return 0;
}
运行结果
1 2总结
初步了解的数据结构学什么内容,初步简略复习了c语言前置内容,可另外寻找资源详细学习
