c语言学习笔记——指针篇

指针

指针
#include<stdio.h>

int main()
{
    //利用指针获取数据
    int a = 10;
    //定义一个指针变量指向变量a
    int* p = &a;//这个*是一个指针标记和下方做区别
    printf("%d\n", *p);
    //*p中的*表示解地址
    *p = 200;//利用指针修改数据
    printf("%d\n", *p);
    
	return 0;
}
  • 指针变量名字是p
  • 指针数据类型要和指向变量的类型保持一致
  • 指针变量占用的大小,跟数据类型无关,跟编译器有关,32位的是4字节,64位是8字节
指针的作用
  • 操作其他函数中的变量
  • 函数返回多个值
  • 函数的结果和计算状态分开
#include<stdio.h>
void swap(int* num1, int* num2);

int main()
{
    //定义两个变量,交换变量中记录的值
    int a = 10;
    int b = 20;
    int* p1 = &a;
    int* p2 = &b;
    printf("%d, %d\n", a, b);
    swap(p1, p2);
    printf("%d, %d\n", a, b);

    return 0;
}
void swap(int* num1, int* num2)
{//如果用变量,只会传递a,b变量的值。
    int temp = *num1;
    *num1 = *num2;
    *num2 = temp;
}

指针作用细节

函数中变量的生命周期跟函数相关,函数结束,变量也会消失,此时在其他函数中,就无法通过指针使用。如果不想函数中的变量被回收,可以在变量前面加static关键字变成静态指针,也叫全局指针。

#include<stdio.h>

int main()
{
    int* p = method();
   	printf("time");
   	printf("%d\n", *p);//不能打印,method函数结束后,该函数里面所有的变量也会随之消失
	return 0;
}

int* method()
{
    int a = 10;//在前面加上static关键字就可以不被删除
    return &a;
}

作用二:返回多个数据

#include<stdio.h>

void getmax(int arr[], int len, int* max, int* min);

int main()
{
    //定义一个函数,求最大值和最小值
    int arr[] = { 1, 2, 3 };
    int len = sizeof(arr) / sizeof(int);
    int max = arr[0];
    int min = arr[0];
    getmax(arr, len, &max, &min);//函数传递max和min的地址
    printf("%d,%d", max, min);
    return 0;
}
void getmax(int arr[], int len, int* max, int* min)
{
    for (int i = 0; i < len; i++)
    {
        if (arr[i] > *max)
        {
            *max = arr[i];
        }
    }
    for (int i = 0; i < len; i++)
    {
        if (arr[i] < *min)
        {
            *min = arr[i];
        }
    }
}

作用三:函数结果和计算状态分开

#include<stdio.h>
int getreminder(int a, int b, int* res);

int main()
{
    //定义一个函数,求两个数的余数
    int a = 10;
    int b = 3;
    int res = 0;//定义一个数用于接受余数
    int flag = getreminder(a, b, &res);//传递参数只用传递res的地址
    if (!flag) 
    {
        printf("余数为:%d\n", res);
    }
    return 0;
}

int getreminder(int a, int b,int* res)//表示res是个指针变量
{
    if (b == 0)
    {
        return 1;
    }
    *res = a % b;//解引用res。改变res地址的值
    return 0;
}
野指针和空指针
#include<stdio.h>

