C语言超详细讲解指针的使用

目录
  • 指针概述
    • 自身类型
    • 指向类型
  • 代码例子
  • 数值型指针
  • 字符型指针
    • 单字符
    • 字符数组
  • 字符串型指针
  • 字符数组总结

指针概述

C语言中指针也可以认为是一种类型,不同于数值型和字符型的类型。推演过去指针变量也就是相当于不同的变量类型,不同于数值变量、字符型变量、字符串变量。

指针变量两种类型:自身类型和指向的类型

自身类型:将变量名去掉,剩下的就是指针变量类型。

指向类型:将变量名和离它最近的一个*去掉,剩下的类型就是指针指向的类型

int num = 10;
int* p = NULL;
p = #

如代码中 指针变量的自身类型是 int * 型;指向类型是 int 型。

自身类型

自身类型是指变量p本身的类型,变量p中放的是地址内容,地址指向的是放整型的数据,为什么需要说是指向整型的地址呢?因为不同类型数据占据的不同大小的一整块内存,整型是一个占4字节大小的一个整体内存,字符型是一个占2个字节大小的一个整体内存,编译器不会把它们拆分开。如定义了一个int型变量,它的地址是0x7fffffff00,紧接着马上定义一个char型变量,他的地址就直接到了0x7fffffff04。从0x7fffffff00 ~ 0x7fffffff04中间不会再被分开了放int型数据,0x7fffffff04 ~ 0x7fffffff06中间不分开放char型数据。

所以 自身类型 是基本类型 + *组合而成,虽然里面放的都是地址,但是地址指向的一整块内容是有区别的。

指向类型

指向类型 是指 指针变量中放置的地址是指向的内容类型。

int num = 10;
int* p = NULL;
p = #
int** pp = NULL;
pp = &p;

这是一个二级指针,指向的类型是int*,说明变量pp指向的是指针类型的数据。

代码例子

代码1

 #include <stdio.h>
 int main()
 {
     int num = 100;
     printf("num = %d, num address = %#lx\n", num, &num);
     //num = 100, num address = 0x7ffd4376ff4c
     int* p = NULL;
     p = &num;
     printf("*p = %d, p =  %#lx, &p = %#lx\n", *p, p, &p);
     //*p = 100, p =  0x7ffd4376ff4c, &p = 0x7ffd4376ff40
     int** pp = NULL;
     pp = &p;
     printf("**pp = %d, *pp = %#lx, pp = %#lx\n", **pp, *pp, pp);
     //**pp = 100, *pp = 0x7ffd4376ff4c, pp = 0x7ffd4376ff40
     int arr[5]= {10,20,30,40,50};
     printf("arr address = %#lx, arr[0] address = %#lx, arr[0] = %d\n",arr,&arr[0],arr[0]);
     //arr address = 0x7ffd4376ff20, arr[0] address = 0x7ffd4376ff20, arr[0] = 10
     int* parr = NULL;
     parr = arr;
     printf("parr = %#lx, *parr = %d, *(parr+2) = %d\n",parr,*parr,*(parr+2));
     //parr = 0x7ffd4376ff20, *parr = 10, *(parr+2) = 30
     char str[6]= {'a','d','m','i','n','\0'};
     printf("str address = %#lx, str[0] address = %#lx, str[1]= %c\n", str, &str[0],str[1]);
     //str address = 0x7ffd4376ff10, str[0] address = 0x7ffd4376ff10, str[1]= d
     char* pstr = NULL;
     pstr = str;
     printf("pstr = %#lx,*pstr = %c,*(pstr+2)= %c\n",pstr,*pstr,*(pstr+2));
     //pstr = 0x7ffd4376ff10,*pstr = a,*(pstr+2)= m
     char str2[6] = "admin";
     printf("str2 = %#lx, str2[0] address = %#lx, str2 = %s, str2[1]= %c\n",str2,&str2[0],str2,str2[1]);
     //str2 = 0x7ffd4376ff00, str2[0] address = 0x7ffd4376ff00, str2 = admin, str2[1]= d
     char* pstr2 = NULL;
     pstr2 = str2;
     printf("pstr2 = %#lx, pstr2 = %s\n",pstr2, pstr2);
     //pstr2 = 0x7ffd4376ff00, pstr2 = admin
 }

