首页 > 其他分享 >C语言学习笔记(八)指针详解

C语言学习笔记(八)指针详解

时间:2023-08-08 17:55:44浏览次数:34  
标签:10 arr int void C语言 char 详解 指针

指针详解

arr[i] = *(arr+i) = *(p+i) = p[i]

字符指针

char p*

int main()
{
	char ch = 'w';
	char* pc = &ch;
	return 0;
}
int main()
{
	char arr[] = "abcdefg";
	char* pc = arr;
	printf("%s\n",arr);
	printf("%s\n",pc);
	return 0;
}
//%s输出字符串形式,遇到字符指针会自动解引用,打印,直到遇到\0才结束打印
int mian()
{
	char* p = "abcde";//将字符串首字符的地址放到p里去了
	printf("%c\n",*p);//结果为a
	printf("%s\n",p);//结果为abcde; 
	return 0;
}

错误操作

int mian()
{
	char* p = "abcdef";//"abcdef"为常量字符串,后续无法对其进行更改
	*p = 'W';//不合规的操作,会造成段错误
	
	return 0;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	char* p1 = "abcdef";//常量字符串无法被修改
	char* p2 = "abcdef"//指针p2所指向的空间的内容为abcdef,即p1指针和p2指针一样
	if(arr1 == arr2)//此处比较的时两个数组的首元素的地址
	{
		printf("hehe\n");
	}
	else
	printf("haha\n");
    //结果打印haha
    if(p1 == p2)
    {
        printf("hehe");
	}
    else
        printf("haha");
    //此处打印hehe
	return 0;
}

注意!易错点:

char* p = "abc";
printf("%s\n",p);//打印的是p指针指向的地址之后的一串字符,遇到\0停止打印,所以结果为abc;
printf("%p\n",p);//打印的是p指针指向的内容的地址,即字符串abc的地址;
printf("%p\n",&p);//打印的是指针p本身自己的地址

指针数组

其实是数组

int arr[10] = {0};//整型数组
char ch[5] = { 0 };//字符数组
同理,指针数组是用来存放指针的
int* parr[4];//存放整型指针的数组,简称指针数组
char* pch[5];//存放字符指针的数组,也是指针数组
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int d = 40;
	int* arr[4] = {&a,&b,&c,&d};
	int i = 0;
	for(i=0;i<4;i++)
	{
		printf("%d ",*(arr[i]) );
	}
	return 0;
}
#include <stdio.h>
int main()
{
	int arr1[] = {1,2,3,4,5};
	int arr2[] = {2,3,4,5,6};
	int arr3[] = {3,4,5,6,7};
	int* parr[] = {arr1,arr2,arr3};//分别存储各数组的首元素的地址
    int i = 0;
    for(i=0;i<3;i++)
    {
        int j = 0;
        for(j=0;j<5;j++)
        {
           printf("%d ",*(parr[i]+j));//以prr[i]地址为起点,移动j个字节,每一组有5个字节,即每个arr[i]中间间隔五个字节
        }
        printf("\n");
    }
    //注意 整型指针数组打印采用循环嵌套,区别于之前字符指针%s会自动解引用
	return 0;
}

arr[0]:指第一行数字1的地址

arr[1]:指第二行数字2的地址

arr[2]:指第三行数字3的地址

数组指针

是指向数组的指针,可以存放数组的地址(指代表整个数组的地址,即&arr)

int arr[10] = {0};
int(*p)[10] = &arr;//先看*p,(原本[ ]的优先级高于*)即p是指针,再指向int [10],即指向一个数组。即此处的p是一个数组指针
//如果写成 int* p[10] = &arr,则此处p还是一个数组,而不是一个指针
int main()
{
	char* arr[5] = {0};
	char* (*pa)[5] = &arr;//数组中每一个指针元素的类型是char*
	return 0;
}

