vf
使用指针接收数组
#include<stdio.h>
//定义功能函数1
void func_1(int brr[], int n)
{
printf("sizeof(brr) = %ld\n", sizeof(brr)); //8
brr++; //对指针进行重新赋值
//从上面两个现象说明,brr本质上不是数组,而是一个指针变量
for(int i=0; i<n; i++)
{
brr[i] += 10; // *(brr+i) += 10;
}
}
//定义功能函数2
void func_2(int *ptr, int n)
{
for(int i=0; i<n; i++)
{
ptr[i] += 10; // *(ptr+i) += 10;
}
ptr++;
}
/***************主程序******************/
int main(int argc, const char *argv[])
{
int arr[5] = {3,2,7,6,8};
//调用函数,将数组地址传入,在被调函数中对数组进行操作
func_1(arr, 5);
//输出数组
printf("arr中元素分别是:");
for(int i=0; i<5; i++)
{
printf("%d\t", arr[i]);
}
printf("\n");
return 0;
}
指针变量与字符串的关系
1."hello world":字符类型的数组类型,本质是第一个字符的地址
520:是一个整数类型
'A':是一个小数类型
3.14:是一个实数类型
2.既然字符串的本质,是一个地址,那么就可以使用一个指针变量存储该地址
char *ptr = "hello world";
3.字符数组也可以存储字符串,两者的区别在于
使用字符数组存储一个字符串,是单独申请了一个数组的空间,将字符串常量复制到该空间中,操作字符数组,其实是操作的复制后的字符串,而并不是该字符串常量
使用指针指向字符串,并不是用指针变量存储字符串,而是将指针指向字符串常量的起始地址。指针对字符串整体只能有只读的权限,不能更改字符串中的内容。