代码2

#include <stdio.h>
int main()
 {
     float num = 10;
     printf("num = %f, &num = %#lx\n\n", num, &num);
     //num = 10.000000, &num = 0x7ffcdf7ffd94
     float* pnum = &num;
     printf("*pnum = %f, pnum = %#lx, &pnum = %#lx\n\n ", *pnum, pnum, &pnum);
     //*pnum = 10.000000, pnum = 0x7ffcdf7ffd94, &pnum = 0x7ffcdf7ffd88
     float** p_pnum = &pnum;
     printf("**p_pnum = %f, *p_pnum = %#lx, p_pnum = %#lx\n\n",**p_pnum,*p_pnum,p_pnum);
     //**p_pnum = 10.000000, *p_pnum = 0x7ffcdf7ffd94, p_pnum = 0x7ffcdf7ffd88
     char arr[10] = {'a','d','m','i','n'};
     printf("arr[0]= %c, arr[5]= %c, arr[6]= %c, arr = %s\n",arr[0],arr[5],arr[6],arr);
     printf("&arr[0]= %#lx, &arr[1]= %#lx, arr= %#lx\n\n", &arr[0], &arr[1], arr);
     //arr[0]= a, arr[5]= , arr[6]= , arr = admin
     //&arr[0]= 0x7ffcdf7ffd70, &arr[1]= 0x7ffcdf7ffd71, arr= 0x7ffcdf7ffd70
     char* parr = NULL;
     parr = arr;
     printf("*parr = %c, *(parr+4)=%c, *(parr+5)=%c, parr = %s\n",*parr,*(parr+4),*(parr+5),parr);
     printf("parr = %#lx, parr+4 = %#lx, parr+5= %#lx\n\n", parr, parr+4, parr+5);
     //*parr = a, *(parr+4)=n, *(parr+5)=, parr = admin
     //parr = 0x7ffcdf7ffd70, parr+4 = 0x7ffcdf7ffd74, parr+5= 0x7ffcdf7ffd75
     char str[10]= "admin";
     printf("str[0]= %c, str[5]= %c, str[6]= %c, str = %s\n",str[0],str[5],str[6],str);
     printf("&str[0]= %#lx, &str[1]= %#lx, str = %#lx\n\n", &str[0], &str[1], str);
     //str[0]= a, str[5]= , str[6]= , str = admin
     //&str[0]= 0x7ffcdf7ffd60, &str[1]= 0x7ffcdf7ffd61, str = 0x7ffcdf7ffd60
     char* pstr = NULL;
     pstr = str;
     printf("*pstr= %c, *(pstr+4)= %c, *(pstr+5)= %c, pstr = %s\n", *pstr, *(pstr+4), *(pstr+5), pstr);
     printf("pstr = %#lx, pstr+4=%#lx, pstr+5= %#lx\n\n",pstr, pstr+4, pstr+5);
     //*pstr= a, *(pstr+4)= n, *(pstr+5)= , pstr = admin
     //pstr = 0x7ffcdf7ffd60, pstr+4=0x7ffcdf7ffd64, pstr+5= 0x7ffcdf7ffd65
 }

数值型指针

数值型指针: int* p;

如:

int num = 100;
int* p = &num;		//同时定义和初始化
int* p1 = NULL;		//定义
p1 = &num;			//初始化

字符型指针

字符型指针可以分为指针指向的是单字符还是字符数组两种

单字符

字符型指针: char* p;

char name = 'a';
char* p = &name;
printf("p = %c",*p);	//结果是 a

这里需要注意需要用 占位符 %c 去承接内容(或者说显示内容)

字符数组

字符型指针:char* p;

