【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

这篇具有很好参考价值的文章主要介绍了【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

接着上次的函数的基本知识,今天我们来讲一讲🔍指针

目录

一、指针的概念

二、指针变量

三、野指针

四、字符指针

五、指针与数组

六、指针数组

七、数组指针

 八、指针与函数

总结


一、指针的概念

1.1、变量和地址

所谓指针,也就是内存的地址;所谓指针变量,也就是保存了内存地址的变量。

总结:指针就是变量,用指针存放地址(口语中说的指针通常指的是指针变量) 

1.2、指针变量和指针的类型

指针变量就是一个变量,它存储的内容是一个指针。在我们定义一个变量的时候,要确定它的类型。在定义指针变量时也是一样的,必须确定指针类型。int 变量的指针需要用 int 类型的指针存储,float 变量的指针需要用 float 类型的指针存储。

 指针类型决定了:指针解引用的权限有多大与指针走一步走多大字节(步长)

整型指针+1跳过一个整型。字符指针+1跳过一个字符

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


二、指针变量

2.1、指针变量的定义及使用

(1)指针变量的定义

指针变量的定义形式如:数据类型 *指针名;例如:

int* x;//整型指针变量
float* f;//浮点型指针变量
char* ch;//字符型指针变量

指针的变量名分别是:x;f和ch。而int*;float*与char*分别是他们中存储的数据的类型。 

(2)指针变量的使用

取地址运算符&:单目运算符&是用来取操作对象的地址。例:&i 为取变量 i 的地址。对于常量表达式、寄存器变量不能取地址(因为它们存储在存储器中,没有地址)。
指针运算符*(解引用运算符 ):与&为逆运算,作用是通过操作对象的地址,获取存储的内容。例:x = &i,x 为 i 的地址,*x 则为通过 i 的地址,获取 i 的内容。

//声明了一个普通变量 a
int a;
//声明一个指针变量,指向变量 a 的地址
int *pa;
//通过取地址符&,获取 a 的地址,赋值给指针变量
pa = &a;
//通过间接寻址符,获取指针指向的内容
printf("%d", *pa);

2.2、指针运算

(1)指针与整数的加减运算

指针变量的自增自减运算。指针加 1 或减 1 运算,表示指针向前或向后移动一个单元(不同类型的指针,单元长度不同)。

(2)指针减指针

前提是两个指针指向同一个空间。

指针减指针得到两个指针间的元素个数

例: Arr[9]指向9与10中间部分(下标)

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


三、野指针

3.1概念:

野指针就是指针指向的为止是不可知的(随机的,不正确的,没有明确限制的

3.2野指针的成因

(1)指针未初始化

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

(2)指针越界

如图:在第十次 访问时,可以进入到循环,相当于从第10个点向后访问4个字节,之后的字节不属于原数组,则越界了,则称为野指针。(只有在超出范围后,在会发生崩溃)

//越界访问
*int arr[10] ={ 0 };
int* p = arr;
int i=0;
for (i=0; i <= 10; i++)//共执行了11次,而arr数组总共只有10个元素
{
    *p = i;
    p++;
}

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

(3)指针指向的空间释放

int* test()//局部变量
{
    int a = 10;
    return &a;
}
int main()
{
    int *p=test();//返回值是a的地址,而局部变量在引用之后就会销毁。
    *p = 20;
    return 0;
}

3.3如何规避野指针

1.指针初始化 

2.小心指针越界。

3.指针指向空间释放即置NULL

4.指针使用之前检查有效性。


四、字符指针

4.1字符指针类型
在指针的类型中我们知道有一种指针类型为字符指针 char* ;
一般使用:
int main()
{
    const char* pstr = "hello ";//这里是把一个字符串放到pstr指针变量里了吗?
    printf("%s\n", pstr);
    return 0; }
本质是把字符串 hello首字符的地址放到了pstr中。

4.2例题

int main()
{
   char str1[] = "hello bit.";
   char str2[] = "hello bit.";
   const char *str3 = "hello bit.";
   const char *str4 = "hello bit.";
   if(str1 ==str2)
printf("str1 and str2 are same\n");
   else
printf("str1 and str2 are not same\n");
     
   if(str3 ==str4)
printf("str3 and str4 are same\n");
   else
printf("str3 and str4 are not same\n");
     
   return 0;
}

最终输出的结果是

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域。当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。
但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。

 


五、指针与数组

之前我们可以通过下标访问数组元素,学习了指针之后,我们可以通过指针访问数组的元素。在数组中,数组名即为该数组的首地址,结合上面指针和整数的加减,我们就可以实现指针访问数组元素。

5.1、指针与二维数组

(1)二维数组的地址

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p=a[0];//此处的p内存放的数组a第一行的地址。

5.2、多级指针

(1)多级指针(指向指针的指针)

指针变量作为一个变量也有自己的存储地址,而指向指针变量的存储地址就被称为指针的指针,即二级指针。依次叠加,就形成了多级指针。

指针变量也是一种变量,也会占用存储空间,也可以使用 &获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号 *。p1 是一级指针,指向普通类型的数据,定义时有一个 *;p2 是二级指针,指向一级指针 p1,定义时有两个*。例:假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


六、指针数组

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

1.parr的第一个数组里放arr1的首元素地址

2.parr每个元素的类型是int*

3.该数组里每个元素都是指针,所以它是一个指针数组

4.Parr[i][j],也可以写成parr[i]+j,

5.相当于地址+j为向后挨个元素指向


七、数组指针

7.1、数组指针的定义

如以下语句:

int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。
//所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

 7.2、&数组名与数组名

让我们看一段代码

#include <stdio.h>
int main()
{
 int arr[10] = { 0 };
 printf("arr = %p\n", arr);
 printf("&arr= %p\n", &arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr+1= %p\n", &arr+1);
 return 0; 
}

 运行结果如下

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。

实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。(细细体会一下)

本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型。

数组的地址+1,跳过整个数组的大小。

 7.3、数组指针的使用

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)//形参用数组来接受
{
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {
            printf("%d ", arr[i][j]);
       }}}
void print_arr2(int (*arr)[5], int row, int col)//形参用数组指针来接受  
 {
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {printf("%d ", arr[i][j]);}
        printf("\n");}}
int main()
{
   int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
   print_arr1(arr, 3, 5);
    //数组名arr,表示首元素的地址
    //但是二维数组的首元素是二维数组的第一行
    //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
    //可以数组指针来接收
    print_arr2(arr, 3, 5);
    return 0; }

 八、指针与函数

8.1、函数指针的定义  

returnType (*pointerName)(param list);
其中,returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。
注意( )的优先级高于*,第一个括号不能省略,如果写作returnType *pointerName(param list);就成了函数原型,它表明函数的返回值类型为returnType *。

8.2、指向函数的指针int (*pf[4])(int,int)={Add,Sub,Mul,Div};

函数指针数组,在函数指针的基础上,将指针变为指针数组

【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....


总结

以上就是初阶指针的基本内容了!!!!非常感谢你能看到这里!

如果你觉得你有些想法和我一样,想和我一起提升自己可以关注私信我,与我一起进步,一起共同努力!!!!!文章来源地址https://www.toymoban.com/news/detail-402522.html