使用

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int (*pa)[10] = &arr;
	int i = 0;
	for(i=0;i<10;i++)
	{
		printf("%d ",(*pa)[i]);//(*pa) = arr
	}
	return 0;
}
int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int (*pa)[10] = &arr;
	int i = 0;
	for(i=0;i<10;i++)
	{
		printf("%d ",*(*pa+i);//  pa = &arr,*pa = arr
	}
	return 0;
}
int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int* p = arr;
	int i = 0;
	for(i=0;i<10;i++)
	{
		printf("%d ",*(p+i);//  *pa = arr
	}
	return 0;
}

正式使用

#include<stdio.h>
void print2(int(*p)[5],int x,int y)
{
    int i = 0;
    int j = 0;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("%d ",*(*(p+i)+j));//*(p+i)其实是第i行数组的数组名,代表该行首元素的地址(此时的首元素真的就是单个元素,而不再是一整个数组,因为此时第i行数组是一维数组)
            //printf("%d ",*(p[i]+j));
            //printf("%d ",p[i][j]);
        }
        printf("\n");
    }
}
int main()
{
    int arr[3][5] = {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
    print2(arr,3,5);//二维数组时arr代表首元素地址,即代表第一行的地址
    return 0;
}

数组指针解引用后得到的是数组名,即为该数组的首元素的地址!

数组参数、指针参数

一维数组传参

void test(int arr[])
{}
void test(int arr[10])
{}
void test(int* arr)//整型->指针
{}
-----------------------------------------------------------------------------------------------------------
void test2(int* arr2[])
{}
void test2(int* arr2[20])
void test2(int* *arr2)//指针->指针
----------------------------------------------------------------------------------------------------------
int main()
{
	int arr[10] = {0};
	int* arr2[20] = {0};//指针数组
	return 0;
}

二维数组传参

void test(int arr[3][5])
{}
void test(int arr[][5])//必须写列数,不可省略
{}
---------------------------------------------------------------------------------------------------------
void test3(int(*arr)[5])
int main()
{
	int arr[3][5] = {0};
	test(arr);//二维数组传参
    test3(arr);
	return 0;
}

一级指针传参

void test(int* p)
{}
int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int* p = arr;
	test(p);
	return 0;
}
void test1(int* p)
{}
//test1能接收什么类型的变量?
//一:test1(&a);
//二:int* pa=&a;test1(pa);

二级指针传参

void test(int** ptr)
{}
int main()
{
int n = 10;
int* p = &n;
int* *pp = &p;
test(pp);
test(&p);
}
void test(int** p)
{}
//test能接受什么类型的变量?
//int* ptr;test(&ptr);
//int** ptr;test(ptr);
//int* arr[10];test(arr);//arr是指针数组,arr代表首元素地址,首元素本身就是指针,所以arr是二级指针

函数指针

是存放函数地址的一个指针

int Add(int a,int b)
{
	int z = 0;
	z = a+b;
	return z;
}
int main()
{
	int x = 10;
	int y = 20;
	//printf("%d\n",Add(x,y));
	printf("%p\n",&Add);//注意此处没有括号!
	printf("%p\n",Add);
	//Add与&Add是一模一样的,都是函数的地址
    int(*pa)(int,int) = Add;//pa是指针,参数类型是int,int,函数的返回类型是int
    printf("%d\n",(*pa)(2,3));//对pa解引用,传入参数2,3,得到函数的运行结果
	return 0;
}
void Print(char* str)
{
	printf("%s\n",str);
}
int main()
{
	void(*p)(char*) = Print;//p即为函数指针//*p代表p为指针,()代表p指向函数,char*代表函数的参数类型,void代表函数的返回值类型
	(*p)("hello!");
	return 0;
}

注意:

以上代码中Print函数接受类型为char*是为了接收整个字符串的地址,这样后续才可以直接打印整个字符串。

因为char类型只能接收一个单个字符:

#include <stdio.h>
void Print(char str)
{
    printf("%c\n", str);
}
int main()
{
    void (*p)(char) = Print; // p即为函数指针
    (*p)('a'); // 传递字符 'h' 给函数指针
    return 0;
}

