C语言中的指针 初阶

目录
  • 1.指针是什么
  • 2.指针和指针类型
  • 3.野指针
    • 3.1野指针成因
    • 3.2如何规避野指针
  • 4.指针的运算
    • 4.1指针±整数
    • 4.2指针-指针
    • 4.3指针的关系运算
  • 5.指针和数组
  • 6.二级指针
  • 7.指针数组

1.指针是什么

初学者都有一个疑问,那就是指针是什么?简单的说,就是通过它能找到以它为地址的内存单元。

地址指向了一个确定的内存空间,所以地址形象的被称为指针。

int main()
{
 int a = 10;
 int* pa = &a;

    return 0;
}
//pa是用来存放地址(指针),所以pa是指针变量。

总结:指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。

​ 地址是唯一标识一块空间的。

​ 指针的大小在32位平台是4个字节,在64位平台是8个字节。

2.指针和指针类型

我们知道变量有不同的类型(整型、浮点型、字符型等),其实指针也是有不同类型的。

​ 指针类型的意义1:

指针类型决定了指针解引用操作的时候,一次访问几个字节(访问内存的大小)
char* 指针解引用访问1个字节
int* 指针解引用访问四个字节

int main()
{
 char* pc = &a;
 *pc = 0;

 return 0;
}

​ 指针类型的意义2:

指针类型决定了,指针±整数的时候的步长(指针±整数的时候,跳过几个字节)
int* 指针+1 跳过四个字节
char* 指针+1 跳过一个字节

int main()
{
 int a = 10;
 int* pa = &a;
 char* pc = &a;

 printf("%p\n", pa);
 printf("%p\n", pc);

 printf("%p\n", pa+1);
 printf("%p\n", pc+1);

 return 0;
}

3.野指针

​ 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。

3.1野指针成因

指针未初始化

int main()
{
    int* p;//局部变量指针未初始化,默认为随机值
    *p = 20;//通过p中存的随机值作为地址,找到一个空间,这个空间不属于我们当前的程序
    //就造成了非法访问,p就是野指针

    return 0;
}

指针越界访问

int main()
{
    int arr[10] = 0;
    int i = 0;
    int* p = arr;

    for(i =0; i <= 10; i++)
    {
        *p = i;
        p++;//当指针指向的范围超出数组arr的范围时,p就是野指针
    }

    return 0;
}

指针指向的空间释放

int* test()
{
    int a = 10;
    return &a;
}

int main()
{
    int* p = test();
    printf("%d\n",*p);

    return 0;
}

3.2如何规避野指针

  • 指针初始化
  • 小心指针越界
  • 指针指向空间释放即使置NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性
int main()
{
    int a = 10;
    int* p = &a;//明确地初始化,确定指向

    int* p2 = NULL;//不知道一个指针当前应该指向哪里时,可以初始化为NULL

    return 0;
}

4.指针的运算

4.1指针±整数

#define N_VALUES 5
float values[N_VALUES];
float* vp;
for(vp = &values[0]; vp < &values[N_VALUES];)
{
    *vp++ = 0;
}

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,0};
    int* p = &arr[9];

    printf("%p\n",p);
    printf("%p\n",p-2);

    return 0;
}

4.2指针-指针

指针-指针 得到的数字的绝对值是指针和指针之间元素的个数

int main()
{
 int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
 printf("%d\n", &arr[9] - &arr[0]);
 printf("%d\n", &arr[0] - &arr[9]);

 return 0;
}

指针-指针 的前提是两个指针指向同一块区域

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,0};
    char ch[5] = {0};
    printf("%d\n",&arr[9] - &ch[0]);//err

    return 0;
}

应用 求字符串长度

int my_strlen(char* s)
{
 int count = 0;
 char* start = s;
 while(*s!='\0')
 {
  s++;
 }
 return s - start;
}

int main()
{
 char arr[] = "abcdef";
 int len = my_strlen(arr);
 printf("%d\n", len);

 return 0;
}