char arr[6] = {'a','d','m','i','n','\0'};
printf("arr = %s, arr = %#lx\n",arr,arr);	//admin,0x7ffffffc0
printf("arr[0]= %c,arr[1]= %c\n",arr[0],arr[1]);//a,d
char* parr = NULL;
parr = arr;     //也可以 parr =  &arr,但是编译时会报warning
printf("parr = %s, parr = %#lx\n", parr,parr);	//admin,0x7ffffffc0
printf("*(parr)= %c,*(parr + 1) = %c\n",*parr, *(parr+1));  

这里需要注意字符数组末尾需要加‘\0’字符表示字符数组结束,或者编译器自己会自动加上,所以在定义字符数组长度时需要加+1。

注意 字符数组名既可以表示地址也可以表示整个字符数组的内容,而不是第一个字符。相应的指针也是整个字符数组的内容。

printf("arr = %c\n", arr);
printf("parr = %c\n", parr);

以上两行代码可以编译过但是不能显示内容,需要用占位符%s去承接整个字符数组内容。

字符串型指针

字符型指针:char* p;

char str[5] = "admin";
printf("str = %s,str = %#lx\n",str,str); // admin,0x7ffffffe0.
printf("str[0]= %c, str[1]= %c\n",str[0],str[1]);	// a,d
char* pstr = NULL;
pstr = str;
printf("pstr = %s, pstr = %#lx\n",pstr,pstr); // admin,0x7ffffffe0.
printf("*pstr = %c,*(pstr+1) = %c\n",*pstr,*(pstr+1)); // a,d

如代码中结果显示所示,字符串数组名即是地址,同时也是数组内容,根据占位符的不同显示不同内容,占位符为%s时显示字符串,%#lx显示地址。同样的对于赋值给的指针变量也具有同样的功能。

但是如果这里

printf("str = %c\n",str);	//可以编译过但是不显示任何信息

字符数组总结

字符数组和字符串数组名都可以即表示地址又表示地址对应的内容,注意看需要它以什么形式显示,显示内容用%s,显示地址用%#lx。

字符数组和字符串数组名对应的地址都是第一个字符所在的地址。如上面的代码中 &arr[0] 和 arr 得到的地址相同