#include<stdio.h>
int main(int argc, const char *argv[])
{
printf("sizeof(520) = %ld\n", sizeof(520)); //4
printf("sizeof(5.20) = %ld\n", sizeof(5.20)); //8
printf("sizeof('A') = %ld\n", sizeof('A')); //4
printf("sizeof(\"52000\") = %ld\n", sizeof("52000")); //?
char str[128] = "52000"; //定义一个数组存储字符串,将字符串起始地址放入第一个位置
//定义一个指针指向字符串
char *ptr = "hello world";
printf("str = %s, ptr = %s\n", str, ptr); //都能输出字符串
/*
str[2] = 'A'; //这是对数组中的某个变量进行更改
printf("11111111111111111111\n");
ptr[2] = 'K'; //错误 这是对常量区的数据进行更改
//指针指向字符串时,具有只读的属性
printf("2222222222222222222\n");
*/
//str = "I love China"; //? 字符数组名是一个地址常量,是一个右值
strcpy(str, "kkk"); //字符数组只能使用字符串处理函数完成重新赋值
ptr = "I love China"; //指针变量,可以直接指向其他的字符串
printf("str = %s, ptr = %s\n", str, ptr); //都能输出字符串
// strcpy(ptr, "I love you"); //不能进行该操作
strcpy(str, ptr); //可以被读取
//指针被赋值字符串常量
char *qtr = "hao \0 you";
printf("qtr = %s, sizeof(qtr) = %ld\n", qtr, sizeof(qtr)); //? hao 8
char s[] = "hao \0 you";
printf("s = %s, sizeof(s)=%ld\n", s, sizeof(s)); // hao 10
return 0;
}
字符数组接收字符串
#include<stdio.h>
#include<string.h>
//使用数组名进行接收
void fun1(char s[])
{
char s1[128] = "";
for(int i=0; i<strlen(s); i++)
{
s1[i] = s[i];
}
printf("s1 = %s\n", s1);
/*
for(int i=0; i<strlen(s); i++)
{
s[i] += 1; //将每个字符进行自增
}
*/
}
/******************主程序**************/
int main(int argc, const char *argv[])
{
char s1[] = "hello a";
//调用函数,完成将字符串中的内容进行更改
fun1(s1);
printf("s1 = %s\n", s1);
//调用函数传入字符串
fun1("hello a"); //?
return 0;
}
指针函数
1> 指针函数本质上是一个函数,返回值为指针的函数就称为指针函数
2> 指针函数调用的结果是一个 左值
3> 指针函数返回的必须是一个生命周期比较长的空间的地址。不能返回局部空间的地址。
1、全局变量的空间
2、静态变量的空间
3、堆区申请的空间
4、主调函数以地址传递传过来的空间
4> 指针函数实现了将被调函数中的内存传递给主调函数使用
5> 定义格式: 返回值类型 * 函数名(参数列表){函数体; return 地址;}
返回静态局部变量的地址
#include<stdio.h>
//定义功能函数1:实现将传递的数据,加10后的结果返回
int fun_1(int m)
{
int s = m+10;
return s; //值返回
}
//定义函数返回函数体内的空间
int * fun_2()
{
/*
int s = 666; //定义一个局部变量
return &s; //不能返回局部变量的地址
*/
static int s = 666; //定义一个静态局部变量
return &s; //返回静态局部变量的地址
}
/***************主程序********************/
int main(int argc, const char *argv[])
{
int num = 520;
//调用功能函数1
int res = fun_1(num); //值返回的函数做右值 只读
printf("res = %d\n", res); //? 530
printf("结果为:%d\n", fun_1(num)); //530
//fun_1(num) = 1314; //值返回的函数不能作为左值
//定义指针变量,接受函数返回的地址
int * ptr = fun_2();
printf("*ptr = %d\n", *ptr); //666
*fun_2() = 777; //指针函数的返回结果是一个左值
printf("*ptr = %d\n", *ptr); //777
return 0;
}
指针函数不能返回局部变量的地址
#include<stdio.h>
//定义指针函数,返回传入的主调函数中的空间的地址
int *fun(int *ptr)
{
//对传入的指针进行内容的操作
*ptr = 1314;
return ptr; //此时返回的就是传入的地址
}
/*****************************主程序***********************/
int main(int argc, const char *argv[])
{
char s1[128] = "hello";
char s2[128] = "world";
printf("s1 = %p, s2 = %p\n", s1, s2); //&s1[0] &s2[0]
printf("%p %p\n", "hello", "world"); //输出的是字符串的地址
char * ptr = strcpy(s1, s2); //调用指针函数 此时该函数返回的是传入的变量的地址
printf("s1 = %p, s2 = %p, ptr = %p\n", s1, s2, ptr); //&s1[0] &s2[0]
printf("*******************************************\n");
int num = 520; //在主函数中申请一个4字节的空间
int *qtr = fun(&num); //将主程序中的变量地址传入
printf("num = %d\n", num); //1314
printf("*qtr = %d\n", *qtr); //1314
printf("&num = %p, qtr = %p\n", &num, qtr);
return 0;
}
函数指针
1> 函数指针本质上是一个指针。用于指向函数入口地址的一个指针
任何函数在被调用时,系统都会为其分运行空间,既然有空间,就有该空间的地址,既然是地址,就可以定义相关的指针变量存储。存储函数运行空间入口地址的指针变量,称为函数指针变量
2> 任何一个函数的函数名,都是该函数对应的入口地址,是一个地址常量
3> 函数指针定义格式: 返回值类型 (* 变量名)(参数列表);
4> 函数指针变量的用法:跟函数名用法一致
#include<stdio.h>
//定义两数求和函数
int sum(int m, int n)
{
return m+n;
}
//定义判断一个数是否为偶数 结果为1表示偶数,为0表示奇数
int judge(int m)
{
return m%2==0 ? 1:0;
}
//定义一个冒泡排序函数
void sort(int *arr, int n)
{
for(int i=1; i<n; i++)
{
for(int j=0; j<n-i; j++)
{
if(arr[j]>arr[j+1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
printf("排序成功\n");
}
int main(int argc, const char *argv[])
{
printf("%p, %p, %p\n", sum, judge, sort); //三个函数的地址
//定义指针存储上面三个地址
int (*sum_ptr)(int, int) = sum; //定义求和函数的指针变量并初始化
int (*judge_ptr)(int) = NULL; //定义了一个返回值类型为int,并有一个int类型的参数的指针变量
judge_ptr = judge; //给指针变量赋值
void (*sort_ptr)(int *, int) = NULL; //表示定义了一个无返回值且第一个参数为int×,第二个参数为int的指针变量
sort_ptr = sort;
//调用求和函数
printf("和为:%d\n", sum(3,7)); //10
printf("和为:%d\n", sum_ptr(3,7)); //10
//调用判断奇数偶数函数
if(judge(56)==1)
{
printf("偶数\n");
}else
{
printf("奇数\n");
}
if(judge_ptr(56)==1)
{
printf("偶数\n");
}else
{
printf("奇数\n");
}
return 0;
}
使用函数指针完成函数回调(回调函数)
函数回调:当调用某个函数时,不仅要向该函数中传递数据参数,也可以向该函数中传入一个功能。在该函数的函数体内,调用传入的功能。
#include<stdio.h>
//定义求和函数
int he(int m, int n)
{
return m+n;
}
//定义求差函数
int cha(int m, int n)
{
return m-n;
}
//定义求乘积函数
int ji(int m, int n)
{
return m*n;
}
//定义计算函数
void calculate(int m, int n, int (*ptr)(int, int))
{
int res = ptr(m, n); //调用传入的功能,完成计算
printf("结果为:%d\n", res);
}
int main(int argc, const char *argv[])
{
int num = 3;
int key = 6;
//调用一个函数,求出指定的运算并输出结果
calculate(num, key, he); //求出两个数的和并输出
calculate(num, key, cha); //求出两个数的差并输出
calculate(num, key, ji); //求出两个数的乘积并输出
return 0;
}
数组指针
1.数组指针的本质也是一个指针,记录的是整个数组的地址
数组指针针对的是整个数组,每偏移一个单位,内存地址就偏移了整个数组的大小
2.数组指针的定义格式: 数据类型 (*指针名)[数组长度];
3.数组指针与一维数组关系
数组名表示的是第一个元素的地址 ---> 变量的地址
对一维数组名,再取地址,就得到了当前数组的地址(数组的地址)
#include<stdio.h>
int main(int argc, const char *argv[])
{
int arr[5] = {4,7,2,8,1}; //定义了一个长度为5的数组
int *ptr = arr; //普通元素的地址
//定义一个指针变量,存储整个数组的地址
int (*arr_ptr)[5] = NULL; //定义一个数组指针
arr_ptr = &arr; //将数组指针指向整个数组 *arr_ptr = *&arr
printf("sizeof(arr) = %ld\n", sizeof(arr)); //20
printf("ptr = %p,arr=%p, &arr[0]=%p, &arr = %p,arr_ptr=%p\n",\
ptr, arr, &arr[0], &arr, arr_ptr);
printf("ptr+1 = %p,arr+1=%p, &arr[0]+1=%p, &arr+1 = %p, arr_ptr+1=%p\n",\
ptr+1, arr+1, &arr[0]+1, &arr+1, arr_ptr+1);
//使用数组指针访问元素
printf("数组元素分别是:");
for(int i=0; i<5; i++)
{
//printf("%d\t", (*arr_ptr)[i]); // *arr_ptr ==> *(arr_ptr+0) ==> arr[0]
printf("%d\t", arr_ptr[0][i]); // *arr_ptr ==> *(arr_ptr+0) ==> arr[0]
}
//常考题目
arr_ptr++; //偏移整个数组
int *tt = (int *)arr_ptr;
tt--; //偏移一个元素
printf("*tt = %d\n", *tt); //1
return 0;
}
指针数组
1.本质是一个数组,但每个元素都是一个指针变量1
2.数据类型 * 数组名[数组长度]
#include<stdio.h>
//定义输出和的函数
void sum(int m, int n)
{
printf("和为:%d\n", m+n);
}
//定义给定两个数据,并输出
void output(int m, int n)
{
printf("m = %d, n = %d\n", m, n);
}
//定义给定两个数据,输出最大值
void max(int m, int n)
{
m>n? printf("%d\n", m) : printf("%d\n", n);
}
// 函数指针类型 void (*fun_ptr)(int, int)
int main(int argc, const char *argv[])
{
//定义三个函数指针存储上面三个函数
void (* fun_ptr_arr[3] )(int, int) = {sum, output, max}; //定义了三个函数指针变量
/*
fun_ptr_arr[0] = sum;
fun_ptr_arr[1] = output;
fun_ptr_arr[2] = max;
*/
//批量调用函数
for(int i=0; i<3; i++)
{
fun_ptr_arr[i](4,7);
}
return 0;
}
函数指针数组
1> 本质上是一个数组,数组中的每个元素都是一个 函数指针变量, 都可以存储函数入口地址
2> 能够实现对函数的批量调用
3> 定义格式: 返回值类型 (* 数组名[数组长度])(形参列表);
#include<stdio.h>
//定义输出和的函数
void sum(int m, int n)
{
printf("和为:%d\n", m+n);
}
//定义给定两个数据,并输出
void output(int m, int n)
{
printf("m = %d, n = %d\n", m, n);
}
//定义给定两个数据,输出最大值
void max(int m, int n)
{
m>n? printf("%d\n", m) : printf("%d\n", n);
}
// 函数指针类型 void (*fun_ptr)(int, int)
int main(int argc, const char *argv[])
{
//定义三个函数指针存储上面三个函数
void (* fun_ptr_arr[3] )(int, int) = {sum, output, max}; //定义了三个函数指针变量
/*
fun_ptr_arr[0] = sum;
fun_ptr_arr[1] = output;
fun_ptr_arr[2] = max;
*/
//批量调用函数
for(int i=0; i<3; i++)
{
fun_ptr_arr[i](4,7);
}
return 0;
}
二级指针
1> 由于指针变量也是占内存地址的,每个指针变量用于8字节的内存空间,有空间就有地址,有地址就有起始地址,就可以定义指针变量来存储
2> 存储一级指针变量的地址的变量称为二级指针变量
一级指针变量的地址称为二级指针
3> 二级指针变量的定义格式: 数据类型 ** 指针名;
4> 二级指针变量的值:一级指针变量的地址
二级指针指向的内存空间中的值是一级指针的值(也就是变量的地址) ---> * 二级指针变量
二级指针取两次值,就得到了变量的值 ---> ** 二级指针变量
#include<stdio.h>
int main(int argc, const char *argv[])
{
int num = 520; //内存中申请了4字节存储数据
int *ptr = # //定义指针变量存储该num的地址,该变量8字节
//long int *qtr = &ptr; //定义一级指针存储指针变量的地址
int **qtr = &ptr; //定义二级指针变量存储
printf("*qtr = %p, ptr = %p, &num = %p\n", *qtr, ptr, &num);
printf("**qtr = %d, *ptr = %d, *&num = %d\n", **qtr, *ptr, *&num);
return 0;
}
万能指针
1> 所谓万能指针,就是可以接收任意地址的指针变量
2> 定义格式: void * 指针名;
3> 由于没有任何类型的限制,导致该指针变量可以接收任意类型的地址
4> 对于万能指针而言,不能直接 取值运算,必须转化成指定的类型的指针进行解析
5> 万能指针常用于函数的形参,表示能够接收任意类型的地址

2240

被折叠的 条评论
为什么被折叠?