4.3指针的关系运算

#define N_VALUES 5
float values[N_VALUES];
float *vp;
for(vp = &values[N_VALUES]; vp > &values[0];)
{
    *--vp = 0;
}

上述程序也可以写成这样

for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
    *vp = 0;
}

实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这么写,因为标准并不保证它可行。

标准规定

​ 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

5.指针和数组

数组 - 是一块连续的空间,放的是相同类型的元素

数组大小和元素类型,元素个数有关系

指针(变量) - 是一个变量,放地址

指针变量的大小 是4(32bit)/8(64bit)byte

数组名确实是首元素地址

但是有两个例外:

  • sizeof(数组名) - 这里的数组名不是首元素的地址,是表示整个数组的,这里计算的是整个数组的大小,单位还是字节。
  • &数组名 - 这里的数组名不是首元素的地址,是表示整个数组的,拿到的是整个数组的地址
int main()
{
 int arr[10] = { 0 };
 int sz = sizeof(arr);
 printf("%d\n", sz);
 return 0;
}
int main()
{
 int arr[10] = { 0 };
 int* p = arr;
 int i = 0;
 int sz = sizeof(arr) / sizeof(arr[0]);
 for (i = 0;i < sz;i++)
 {
  *(p + i) = i;
 }
 for (i = 0;i < sz;i++)
 {
  printf("%d ", *(p + i));
 }

 return 0;
}

6.二级指针

我们都知道,指针变量是变量,是变量就有地址,那么指针变量的地址存放在哪里呢?

这就是我们要了解的二级指针。

int main()
{
    int a = 10;
    int* p = &a;
    int** pp = &p;//pp就是二级指针
    **pp = 20;
    printf("%d\n", a);//a = 20
    return 0;
}

7.指针数组

​ 从名字上来看,大家觉得指针数组是指针还是数组?

答案是数组,是存放指针的数组。

整型数组 - 存放整型的数组就是整型数组
字符数组 - 存放字符的数组就是字符数组
指针数组 - 存放指针的数组就是指针数组
int* 整型指针的数组
char* 字符指针的数组

int main()
{
 int arr[10];
 char ch[5];

 int* parr[5];
 char* pc[6];

 return 0;
}

int main()
{
 int a = 10;
 int b = 20;
 int c = 30;
 int* parr[3] = { &a,&b,&c };
 for (int i = 0;i < 3;i++)
 {
  printf("%d\n", *(parr[i]));
 }

 return 0;
}

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

(0)

