c-指针的理解
c-指针的理解
最近在学习MFC,其中的代码有点看的不是很深刻,究其原因还是对c语言中的指针理解的不是很好,下面详细的给大家介绍一下指针,如有不当之处,欢迎各位读者指正。
一.指针的概念
C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。也就是说:指针是一种保存变量地址的变量。
前面已经提到内存其实就是一组有序字节组成的数组,数组中,每个字节大大小固定,都是 8bit。对这些连续的字节从 0 开始进行编号,每个字节都有唯一的一个编号,这个编号就是内存地址。示意如下图:
这是一个 4GB 的内存,可以存放 2^32 个字节的数据。左侧的连续的十六进制编号就是内存地址,每个内存地址对应一个字节的内存空间。而指针变量保存的就是这个编号,也即内存地址。
二.为什么使用指针
在C语言中,指针的使用非常广泛,因为使用指针往往可以生成更高效、更紧凑的代码。总的来说,使用指针有如下好处:
1)指针的使用使得不同区域的代码可以轻易的共享内存数据,这样可以使程序更为快速高效;
2)C语言中一些复杂的数据结构往往需要使用指针来构建,如链表、二叉树等;
3)C语言是传值调用,而有些操作传值调用是无法完成的,如通过被调函数修改调用函数的对象,但是这种操作可以由指针来完成,而且并不违背传值调用。
三.如何申明一个指针
1 .声明并初始化一个指针
指针其实就是一个变量,指针的声明方式与一般的变量声明方式没太大区别:
int *p; // 声明一个 int 类型的指针 p
char *p // 声明一个 char 类型的指针 p
int *arr[] // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针
int (*arr)[] // 声明一个数组指针,该指针指向一个 int 类型的一维数组
int **p; // 声明一个指针 p ,该指针指向一个 int 类型的指针
指针的声明比普通变量的声明多了一个一元运算符 “*”。运算符 “*” 是间接寻址或者间接引用运算符。当它作用于指针时,将访问指针所指向的对象。在上述的声明中: p 是一个指针,保存着一个地址,该地址指向内存中的一个变量; *p 则会访问这个地址所指向的变量。
声明一个指针变量并不会自动分配任何内存。在对指针进行间接访问之前,指针必须进行初始化:或是使他指向现有的内存,或者给他动态分配内存,否则我们并不知道指针指向哪儿,这将是一个很严重的问题,稍后会讨论这个问题。初始化操作如下:
/* 方法1:使指针指向现有的内存 */
int x = ;
int *p = &x; // 指针 p 被初始化,指向变量 x ,其中取地址符 & 用于产生操作数内存地址 /* 方法2:动态分配内存给指针 */
int *p;
p = (int *)malloc(sizeof(int) * ); // malloc 函数用于动态分配内存
free(p); // free 函数用于释放一块已经分配的内存,常与 malloc 函数一起使用,要使用这两个函数需要头文件 stdlib.h
指针的初始化实际上就是给指针一个合法的地址,让程序能够清楚地知道指针指向哪儿
2. NULL指针
NULL 指针是一个特殊的指针变量,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针。
#include "stdio.h" int main(){
int *p = NULL;
printf("p的地址为%d\n",p); return ;
} /***************
* 程序输出:
* p的地址为0
***************/
以看到指针指向内存地址0。在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是为操作系统保留的。但是,内存地址 0 有一个特别重要的意义,它表明改指针不指向一个可访问的内存位置。
3.未初始化和非法的指针
如果一个指针没有被初始化,那么程序就不知道它指向哪里。它可能指向一个非法地址,这时,程序会报错,在 Linux 上,错误类型是 Segmentation fault(core dumped),提醒我们段违例或内存错误。它也可能指向一个合法地址,实际上,这种情况更严重,你的程序或许能正常运行,但是这个没有被初始化的指针所指向的那个位置的值将会被修改,而你并无意去修改它。
四.指针的运算
C 指针的算术运算只限于两种形式:
1) 指针 +/- 整数 :
可以对指针变量 p 进行 p++、p--、p + i 等操作,所得结果也是一个指针,只是指针所指向的内存地址相比于 p 所指的内存地址前进或者后退了 i 个操作数。用一张图来说明一下:
在上图中,10000000等是内存地址的十六进制表示(数值是假定的),p 是一个 int 类型的指针,指向内存地址 0x10000008 处。则 p++ 将指向与 p 相邻的下一个内存地址,由于 int 型数据占 4 个字节,因此 p++ 所指的内存地址为 1000000b。其余类推。不过要注意的是,这种运算并不会改变指针变量 p 自身的地址,只是改变了它所指向的地址。
2)指针 - 指针
只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。两个指针相减的结果的类型是 ptrdiff_t,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。举个例子:
五.指针与数组
在C语言中,指针与数组之间的关系十分密切。实际上,许多可以用数组完成的工作都可以使用指针来完成。一般来说,用指针编写的程序比用数组编写的程序执行速度快,但另一方面,用指针实现的程序理解起来稍微困难一些。
#include "stdio.h" int main(){
int arr[][] = {,,,,,}; // 定义一个二维数组并初始化
int (*p)[]; // 定义一个数组指针,指针指向一个含有3个元素的一维数组 p = arr; // 将二维数组的首地址赋给 p,此时 p 指向 arr[0] 或 &arr[0][0]
printf("%d\n",(*p)[]); // 输出结果为 1
p++; // 对 p 进行算术运算,此时 p 将指向二维数组的下一行的首地址,即 &arr[1][0]
printf("%d\n",(*p)[]); // 输出结果为5 return ;
}
参考链接:https://www.cnblogs.com/tongye/p/9650573.html
c-指针的理解的更多相关文章
- C语言教学--二维数组和指针的理解
对于初学者对二维数组和指针的理解很模糊, 或者感觉很难理解, 其实我们和生活联系起来, 这一切都会变得清晰透彻. 我们用理解一维数组的思想来理解二维数组, 对于一维数组,每个箱子里存放的是具体的苹果, ...
- 【C++】类中this指针的理解
转自 苦涩的茶https://www.cnblogs.com/liushui-sky/p/5802981.html C++类中this指针的理解 先要理解class的意思.class应该理解为一种类型 ...
- 函数指针的理解 from 数据结构
今天在学习数据结构中遇到一些问题,函数的指针不知道怎么用,给自己科普一哈 1 int LocateElem_Sq(SqList L, LElemType_Sq e, Status(*Compare)( ...
- C++中this指针的理解
C++中this指针的理解 先要理解class的意思.class应该理解为一种类型,象int,char一样,是用户自定义的类型.用这个类型可以来声明一个变量,比如int x, myclass my等等 ...
- c++形参改变实参(对指针的理解
这几天搞逻辑比较晕,居然把指针的概念都混淆了. eg:int *p;//当然不对指针初始化在有些编译器是通不过编译的,比如VS(尤其是选中了SDL) 指针p是一个对象,定义开始没有分配了内存空间,只是 ...
- C/C++学习笔记----指针的理解
指针是C/C++编程中的重要概念之一,也是最容易产生困惑并导致程序出错的问题之一.利用指针编程可以表示各种数据结构,通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯:指针能 ...
- 对于C语言中数组名是指针的理解
我们都知道,c语言中数组名是一个指针,比如下面这段代码 #include<iostream>using namespace std;int main(){ int a[4]={1,2,3, ...
- C 语言指针怎么理解?
对于程序员来说内存可以简化成这样一种东西:<img src="https://pic1.zhimg.com/4d060c3f67c22cd4b07273db00f64708_b ...
- c语言函数指针的理解与使用
1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun ...
- C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和&a 的区别
1.一个实例+理论分析 在了解数组和指针的访问方式前提下,下面再看这个例子: main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); pr ...
随机推荐
- 谈谈一些有趣的CSS题目-- 从倒影说起,谈谈 CSS 继承 inherit
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你 ...
- Laravel Vuejs 实战:开发知乎 (10)使用 Select2 优化话题选择
1.添加选择Topic 使用Select2,如何安装Select2 ,具体使用实例 Select2 and Laravel: Ajax Autocomplete 及 Loading data remo ...
- 【C语言】输入5个整数并按输入顺序逆序输出
#include <stdio.h> int main() { ],i; printf("请输入5个整数:\n"); ;i<;i++) scanf("% ...
- C语言:将3*4矩阵中找出行最大,列最小的那个元素。-将低于平均值的人数作为函数返回值,将低于平均分的分数放入below数组中。
//将3*4矩阵中找出行最大,列最小的那个元素. #include <stdio.h> #define M 3 #define N 4 void fun(int (*a)[N]) { ,j ...
- Leader:这样的 Bug 你也写的出来???
Hello~各位读者新年好!不知道大家春节假期是否已延长,小黑哥刚接到通知,假期延长到 2 月 2 号,另外回去之后需要在家办公,自行隔离两周.还没试过在家办公,小黑哥就怕到时候生物钟还没调整过来,一 ...
- 创业学习---《预判项目的长期壁垒》--B-3.预判模块---HHR计划---以太一堂
一,<开始学习> 1,投资人经常会问CEO:你的项目的长期壁垒是什么?你是怎么思考的? 2,三个预热思考题: (1)突然有一天,大公司要抄你,你会怎么办? 答:用增长技术来和他竞争. ( ...
- WLC-Download 3-party CA to WLC
一.基础准备 为了创建和导入第三方SSL-certificate你需要做如下准备:1.一个WLC(随着版本的不同,可能需要准备的也不同)这里以7.0.98版本为例.2.一个外部的证书颁发机构(Cert ...
- js图片轮换播放器
<!DOCTYPE html> <html> <head> <title></title> <meta charset="u ...
- C++ STL之栈stack和queue的使⽤
写在最前面,本文摘录于柳神笔记: (1)栈 stack 在头⽂件 #include 中,是数据结构⾥⾯的栈-以下是常⽤⽤法: (2)队列 queue 在头⽂件 #include 中,是数据结构⾥⾯的队 ...
- jenkins windows 2.204版,免安装,推荐插件齐备.
windows专用,已安装好推荐插件, 更新了安装源为清华源,也就是说只要官方的插件,你都可以秒速下载了.香不? 解压到一个文件夹,管理员模式运行cmdcd 文件夹名jenkins install这样 ...