int* method();
int main()
{
    //野指针,指向空间未分配
    int a = 10;
    int* p = &a;
    printf("%p\n", p);
    printf("%d\n", *p);
    int* p1 = p + 10;
    printf("%p\n", p1);
    printf("%d\n", *p1);
    //悬浮指针,指针地址空间已经被释放
    int* p2 = method();
    printf("asdf\n");//拖时间,如果没有这句,函数定义的局部变量还没有被释放
    printf("%p\n", p2);
    printf("%d\n", *p2);

    return 0;
}
int* method()
{
    int num = 10;
    int* p = &num;
    return p;
}
结果:
0116F72C
10
0116F754
23165464
asdf
0116F624
10098975
二级指针和多级指针
#include<stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	int* p = &a;
	//定义二级指针
	int** pp = &p;
	//作用一:利用二级指针修改一级指针里面记录的内存地址
	printf("%p\n", p);
	*pp = &b;
	//作用二:利用二级指针获取到变量中记录的数据
	printf("%p\n", &a);
	printf("%p\n", &b);
	printf("%p\n", p);
	printf("%d\n", **pp);

	return 0;
}
结果:
008FFD98
008FFD98
008FFD8C
008FFD8C
20
数组指针
#include<stdio.h>

int main()
{
	int arr[] = { 10,20,30,29,32 };
	int len = sizeof(arr) / sizeof(int);
	//获取数组指针
	// 实际上获取的数组首地址
	int* p1 = arr;
	int* p2 = &arr[0];
	for (int i = 0; i < len; i++) {
		printf("%d\n", *p1);
		p1++;
		//或者表达为一行printf("%d\n", *p1++);
		
	}
	

	return 0;
}

结果:

10
20
30
29
32

数组指针细节

arr参与计算的时候,会退化为第一个元素的指针

特殊情况,利用sizeof计算整个数组大小时候,不会退化,arr还是整体。

二维数组
两种定义方式
遍历

用索引遍历第一种二维数组

#include<stdio.h>

int main()
{
	//定义二维数组
	int arr[3][5] = {
		{1,2,3,4,5},
		{11,22,33,44,55},
		{12,23,43,54,15},
	};
	//利用索引方式进行遍历
	//arr[0]:表示二维数组中的第一个一维数组,{1,2,3,4,5}
	//arr[1]:表示二维数组中的第二个一维数组,{11,22,33,44,55}
	//arr[2]:表示二维数组中的第三个一维数组,{12,23,43,54,15}

	for (int i = 0; i < 3; i++) 
	{
		//依次表示二维数组中的索引
		for (int j = 0; j < 5; j++)
		{
			//j:依次表示一位数组中的索引
			//内循环:遍历每一个一维数组
			printf("%d ", arr[i][j]);
		}
		//当内循环结束之后,表示一维数组遍历完成
		printf("\n");
	}
	

	return 0;
}

遍历第二种索引

#include<stdio.h>

int main()
{
	//第二种方法定义二维数组
	int arr1[] = { 1,2,3 };
	int arr2[] = { 2,12,13,14 };
	int arr3[] = { 1,321,312,32,24,42 };
	int* arr[3] = { arr1,arr2,arr3 };//存入的是三个一维数组的地址
	//利用索引方式进行遍历
	//再定义一个数组,存所有数组长度
	int len1 = sizeof(arr1) / sizeof(int);
	int len2 = sizeof(arr2) / sizeof(int);
	int len3 = sizeof(arr3) / sizeof(int);

	int lenArr[3] = { len1,len2,len3 };
	for (int i = 0; i < 3; i++) 
	{
		//依次表示二维数组中的索引
		for (int j = 0; j < lenArr[i]; j++)
		{
			//j:依次表示一位数组中的索引
			//内循环:遍历每一个一维数组
			printf("%d ", arr[i][j]);
		}
		//当内循环结束之后,表示一维数组遍历完成
		printf("\n");
	}
	

	return 0;
}
函数指针
#include<stdio.h>

void method1();
int method2(int a, int b);

int main()
{
	//函数指针
	//定义指针指向两个函数
	void (*p1)() = method1;
	int (*p2)(int, int) = method2;
	//利用函数指针调用函数
	p1();
	int nu = p2(1, 2);
	printf("%d\n", nu);
	return 0;
}

void method1()
{
	printf("method1\n");
}
int method2(int a, int b)
{
	printf("method2\n");
	int num = a + b;
	return num;
}

结果

method1
method2
3
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值