相关推荐

  • C语言运用函数指针数组实现计算器功能

    本文实例为大家分享了C语言运用函数指针数组制作计算器的具体代码,供大家参考,具体内容如下 先来回顾一下概念: 指针数组 -- 存放指针的数组 函数指针 -- 存放函数地址的指针 函数指针数组 -- 存放函数指针的数组 接下来说说这次要制作的计算器的功能: 1.add -- 加法 2.sub -- 减法 3.mul -- 乘法 4.div -- 除法 0.exit -- 退出 具体来通过代码讲解: (1)首先写一个菜单程序,在运行程序时首先打印一次菜单. void menu() { printf(

  • C语言中的初阶指针详解

    目录 1.指针是什么 2.指针和指针类型 3.野指针 3.1野指针成因 3.2如何规避野指针 4.指针的运算 4.1指针±整数 4.2指针-指针 4.3指针的关系运算 5.指针和数组 6.二级指针 7.指针数组 ​ 总结 1.指针是什么 ​ 初学者都有一个疑问,那就是指针是什么?简单的说,就是通过它能找到以它为地址的内存单元. 地址指向了一个确定的内存空间,所以地址形象的被称为指针. int main() { int a = 10; int* pa = &a; return 0; } //pa是

  • C语言指针之必须要掌握的指针基础知识

    目录 一.指针概述 指针的创建 指针的大小 如何使用指针 二级指针 二.野指针 形成野指针的原因 如何规避野指针 三.指针的基本运算 指针± 整数 指针-指针 四.指针和数组 五.指针数组 总结 一.指针概述 指针是个变量,存放内存单元的地址(编号). 指针的创建 在定义指针变量的时候,在变量前面加上' * ',代表这个变量是一个指针,再往前面加上一个类型名,就代表指针的类型,称为XX指针. 指针的初始化: 使用&(取地址操作符)可以获得变量的地址,将其赋值给已经定义好的指针变量,需要它们的类型

  • C语言经典指针笔试题详解

    目录 题目一(有关传值调用与非法访问) 题目二 (返回栈空间地址的问题 ) 题目三 (区别传值调用的传址调用) 题目四 (free释放的时机)

  • C语言进阶学习之指针

    目录 1.指针概念回顾 2.字符指针 3.数组指针和指针数组 3.1数组指针的含义 3.2&数组名vs数组名 3.3数组指针 4.数组传参和指针传参 4.1一维数组传参 4.2二维数组传参 4.3一级指针传参 4.4二级指针传参 5.函数指针 6.函数指针数组 7.指向函数指针数组的指针 8.回调函数 总结 1.指针概念回顾 指针的基本概念: 指针是一个变量,用来存放地址,地址唯一标识一块内存空间.指针的大小是固定的4/8个字节(32位平台/64位平台).指针是有类型,指针的类型决定了指针的±整

  • C语言中的指针新手初阶指南

    目录 1.指针是什么 2.指针和指针类型 3.野指针 3.1野指针成因 3.2如何规避野指针 4.指针的运算 4.1指针±整数 4.2指针-指针 4.3指针的关系运算 5.指针和数组 6.二级指针 7.指针数组 总结 1.指针是什么 ​ 初学者都有一个疑问,那就是指针是什么?简单的说,就是通过它能找到以它为地址的内存单元. 地址指向了一个确定的内存空间,所以地址形象的被称为指针. int main() { int a = 10; int* pa = &a; return 0; } //pa是用来

  • C语言中的指针 初阶

    目录 1.指针是什么 2.指针和指针类型 3.野指针 3.1野指针成因 3.2如何规避野指针 4.指针的运算 4.1指针±整数 4.2指针-指针 4.3指针的关系运算 5.指针和数组 6.二级指针 7.指针数组 1.指针是什么 初学者都有一个疑问,那就是指针是什么?简单的说,就是通过它能找到以它为地址的内存单元. 地址指向了一个确定的内存空间,所以地址形象的被称为指针. int main() { int a = 10; int* pa = &a; return 0; } //pa是用来存放地址(

  • Go语言中的指针运算实例分析

    本文实例分析了Go语言中的指针运算方法.分享给大家供大家参考.具体分析如下: Go语言的语法上是不支持指针运算的,所有指针都在可控的一个范围内使用,没有C语言的*void然后随意转换指针类型这样的东西.最近在思考Go如何操作共享内存,共享内存就需要把指针转成不同类型或者对指针进行运算再获取数据. 这里对Go语言内置的unsafe模块做了一个实验,发现通过unsafe模块,Go语言一样可以做指针运算,只是比C的方式繁琐一些,但是理解上是一样的. 下面是实验代码: 复制代码 代码如下: packag

  • C语言中函数指针的三种使用方法总结

     C语言中函数指针的三种使用方法总结 在这里分享一下自己的心得,希望和大家一起分享技术,如果有什么不足,还请大家指正.写出这篇目的,就是希望大家一起成长,我也相信技术之间没有高低,只有互补,只有分享,才能使彼此更加成长. 定义方式:int (*p)(int x, int y); 实现代码: #include <stdio.h> int sum(int x, int y){ return x + y; } int reduce(int x, int y){ return x - y; } int

  • C语言中二级指针的实例详解

    C语言中二级指针的实例详解 用图说明 示例代码: #include <stdio.h> int main(int argc, const char * argv[]) { // int a = 5; int *p1 = &a; //-打印地址-----地址相同--------------- printf("&a = %p\n", &a);// printf("p1 = %p\n", p1);// int **p2 = &p

  • C语言中的指针以及二级指针代码详解

    很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家: 1.什么是"指针": 在执行C程序的时候,由于我们的数据是存储在内存中的.所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的内存地址是多少,换言之,C程序通过已知的内存地址到相应的内存位置存储数据. 这里简单说一下内存管理(对于初学者来说.为了避免专业术语引发的理解问题,下面的叙述尽量避免专业定义:),对于现代计算机系统来说,内存空间分为两个区域,一个是"数据区",一个是"

  • 详解C语言中的指针与数组的定义与使用

    指针的特点 他就是内存中的一个地址 指针本身运算 指针所指向的内容是可以操作的 操作系统是如何管理内存的 栈空间 4M~8m的大小 当进入函数的时候会进行压栈数据 堆空间 4g的大小 1g是操作系统 全局变量 内存映射 可以对内存的内容修改修改硬盘的内容 一般在数据库中经常使用 内存的分配与释放 c语言分配内存的方法 // malloc(需要分配的大小): 这里的分配的大小需要对齐的2的指数 void *mem = malloc(size); 释放内存 // 一般分配的内容都是在堆空间中的 //

  • 详解C语言中二级指针与链表的应用

    目录 前言 二级指针讲解 链表的应用 定义双链表的结构体 创建双链表 前言 这篇文章即将解决你看不懂或者不会写链表的基本操作的问题,对于初学者而言,有很多地方肯定是费解的.比如函数的参数列表的多样化,动态分配内存空间函数malloc等,其实这些知识和指针联系紧密,尤其是二级指针.那么开始好好的学习这篇文章吧! 二级指针讲解 简述:其实就是一个指针指向另一个指针的地址. 我们都知道指针指向地址,但是指针自身也是一个变量,当然也可以被二级指针所指向. 语法:形如 int x = 10; int *q

  • 一文带你了解Go语言中的指针和结构体

    目录 前言 指针 指针的定义 获取和修改指针所指向变量的值 结构体 结构体定义 结构体的创建方式 小结 前言 前面的两篇文章对 Go 语言的基础语法和基本数据类型以及几个复合数据类型进行介绍,本文将对 Go 里面的指针和结构体进行介绍,也为后续文章做铺垫. 指针 在 Go 语言中,指针可以简单理解是一个地址,指针类型是依托于某一个类型而存在的,例如 Go 里面的基本数据类型 int.float64.string 等,它们所对应的指针类型为 *int.*float64.*string等. 指针的定

  • C语言中函数指针与软件设计经验总结

    函数指针与软件设计 记得刚开始工作时,一位高手告诉我,说,longjmp和setjmp玩得不熟,就不要自称为C语言高手.当时我半信半疑,为了让自己向高手方向迈进,还是花了一点时间去学习longjmp和setjmp的用法.后来明白那不单是跳来跳去那样简单,而是一种高级的异常处理机制,在某些情况下确实很有用. 为了显示自己的技巧,也在自己的程序中用过几次.渐渐发现这样的技巧带来的好处是有代价的,破坏了程序的结构化设计,程序变得很难读,尤其对新手来说.终于明白这种技巧不过是一种调味料,在少数情况使用几

  • C语言中关于指针变量的坑

    先看一个初始化带头结点单链表的例子,LNode是结点变量,LinkList是结点指针变量,等同于LNode* typedef struct LNode{ // 定义单链表节点类型 int data; struct LNode *next; }LNode,*LinkList; 例1.错误的方法:初始化带头结点的单链表 void InitList(LinkList L) { L = (LinkList)malloc(sizeof(LNode)); L->data = 3; L->next = NU

随机推荐