到此这篇关于C语言超详细讲解指针的使用的文章就介绍到这了,更多相关C语言指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中二级指针解析(指向指针的指针)

    目录 二级指针(指向指针的指针) 二级指针的定义与理解 二级指针定义格式 二级指针赋值实例 二级指针(指向指针的指针) 指针可以指向一份普通类型的数据,例如 int.double.char 等,也可以指向一份指针类型的数据,例如 int *.double *.char * 等. 如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针. 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示: 将这种关系转换为C语

  • c语言中的二级指针做函数参数说明

    目录 二级指针做函数参数 二级指针作为形参简单实例分析 实例 一级指针二级指针做函数形参 下面看看实例 二级指针做函数参数 1.用指针做函数参数申请动态内存的问题 //如果函数参数是指针,不能用一级指针做函数参数实现申请动态内存   void getMemory(char *p, int num) {     p = (char *)malloc(sizeof(char)*num); } void main() {     char *str = NULL;     getMemory(str,

  • C语言 从根本上理解指针

    目录 一.* 的意义 二.传值调用与传址调用 三.常量与指针 四.小结 一.* 的意义 在指针声明时,* 号表示所声明的变量为指针 在指针使用时,* 号表示取指针所指向的内存空间中的值 如下: int i = 0; int j = 0; int* p = &i; //指针声明 j = *p; //取值 变量 p 保存着变量 i 的内存地址,即:p <--> &i *p <--> i * 号类似一把钥匙,通过这把钥匙可以打开内存,读取内存中的值. 下面看一个指针的使用

  • C语言一看就懂的指针与结构体介绍

    目录 指针 结构体 指针 指针是C语言或者是c++里面最让人头疼的内容之一,正所谓指针在手,可以任指天下,这里只是简单的介绍指针的一些概念,后期我们将会深入剖析指针的基本原理. 注意:一个汉字占2个字节! 首先我们需要认识一下内存这个基本概念: 内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的,为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节,为了能够有效的访问到内存中的每个单元,就把内存单元进行了编号,这些编号被称为内存单元的地址. #inc

  • C语言超详细讲解指针的概念与使用

    目录 一.指针与一维数组 1. 指针与数组基础 2. 指针与数组 3. 一个思考 二.指针与字符串 三.指针和二维数组 1. 指针数组与数组指针 2. 指针数组 3. 数组指针 一.指针与一维数组 1. 指针与数组基础 先说明几点干货: 1. 数组是变量的集合,并且数组中的多个变量在内存空间上是连续存储的. 2. 数组名是数组的入口地址,同时也是首元素的地址,数组名是一个地址常量,不能更改. 3. 数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的其实地址. 对于第一点数

  • C语言由浅入深理解指针

    目录 1. 相关概念 2. 指针的定义方法 3. 指针的分类 4. 指针和变量的关系 5. 指针与数组的关系 6. 指针的运算 1. 相关概念 操作系统给每个存储单元分配了一个编号,从ox00 00 00 00~0xff ff ff ff,这个编号称为地址,指针就是地址 指针变量:即这个变量用来存放一个地址编号 无论什么类型的地址,都是存储单元的变换,在32位平台下都是4个字节,即任何类型的指针变量都是4个字节大小,64位操作系统占8个字节. 对应类型的指针变量,只能存放对应类型的地址.例如整型

  • C语言进阶教程之函数指针详解

    目录 一.函数指针 1.概念 1.2函数指针的使用方法 1.3练习巩固 1.4小结一下 二.阅读两段有趣的代码 1.( *(void( *)( ))0 )( ) 2.void (* signal(int,void( * )( int ) ) )(int) 附:函数指针的应用——函数回调 总结 一.函数指针 1.概念 函数指针:首先它是一个指针,一个指向函数的指针,在内存空间中存放的是函数的地址: 请看示例: int main(){ int a = 10; int*pa = &a; char ch

  • C语言详细讲解指针数组的用法

    目录 1. 指针数组定义方法 2. 指针的指针(二级指针) 3. 字符串和指针 4. 数组指针 定义方法 数组指针的用法 1. 指针数组定义方法 格式: 类型说明符 *数组名[ 元素个数 ] int *p[10]; // 定义了一个整型指针数组p,有10个元素,都是int *类型的变量 指针数组的分类: 同指针类型的分类,见上一篇 大多数情况下,指针数组都用来保存多个字符串. #include <stdio.h> int main() { char *name[5] = {"Hell

  • C语言超详细讲解指针的使用

    目录 指针概述 自身类型 指向类型 代码例子 数值型指针 字符型指针 单字符 字符数组 字符串型指针 字符数组总结 指针概述 C语言中指针也可以认为是一种类型,不同于数值型和字符型的类型.推演过去指针变量也就是相当于不同的变量类型,不同于数值变量.字符型变量.字符串变量. 指针变量两种类型:自身类型和指向的类型 自身类型:将变量名去掉,剩下的就是指针变量类型. 指向类型:将变量名和离它最近的一个*去掉,剩下的类型就是指针指向的类型 int num = 10; int* p = NULL; p =

  • C语言超详细讲解宏与指针的使用

    目录 1.关于define 2.初识指针 (1)内存 (2)示例 (3)指针的使用示例 (4)指针变量的大小 1.关于define define是一个预处理指令,有两种用法,一种是用define定义常量:另外一种是define定义宏. 下面的例子为利用define定义常量 #define _CRT_SECURE_NO_WARNINGS #define MAX 1000 #include <stdio.h> int main() { printf("%d\n",MAX); r

  • C语言超详细讲解函数指针的运用

    目录 前言 计算器的例子 回调函数 转移表 前言 前面我们学习了各种各样的指针类型,有些指针可以说是稀奇百怪,特别是函数指针,有些朋友可能觉得,函数指针有些多余,调用函数为什么要用指针调用,直接调用不好吗? 接下来我们从具体的实例来回答同学们的问题,加深对函数指针的理解. 计算器的例子 接下来我们写一个简单的计算器程序,完成不同的计算功能比如加减乘除: #include <stdio.h> //相加函数 int add(int a, int b) { return a + b; } //相减函

  • C语言超详细讲解指向函数的指针

    目录 一.函数的指针 二.指向函数的指针变量 三.调用函数的两种方式 四.指向函数的指针的作用 五.用指向函数的指针作函数参数(重点) 六.为什么要将指向函数的指针变量作为函数的形参(重点) 一.函数的指针 首先,函数名代表函数的起始地址,调用函数时,程序会从函数名获取到函数起始地址,并从该地址起执行函数中的代码,函数名就是函数的指针,所以我们可以定义一个指向函数的指针变量,用来存放函数的起始地址,这样一来,就可以通过该变量来调用其所指向的函数. 二.指向函数的指针变量 定义指向函数的指针变量

  • C语言 超详细讲解链接器

    目录 1 什么是链接器 2 声明与定义 3 命名冲突 3.1 命名冲突 3.2 static修饰符 4 形参.实参.返回值 5 检查外部类型 6 头文件 1 什么是链接器 典型的链接器把由编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体–该实体能够被操作系统直接执行. 链接器通常把目标模块看成是由一组外部对象组成的.每个外部对象代表着机器内存中的某个部分,并通过一个外部名称来识别.因此,==程序中的每个函数和每个外部变量,如果没有被声明为static,就都是一个外部

  • C语言 超详细讲解库函数

    目录 1 返回整数的getchar函数 2 更新顺序文件 3 缓冲输出与内存分配 4 库函数 练习 1 返回整数的getchar函数 代码: #include<stdio.h> int main() { char c; while((c = getchar())!=EOF)//getchar函数的返回值为整型 putchar(c); return 0; } 上述代码有三种可能: 某些合法的输入字符在被"截断"后使得c的取值与EOF相同,程序将在复制的中途停止. c根本不可能

  • C语言 超详细讲解算法的时间复杂度和空间复杂度

    目录 1.前言 1.1 什么是数据结构? 1.2 什么是算法? 2.算法效率 2.1 如何衡量一个算法的好坏 2.2 算法的复杂度 2.3 复杂度在校招中的考察 3.时间复杂度 3.1 时间复杂度的概念 3.2 大O的渐进表示法 3.3 常见时间复杂度计算举例 4.空间复杂度 5. 常见复杂度对比 1.前言 1.1 什么是数据结构? 数据结构(Data Structure)是计算机存储.组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合. 1.2 什么是算法? 算法(Algorit

  • C语言超详细讲解轮转数组

    目录 题目描述 实例 解题思路 1. 先整体逆转 2.逆转子数组[0, k - 1] 3.逆转子数组[k, numsSize - 1] 易错点 代码 题目描述 给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数.OJ链接 实例 1.实例1 输入: nums = [1,2,3,4,5,6,7], k = 3输出: [5,6,7,1,2,3,4]解释:向右轮转 1 步: [7,1,2,3,4,5,6]向右轮转 2 步: [6,7,1,2,3,4,5]向右轮转 3 步: [5,6,7

  • C语言超详细讲解数据结构中双向带头循环链表

    目录 一.概念 二.必备工作 2.1.创建双向链表结构 2.2.初始化链表 2.3.动态申请节点 2.4.打印链表 2.5.销毁链表 三.主要功能 3.1.在pos节点前插入数据 尾插 头插 3.2.删除pos处节点数据 尾删 头删 3.3.查找数据 四.总代码 List.h 文件 List.c 文件 Test.c 文件 五.拓展 一.概念 前文我们已经学习了单向链表,并通过oj题目深入了解了带头节点的链表以及带环链表,来画张图总体回顾下: 在我们学习的链表中,其实总共有8种,都是单双向和带不带

随机推荐