到了这里,关于【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言初阶】带你轻松掌握指针基础知识完结篇——野指针,指针运算,指针和数组,二级指针

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,这里是君兮_,今天继续给大家更新0基础入门C语言的内容,我们这次主要更新的依然是初阶指针的基础知识 废话不多说咱们直接开始吧!! 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有

    2024年02月16日
    浏览(46)
  • C语言之指针篇【超详细讲解,带你层层深入理解指针】

    目录 一、关于指针 二、指针类型 1、整型指针的访问权限说明: 2、字符指针的访问权限说明: 3、指针的类型决定向前或向后一步走了多大距离 三、野指针相关知识 1、野指针的成因 ①指针未初始化 ②指针的越界访问 ③指针所指向的空间释放了 2、如何规避野指针 ①指针

    2024年02月02日
    浏览(38)
  • C语言/c++指针详细讲解【超详细】【由浅入深】

    指针,是内存单元的编号。 内存条分好多好多小单元,一个小单元有 8 位,可以存放 8 个 0 或 1;也就是说,内存的编号不是以位算的,而是以字节算的,不是一个 0 或 1 是一个编号,而是 8 个 0 或 1 合在一起是一个编号。这个编号,就是地址。 内存条就分为好多小格子,一

    2024年01月21日
    浏览(46)
  • 初始C语言(7)——详细讲解有关初阶指针的内容

     第一章 “C“浒传——初识C语言(1)(更适合初学者体质哦!)  第二章 初始C语言(2)——详细认识分支语句和循环语句以及他们的易错点   第三章 初阶C语言(3)——特别详细地介绍函数   第四章 初始C语言(4)——详细地讲解数组的内容以及易错点   第五章

    2024年02月11日
    浏览(36)
  • 【运维知识大神篇】超详细的ELFK日志分析教程10(kafka集群原理+基本使用+zookeeper和kafka堆内存调优+kafka监控和压力测试+filebeat和logstash对接kafka)

    本篇文章继续给大家介绍ELFK日志分析,我们先前介绍了ELFK架构,zookeeper部署使用,kafka的部署,仅差kafka使用就将整个体系融汇贯通了。我们本篇文章将以kafka为核心,详细介绍kafka使用,最终将kafka融入ELFK架构中,大致内容见下面目录。 目录 kafka集群原理 一、专业术语 二、

    2024年02月04日
    浏览(71)
  • Web数据库基本知识,SQL基本语法

    当我们谈论整个技术栈时,实际上涉及了一系列步骤,而在Web开发中,这些步骤可以被具体化为以下几个阶段: DBMS-GUI-翻译器-查询语言 在web中具体如下: postgreSQL-Hasura-Apollo+ts-GraphQL 具体解释 DBMS(数据库管理系统): 作用: 数据库管理系统允许我们直接使用SQL语言来操作数

    2024年02月03日
    浏览(49)
  • shell基本知识

    一、为什么学习和使用shell编程 二、什么是shell 系统当前支持的所有的shell: 三、shell的分类 为nologin,运行进程的,不允许登录系统,考虑系统安全性 用户名:密码的占位符:uid(用户的id):gid(用户所属基本组的id:关于账号的描述信息:用户家目录:当前用户与系统交

    2024年02月12日
    浏览(52)
  • c++ 基本知识(一)

    一、c++调用python #include cstdlib int main() {     int result = system(\\\"python your_script.py\\\");     return 0; } 二、cmake、make、gcc的区别? 1、CMake(Cross-Platform Make)是一个跨平台的构建工具,用于生成适合不同操作系统和编译器的构建脚本。它使用CMakeLists.txt文件来描述项目的构建过程,并根据

    2024年02月16日
    浏览(36)
  • Linux 基本知识

    FHS(Filesystem Hierarchy Standard)—— 文件系统层次化标准 。 Filesystem Hierarchy Standard(文件系统层次化标准)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系统中c盘的文件目录,FHS采用树形结构组织文件。FHS定义了系统中每个区域的用途、所需要的最小构成的

    2024年02月16日
    浏览(43)
  • 数学向量基本知识

    1.向量相关定义 2.向量的线性运算 3.向量积与数量积    向量积与数量积的区别 名称 标积/内积/数量积/点积 矢积/外积/向量积/叉积 运算式(a,b和c粗体字,表示向量) a·b=|a||b|·cosθ a×b=c,其中|c|=|a||b|·sinθ,c的方向遵守右手定则 几何意义 向量a在向量b方向上的投影与向

    2023年04月08日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包