标签:10,arr,int,void,C语言,char,详解,指针
From: https://www.cnblogs.com/arongsec/p/17615030.html

相关文章

  • TCP/IP 详解
    第四章ARPARP为IP地址到对应的硬件地址之间提供动态映射RARP是被那些没有磁盘驱动器的系统使用(一般是无盘工作站或X终端),它需要系统管理员进行手工设置  ARP分组格式 ARP高速缓存ARP高效运行的关键是由于每个主机上都有一个ARP高速缓存。这个高速缓存存放了最近Inter......
  • LeetCode 16. 3Sum Closest 双指针+排序
    Givenanintegerarraynumsoflengthnandanintegertarget,findthreeintegersinnumssuchthatthesumisclosesttotarget.Returnthesumofthethreeintegers.Youmayassumethateachinputwouldhaveexactlyonesolution.Solution先将原数组排序,然......
  • C语言听课笔记
    %1f——double;%c——char;%p——&a;%s——char[]求两个数的较大值#include<stdio.h>int main(){ int num1=10; int num2=20; if (num1>num2)    printf("较大值是:%d\n",num1); else    printf("较大值是:%d\n",num2); return 0;}#include<stdio.h&......
  • 造船(并查集)思路详解
    造船题目描述:题目描述小Y想要在虚拟世界里造船。最开始m个船的完成度全部都为0。小Y第i时刻可以在a_i和b_i两艘船中选择一艘让这艘船的完成度。由于国家政府是奇数控,所以所有偶数完成度的船只都将被摧毁,小Y想知道m时刻后能剩下来的船只最多有多少艘。输入格式第一行两个......
  • json web token(jwt)详解
    1.jsonwebtoken是什么?JSONWebToken(JWT)是一个开放标准(RFC7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。 2.什么时候你应该用JSONWebTokens下列场景中使用JSONWebToken是......
  • 【C语言基础练习】
    学习来源:https://www.bilibili.com/video/BV1q54y1q79w/?spm_id_from=333.337.search-card.all.click1.判断一个数是否为奇数。#include<stdio.h>intmain(){ inta; printf("请输入需要判断的数字\n"); scanf_s("%d",&a); if(a%2==1) printf("奇数\......
  • 详解Jvm中时区设置方式,推荐 代码中TimeZone.getTimeZone("Asia/Shanghai") 而不使用Ti
    详解Jvm中时区设置方式原文链接:https://www.45fan.com/article.php?aid=20090934958860528675768691这篇文章memo一下Jvm中关于时区设定的基础操作。Java的时区设定这里列出如下三种方式方式说明TimeZone.setDefault方式通过java的utils下的TimeZone进行动态设定......
  • @Transactional(rollbackFor = Exception.class) 详解 推荐的事务注解方式 @Transact
    @Transactional(rollbackFor=Exception.class)详解原文链接:https://blog.csdn.net/weixin_43987718/article/details/12342262117、@Transactional(rollbackFor=Exception.class)详解1、参考来源:https://www.cnblogs.com/clwydjgs/p/9317849.html1)、异常是分为运行......
  • 一文详解TextBrewer
    本文分享自华为云社区《TextBrewer:融合并改进了NLP和CV中的多种知识蒸馏技术、提供便捷快速的知识蒸馏框架、提升模型的推理速度,减少内存占用》,作者:汀丶。TextBrewer是一个基于PyTorch的、为实现NLP中的知识蒸馏任务而设计的工具包,融合并改进了NLP和CV中的多种知识蒸馏技术,提供便......
  • C语言(不完善)
    C语言程序设计分支和循环语句C语句可分为以下五类:表达式语句、函数调用语句、控制语句、符合语句、空语句选择语句if语句如果表达式的结果为真,则语句执行。(0为假,非0为真)else的匹配:else是和它离的最近的if匹配的。语法结构:if(表达式){语句;}if(表达式){......