C语言第八章,链表

#define _CRT_SECURE_NO_WARNINGS//所有代码之前都要写一个这个

第八章 指针

概念

指针:就是地址

&变量名:获取该变量的地址(指针),&称为取地址符,%p:输出地址(指针),以十六进制输出

指针变量:保存指针(地址)的变量,(int 型指针变量)

int *p=&a;//一个int型的地址赋值给int指针变量,定义

p=&b,跟上面一个意思,使用

/*char c;

* char *p1=&c;

* double d;

* double *p2=&d;指针类型必须匹配

* *p的含义访问p所指向的变量,解引用,间接访问符

* 输出p和&p含义不同,前者输出指向变量的地址,后者输出p自己的地址

而*p输出的是所指变量的内容

p里的内容是a的地址,p指向的内容是a的内容

*/

用指针加函数交换两个数的值

#include<stdio.h>

void Swap(int* p1, int* p2) {

int temp;

temp = *p1;//交换的是数不是地址,*p才是指向数

*p1 = *p2;

*p2 = temp;

}

int main() {

/*int a, b;

scanf("%d%d", &a, &b);

Swap(&a, &b);

printf("%d %d", a, b);

return 0;*/

int a, b;

int* p1=&a, * p2=&b;//把地址给人家,这步很重要,先加上人家微信啊

scanf("%d%d", p1, p2);

Swap(p1, p2);//传的是a,b的地址

printf("%d %d\n", a, b);

printf("%d %d", *p1, *p2);//两种输出方式都对

return 0;

}

c语言只能返回0个或1个值

用指针解决多个返回值

指针求方程的根

#include<stdio.h>

#include<math.h>

int Fun(int a, int b, int c, double* x1, double* x2) {

int d = b * b - 4 * a * c;

*x1 = (-b + sqrt(d)) / (2 * a);//*x1才是指数

*x2 = (-b - sqrt(d)) / (2 * a);

return 2;//两个根

}

int main() {

double x1, x2;

Fun(3, 5, 1, &x1, &x2);//传地址

printf("%lf %lf", x1, x2);

return 0;

}

指针指向数组

int *p=&arr[0] 等于 int*p=arr//都是指向第一个元素的地址

用指针输出一个数组

#include<stdio.h>

int main() {

int arr[] = { 1,3,5,7 };

int n = sizeof(arr) / sizeof(arr[0]);//求数组长度

//从前往后输出

//int* p = &arr[0];//指针指向数组的第一个地址

//for (int i = 0; i < n; i++) {

// printf("%d ", *p);//输出指针指向的内容

// //printf("%d ",*(p+i));//这么写也行,但我觉得还是地址往后走比较好理解

// p++;//地址往后走一位

//}

//从后往前输出

int* p = &arr[n - 1];

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

printf("%d ", *p);

p--;

}

return 0;

}

指针的关系运算,前提必须在同一个数组,>,<等,两个单独的变量或两个不同的数组不可以比较大小

从头到尾输出数组

#include<stdio.h>

int main() {

//int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

//指针输入

int arr[10];

int* p = &arr[0];

//int*p=arr;(同理)

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

scanf("%d", p);

p++;

}

p = &arr[0];//重新回到第一个元素位置

//p=arr;同理

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

printf("%d ", *p);

p++;

}

//for (int* p = arr; p != &arr[10]; p++) {//就是10,这叫尾后指针

// printf("%d ", *p);

//}

或者

//for (int* p = arr; p < &arr[10]; p++) {//就是10,这叫尾后指针

// printf("%d ", *p);

//}

return 0;

}

数组作为参数传递,数组名仅仅只是表示数组首元素的地址

传数组要加长度

传整个数组到函数中

#include<stdio.h>

void Show(int* p, int n) {

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

printf("%d ", *p);

//高级版本

//printf("%d", p[i]);//这么写有点6

p++;

}

}

int main() {

int arr[] = { 1,2,3,5 };

int n = sizeof(arr) / sizeof(arr[0]);

Show(arr,n);

return 0;

}

将数组中的n个整数按相反顺序存放

数组,函数,指针,他们仨才是真玩,跟别人都是假玩

#include<stdio.h>

void Inv(int* p, int n) {

int temp;

for (int i = 0, j = n - 1; i < j; i++, j--) {//一个指前一个指后,错位则停止

temp = p[i];

p[i] = p[j];

p[j] = temp;

//用指针的方式写

/*temp = *(p+i);

*(p+i) = *(p+j);

*(p+j) = temp;*/

}

}

void Show(int* p, int n) {//输出交换后的结果

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

printf("%d ", *p);

p++;

}

}

int main() {

int arr[] = { 1,2,3,4,5,6 };

int n = sizeof(arr) / sizeof(arr[0]);

Inv(arr, n);//传的是首地址和长度

Show(arr, n);//同上

return 0;

}

用指针法对十个整数选择法从大到小排序

找到最大的数与最左边交换

#include<stdio.h>

void Pai(int* p, int n) {

//用数组下标做其实更好,道理都一样,写成数组形式就可以了

int i, j;

int index;

int temp;

for (i = 0; i < n - 1; i++) {

index = i;

for (j = i + 1; j < n; j++) {

if (*(p + index) < *(p + j)) {//看好了跟谁比,不是ij比,很重要,但我不明白为啥i不行

index = j;//道理我懂,但我想不通i也是最左边的数啊,也没变过啊

}

}

if (index != i) {//最小的下标变了则交换数

temp = *(p + i);

*(p + i) = *(p + index);

*(p + index) = temp;

}

}

}

void Show(int* p, int n) {

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

printf("%d ", *p);

p++;

}

}

int main() {

int arr[] = { 11,96,48,63,5,4,69,74,56 };

int n = sizeof(arr) / sizeof(arr[0]);

Pai(arr, n);

Show(arr, n);

return 0;

}

