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

数组名确实是首元素地址

但是有两个例外:

  1. sizeof(数组名) - 这里的数组名不是首元素的地址,是表示整个数组的,这里计算的是整个数组的大小,单位还是字节。
  2. &数组名 - 这里的数组名不是首元素的地址,是表示整个数组的,拿到的是整个数组的地址
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语言指针的进阶版本,希望大家能够对C语言的指针能够有更深层次的了解。

总结

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

(0)

相关推荐

  • C语言指针的长度和类型深入分析

    指针是C语言的精髓,本文就以实例的形式详细分析了C语言的长度和类型.对于初学者深入理解C语言程序设计有很好的参考价值.具体分析如下: 一般来说,如果考虑应用程序的兼容性和可移植性,指针的长度就是一个问题,在大部分现代平台上,数据指针的长度通常是一样的,与指针类型无关,尽管C标准没有规定所有类型指针的长度相同,但是通常实际情况就是这样.但是函数指针长度可能与数据指针的长度不同. 指针的长度取决于使用的机器和编译器,例如:在现代windows上,指针是32位或是64位长 测试代码如下: #inclu

  • C语言指针学习经验总结浅谈

    这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较费解的东西做一下讲解,希望能达到以下三个目的 1.通过写这些东西,把我脑袋中关于C的模糊的知识清晰化.2.给初转C的同事们一点提示和帮助.3.也希望各位前辈检查一下文档中是否有理解偏差的地方.1 指针的概念分解      指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容: 1.指针的类型2.指

  • 基于C语言中野指针的深入解析

    "野指针"的成因主要有两种:(1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存.例如 复制代码 代码如下: char *p = NULL;     char *str = (char *) malloc(100); (2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针.参见7.5节.别看free和dele

  • C语言指针详解及用法示例

    新手在C语言的学习过程中遇到的最头疼的知识点应该就是指针了,指针在C语言中有非常大的用处.下面我就带着问题来写下我对于指针的一些理解. 指针是什么? 指针本身是一个变量,它存储的是数据在内存中的地址而不是数据本身的值.它的定义如下: int a=10,*p; p=&a int a=10; int *p=&a; 首先我们可以理解 int* 这个是要定义一个指针p,然后因为这个指针存储的是地址所以要对a取地址(&)将值赋给指针p,也就是说这个指针p指向a. 很多新手都会对这两种定义方法

  • C语言入门之指针用法教程

    本文针对C语言初学者详细讲述了指针的用法,并配以实例进行说明.具体分析如下: 对于C语言初学者来说,需要明白指针是啥?重点就在一个"指"上.指啥?指的地址.啥地址?内存的地址. 上面说明就是指针的本质了. 这里再详细解释下.数据存起来是要存在内存里面的,就是在内存里圈出一块地,在这块地里放想放的东西.变量关心的是这块地里放的东西,并不关心它在内存的哪里圈的地:而指针则关心这块地在内存的哪个地方,并不关心这块地多大,里面存了什么东西. 指针怎么用呢?下面就是基本用法: int a, b,

  • C语言中函数与指针的应用总结

    1. 首先,在C语言中函数是一种function-to-pointer的方式,即对于一个函数,会将其自动转换成指针的类型. 复制代码 代码如下: #include<stdio.h> void fun(){} int main(void){   printf("%p %p %p\n", &fun, fun, *fun);   return 0;} -------------------------------------------------------------

  • c语言指针之二级指针示例

    二级指针的概念 首先任何值都有地址,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址,这就是存放地址这一值的空间所具有的地址,二级指针就是为了获取这个地址,一级指针所关联的是其值(一个地址)名下空间里的数据,这个数据可以是任意类型并做任意用途,但二级指针所关联的数据只有一个类型一个用途,就是地址,指针就是两个用途提供目标的读取或改写,那么二级指针就是为了提供对于内存地址的读取或改写指针的表现形式是地址,核心是指向关系指针运算符"*"的作用是按照指向关系访问

  • C语言的指针类型详细解析

    指针存储了内存的地址,同时指针是有类型的,如int*,float*,那么,一个自然的猜想就是指针变量应该存储这两方面的信息:地址和指针类型,比如,就像下面的结构体: 复制代码 代码如下: struct pointer{    long address;    int type;} 举个例子:打印sizeof(int*),值为4,可见4字节是存储内存地址用的,反过来就说明指针并没有存储类型信息的地方,那么指针的类型信息存放在哪儿呢?下面剖析一段简单的代码. 复制代码 代码如下: // ma.cpp

  • C语言指针应用简单实例

    C语言指针应用简单实例 这次来说交换函数的实现: 1. #include <stdio.h> #include <stdlib.h> void swap(int x, int y) { int temp; temp = x; x = y; y = temp; } int main() { int a = 10, b = 20; printf("交换前:\n a = %d, b = %d\n", a, b); swap(a, b); 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语言中的指针 初阶

    目录 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语言新手初阶教程之三子棋实现

    目录 三子棋 创建项目环境 头文件内容 编写main函数(test.c) 实现每一个接口函数 1.board 2.printfboard 3.play 4.computerplay 5.win 总结 三子棋 大家小时候应该都玩过三子棋吧,学习了这么久的C语言,我们其实已经具备了做三子棋这种小型项目的能力,今天我会尽量沉浸式的教大家实现三子棋,如果看完这篇博客还是不会的可以去我最后附上的gitee仓库链接中寻找.但我还是希望大家能自己完成,在三子棋中体现自己的风格. 创建项目环境 首先,第一步,打

  • 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等. 指针的定

随机推荐