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 ...
随机推荐
- list的使用-Hdu 1276
士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- iOS-动态库创建(详解)
https://blog.csdn.net/LisztCoder/article/details/78132147 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...
- 洛谷 P3808 【模板】AC自动机(简单版) (AC自动机优化板子)
题中有一个坑点,就是模式串可以相同,并且全部计数. #include <bits/stdc++.h> using namespace std; const int maxn=1e6+10; ...
- 【知识学习】PHP实现批量替换字典后缀
<?php //要打开字典的物理路径 $filename = 'E:\Local Test\WWW\password.txt'; $handle = fopen($filename,'r') o ...
- cookie,session,localStorage和sessionStorage
cookies:存储于浏览器端的数据.可以设置 cookies 的Max-Age或者Expires到期时间,如果不设置时间,则在浏览器关闭窗口的时候会消失. session:存储于服务器端的数据.se ...
- JavaScript位置:window&client&offset&scroll&MouseEvent&getBoundingClientRect&计算任意元素滚动条宽度
Window: window.innerWidth:浏览器viewport视口宽,包括垂直滚动条 window.innerHeight:浏览器视口高,包括水平滚动条 window.outerWidth ...
- codeforces round#613
A题:输出n+1: B题: 题意:就是给n个数,a人全拿,b人拿连续的子段和,如果b人比a人大于等于的话输出NO,反之输出YES 思路:最大子段和,比赛的时候忘记 ll 和 字段和不是遇到负数就重置. ...
- Android Studio如何更新support repository
转自: http://blog.csdn.net/sinat_29696083/article/details/70256377 刚进新公司,熟悉新业务中.老大叫我看看关于ConstraintLayo ...
- 输入流输出流IO的理解
之前对IO理解总是有点模糊, 输入输出,其实针对 数据处理主体 A ,这个主体我们通常是指服务器程序本身, 交互目的源B ,一般是本地磁盘,由本地磁盘IO传输, 或者 远程客户端,由网络IO传输. ...
- python3 linux
记录了Linux 安装python3.7.0的详细过程,供大家参考,具体内容如下 我这里使用的时centos7-mini,centos系统本身默认安装有python2.x,版本x根据不同版本系统有所不 ...