通过指针引用多维数组

#include<stdio.h>

int main() {

int arr[3][4];

int(*p)[4] = arr;//3行4列 /*1*/

int* p2 = arr[0]; /*2*/

p = arr + 1;//加一类型不改变 /*3*/

p2 = arr[0] + 1; /*4*/

int x = arr[0][0]; /*5*/

x = arr[0][0] + 1; /*6*/

return 0;//13,24,56三种不同的类型

}

调用函数,输出二维数组

#include<stdio.h>

void Show(int(*p)[4]) {//这个类型记好

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

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

printf("%d ", p[i][j]);

}

printf("\n");

}

}

int main() {

int arr[3][4] = { 1,2,3,4,5 };//后面会自己补0

Show(arr);

}

通过指针引用字符串

const:不允许修改(其修饰的)内容

const 只能修饰直接右边,eg:const int *p; p可以变,*p不可以

用函数调用实现字符串的复制

字符串和普通数组的区别:字符串可以通过'\0'判断结尾,所以字符串不需要传长度

#include<stdio.h>

#include<string.h>

void Mystrcpy(const char* first, char*end) {//const加不加都可以,加了之后不能修改他的值

int i; //其实就是相当于粘贴而不是剪切

for (i = 0; first[i] != '\0'; i++) {//字符串结束标志'\0'

end[i] = first[i];

}

end[i] = '\0';//给结尾加个末尾标识符,必须加,要不然会输出后面的未赋值的数

}

int main() {

char arr[10] = "abcde";

char brr[10];

Mystrcpy(arr, brr);

//strcpy(brr, arr);(直接用人家写好的就行,把后面的赋值给前面的,加个头文件)

printf("%s", brr);//字符串%s输出就行

return 0;

}

指向函数的指针

函数名相当于函数地址 Max=&Max

#include<stdio.h>

int Max(int a, int b) {

return a >= b ? a : b;//公式,求最大值的意思

}

int main() {

int(*pfun)(int, int);//pfun是指针,函数参数为int,int

pfun = Max;

pfun = &Max;//与上一句同含义

int a, b;

scanf("%d%d", &a, &b);

printf("%d", pfun(a, b));

return 0;

}

指向函数的指针排序,整的挺复杂的,正经复杂

#include<stdio.h>

#include<stdlib.h>

int Cmp_int(const void* vp1, const void* vp2) {//如果是>0,返回前面,<0返回后面

return *(int*)vp1 - *(int*)vp2;//还原本质

}

int Cmp_double(const void* vp1, const void* vp2) {//必须是int型

double tmp= *(double*)vp1 - *(double*)vp2;//因为返回int型,所以要分情况讨论

if (tmp > 0) {

return 1;

}

else if (tmp < 0) {

return -1;

}

else {

return 0;

}

}

int main() {

int str[] = { 2,65,3,8,96 };

double str2[] = { 34.2,34.3,34.4,65.9 };

int len = sizeof(str) / sizeof(str[0]);

int len2 = sizeof(str2) / sizeof(str2[0]);

qsort(str, len, sizeof(str[0]), Cmp_int);//排序函数四个参数:数组,长度,单个元素长度,比较标准

qsort(str2, len2, sizeof(str2[0]), Cmp_double);

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

printf("%d ", str[i]);

}

printf("\n");

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

printf("%lf ", str2[i]);

}

return 0;

}

#include<stdio.h>

#include<stdlib.h>

int main() {

动态内存分配:数组里的容量<1024*1024=1M,很小

void*:没有类型信息的指针,仅仅是记录地址

使用场景:1.需要大容量内容2.在一个函数创建的内存在别的函数中还需要使用时

malloc:创建内存,需引用stdlib.h,失败返回NULL,成功返回地址

/* *void *p=malloc(1024*1024*10);

* if (p == NULL) {

*printf("申请失败了");

}

*printf("给一个地址");

*/

/*calloc:创建内存,参数有长度和大小,会把每个元素初始化为0

int* arr = (*int)calloc(n, sizeof(int));//100个整型单元

for (int i; i < n; i++) {

arr[i] = i;

}

*/

/* realloc:修改动态内存大小

int n = 10;

int* arr = (int*)malloc(n*sizeof(int));

arr = (int*)realloc(arr, 2 * n * sizeof(int));

for (int i = 0; i < 2 * n; i++) {

arr[i] = i;

}*/

free:释放内存,动态内存申请,用完要释放掉,要不然内存泄漏,可用的内存越来越少,v变慢

return 0;

}

相关推荐
DdddJMs__13512 分钟前
C语言 | Leetcode C语言题解之第517题超级洗衣机
c语言·leetcode·题解
边疆.20 分钟前
C++类和对象 (中)
c语言·开发语言·c++·算法
binqian32 分钟前
【K8S】kubernetes-dashboard.yaml
算法·贪心算法
林浔090633 分钟前
C语言部分输入输出(printf函数与scanf函数,getchar与putchar详解,使用Linux ubuntu)
c语言·开发语言
Wils0nEdwards1 小时前
Leetcode 合并 K 个升序链表
算法·leetcode·链表
Tisfy1 小时前
LeetCode 3211.生成不含相邻零的二进制字符串:二进制枚举+位运算优化
算法·leetcode·二进制·题解·枚举·位运算
好看资源平台1 小时前
深入理解所有权与借用——借用与生命周期管理
开发语言·算法·rust
qiaoxinyu19892 小时前
线性代数(1)——线性方程组的几何意义
线性代数·算法·机器学习
blessing。。2 小时前
__attribute__ ((__packed__))
linux·c语言·arm开发
爱吃饭团的饭桶2 小时前
【附源码】Python :哈密顿回路
开发语言·python·算法