原文:深入理解C指针之一:初识指针

  简单来说,指针包含的就是内存地址。理解指针关键在于理解C的内存管理模式。C里面有三种内存:

  ①、静态全局内存(生命周期从程序开始到程序结束,全局变量作用域是全局,静态变量作用域在定义它们的函数内部);

  ②、自动内存(在函数内部声明的变量,在函数被调用时创建,作用域和生命周期都在函数内部);

  ③、动态内存(内存分配在堆上,根据需要释放,通过指针引用,作用域局限于引用的指针);

  下面先来声明一个指针并打印其地址和值,这里p%指的是以十六进制的形式返回数据:

#include <stdio.h>
main()
{
int num=5;
int* pi=&num;
printf("Address of pi is : %p\n Value: %p\n", &pi, pi);
//Address of pi is : 0xbfa98298
//Value: 0xbfa98294
}

  间接引用操作符(*)返回指针变量指向的值,一般称为解引指针。我们可以把接引操作符的结果用作左值,“左值”指赋值操作符左边的操作数,所有左值都必须可以修改,因为它们会被赋值。

*pi = 10;
printf("%d\n", num);

  null有几种不同的应用情况,这可能使它被误解。null被赋值给指针就说明该指针不指向任何东西。当然他还是有自己的地址,但是他的value将是空的。NULL宏是强制转换为void指针的整数常量0。很多头文件都包含这个定义,如stddef.h,stdblib.h,stdio.h。通过NULL宏来获取null指针。ASCII字符NUL定义为全0的字节。null语句就是只有一个分号的语句。null字符串就是空字符串。注意为初始化的指针可能包含任何值,但是null指针不会引用内存中 任何地址。当指针为null时,if(指针)表示false,反之表示true。

  NULL宏:

#define NULL ((void*) 0)
int* pi1 = 0;//1
int* pi2 = NULL//2  

  1和2是等价的。在这里,根据不同上下文,数字0被重载了,表示null指针。

  void指针是通用类型指针,用来存放任何数据类型的引用。任何指针都可以被赋值给void指针,也可以转换成原来的指针类型,因此我们应该小心不能胡乱转换,因为不同类型的指针长度不一定相同。使用sizeof()函数打印指针的长度:

printf("size of *pi is : %d\n", sizeof(*pi));

  当指针被声明全局或静态,就会在程序启动时被初始化为NULL。指针的实际长度取决于使用的机器和编译器。不同的计算机给C的数据类型分配空间采用不同的数据模型。一种操作系统可能支持多种模型,具体采用哪种通常由编译器决定。

  使用指针时可能遇到一下预定义类型

  ①、size_t :用于安全的表示长度;

  ②、ptrdiff_t:用于处理指针算术运算;

  ③、intptr_t和uintptr_t:用于存储指针地址;

  size_t类型表示C中任何对象能达到的最大长度。它是无符号整数。size_t作为sizeof操作符的返回值类型,同时也是很多函数如malloc和strlen的参数类型。打印size_t可以用 %zu 或 %u格式说明符。

size_t s = sizeof(pi);
printf("s is : %zu\n",s);

  intptr_t和uintptr_t类型用来存放指针地址。它们提供了一种可移植且安全的方法声明指针,而且和系统中使用的指针长度相同。当可移植性和安全性变得重要时,就应该使用这些类型。

#include <stdint.h>
main()
{
int im = 100;
intptr_t* iptr = &im;
printf("iptr is : %p\n", iptr);
  //iptr is : 0xbfebdb30
}

  指针有如下几种操作符

  *    声明指针

  *    解引指针

  ->      指向操作符

  +    加法

  -     减法

  == !=   相等、不等

  > >= < <= 大于大于等于小于小于等于

  数据指针可以执行以下算数运算

  加上整数;实际加的数是整数与指针数据类型对应字节的乘积。

  减去整数;原理同上。

  两个指针相减;一个指针减去另一个指针得到两个指针间的差值。同样这个差值是"单位"数,是实际地址差除以数据对应字节数的值。ptrdiff_t类型用于表示两个指针差值的可移植方式。

  比较指针;差值和比较指针通常在数组方面比较有用,可以用来判断元素顺序。

  大部分系统基本数据类型的长度:

  byte     1

  char     1

  short    2

  int         4

  long      8

  float      4

  double     8

  现在来对一个指向数组的指针做加法,看看输出的结果:

int vector[] = {100, 200, 300};
int* vpi = vector;
printf("vpi is : %p\n", vpi);//vpi is : 0xbff740c0
vpi +=1;
printf("vpi is : %p\n", vpi);//vpi is : 0xbff740c4
vpi +=1;
printf("vpi is : %p\n", vpi);//vpi is : 0xbff740c8

  指针支持多层间接引用。指向指针的指针叫做“双重指针”。

char* titles[] = {"titanic", "jack", "rose", "ocean", "big ship", "naked"};
char* *human[2];
char* *object[3];
human[0] = &titles[1];
human[1] = &titles[2];
object[0] = &titles[0];
object[1] = &titles[3];
object[2] = &titles[4];
printf("human[1] is : %s\n", *human[1]);
//human[1] is : rose

  如果字符串的地址变了,只需要修改titles就可以了,不需要连human和object数组一起修改。

   常量与指针。指向常量的指针意味着你不能通过接引修改它所引用的值。指向非常量的常量指针意味着指针不可变,但是指向的数据可变。指向常量的常量指针本身不能被修改,所指向的数据也不能被修改。看看区别:

const int con = 50;
const int * pcon = &con;//指向常量数据的非常量指针
printf("pcon is : %p\n", pcon);//pcon is : 0xbfefd754
int ncon = 50;
int* const pncon = &ncon;//指向非常量数据的常量指针
printf("pncon is : %p\n", pncon);//pncon is : 0xbfefd758
const int * const pcncon = &con;//指向常量数据的常量指针
printf("pcncon is : %p\n", pcncon);//pcncon is : 0xbfefd754

  现在来看看本节的最后一种指针:指向“指向常量的常量指针”的指针。除了它本身能改以外(重新赋其它地址),它所指向的指针(值)和解引的数据都是不可修改的。有些指针比较长,读的时候可以从右往左读,const和int被*分开时,表示不是常量数据,两个紧挨着,前后关系不重要,都表示常量数据。从右边往左边读,第一个*表示是一个指针,一个被*分开的const表示是一个常量指针,又一个*表示这是一个指向指针的指针,const int表示指向的是常量整形数据指针,因此是一个指向“指向常量数据的指针”的指针。

const int * const * pcpncon = &pcncon;
printf("pcpncon is : %p\n pcncon is : %p\n con is :%d\n", pcpncon, *pcpncon, **pcpncon);
//pcpncon is : 0xbf8e20c8
//pcncon is : 0xbf8e20c0
//con is :50

深入理解C指针之一:初识指针的更多相关文章

  1. 浅谈 .NET 中的对象引用、非托管指针和托管指针 理解C#中的闭包

    浅谈 .NET 中的对象引用.非托管指针和托管指针   目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五 ...

  2. 深入理解C语言中的指针与数组之指针篇

    转载于http://blog.csdn.net/hinyunsin/article/details/6662851     前言 其实很早就想要写一篇关于指针和数组的文章,毕竟可以认为这是C语言的根本 ...

  3. 深入理解C语言中的指针与数组之指针篇(转载)

    前言 其实很早就想要写一篇关于指针和数组的文章,毕竟可以认为这是C语言的根本所在.相信,任意一家公司如果想要考察一个人对C语言的理解,指针和数组绝对是必考的一部分. 但是之前一方面之前一直在忙各种事情 ...

  4. 深入理解C指针之五:指针和字符串

    原文:深入理解C指针之五:指针和字符串 基础概念 字符串可以分配到内存的不同区域,通常使用指针来支持字符串操作.字符串是以ASCII字符NUL结尾的字符序列.ASCII字符NUL表示为\0.字符串通常 ...

  5. 深入理解C指针之六:指针和结构体

    原文:深入理解C指针之六:指针和结构体 C的结构体可以用来表示数据结构的元素,比如链表的节点,指针是把这些元素连接到一起的纽带. 结构体增强了数组等集合的实用性,每个结构体可以包含多个字段.如果不用结 ...

  6. 深入理解C指针之四:指针和数组

    原文:深入理解C指针之四:指针和数组 数组是C内建的基本数据结构,数组表示法和指针表示法紧密关联.一种常见的错误认识是数组和指针完全可以互换,尽管数组名字有时可以当做指针来用,但数组的名字不是指针.数 ...

  7. 深入理解C指针之三:指针和函数

    原文:深入理解C指针之三:指针和函数 理解函数和指针的结合使用,需要理解程序栈.大部分现代的块结构语言,比如C,都用到了程序栈来支持函数的运行.调用函数时,会创建函数的栈帧并将其推到程序栈上.函数返回 ...

  8. typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针

    首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...

  9. 理解git 中的HEAD指针&branch指针

    理解git 中的HEAD指针&branch指针 Yooye关注 2019.02.28 10:44:32字数 492阅读 668 HEAD指针 使用git checkout 来移动HEAD指针, ...

随机推荐

  1. [Android 4.4.4] 泛泰A870 通过刷第三版 Mokee4.4.4 KTU84P 20140626 RC2.1 by syhost

    主题及注意事项请访问以前的版本: http://blog.csdn.net/syhost/article/details/29931291 此RC2.1版比RC2.0改进的地方: 1. Mokee本身 ...

  2. 默认情况下安装的应用程序C盘后提示权限不足,当你开始介意。。。

    最近,不少用户抱怨的经销商.正在使用win 7我们的计算机系统上安装软件后,提示权限不够开放系统,无法启动软件. 在xp该系统是没有问题的.原因是,我们会选择在默认安装路径系统C-disk.和win ...

  3. 新RSS reader

    阅读之前采取正确的方法,但是非常不介意,没有收到订阅很大. 走到今天 http://www.feedspot.com 2014/11/8追加:用下来感觉不错. feedspot 的相关快捷键例如以下: ...

  4. 非阻塞IOserver型号

    让我们来考虑一个场景,你和百万玩家的魔兽世界的忠实粉丝.时间之旅打每到周末boss. 每当周末比赛server在亚历山大,因为至少在同一时间数十万用户在线. 假设我们的多-threaded果酱serv ...

  5. opencv-形态处理

    开运算 (Opening) 原理摘自:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/opening_closi ...

  6. POJ1149 PIGS 【最大流量】

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16555   Accepted: 7416 Description ...

  7. Android 按下电源按钮关闭小学习过程的整个长度

    Android 按下电源按钮关闭小学习过程的整个长度 近期研究了一下android关机跟又一次启动功能,看了一些长按电源键到弹出关机对话框,到真正关机的一系列处理过程. 首先还是来看看这个长按电源键都 ...

  8. adp设备是什么

    今天在写软工文档的可行性分析部分的时候.遇到一个新名词--adp,瞬间就不淡定了.原话例如以下: 6.1.1 基本建设投资 包含採购.开发和安装下列各项所需的费用,如: a. 须要提供一件教室,供开发 ...

  9. cocos2d-x由Jni实现Java与C++打电话给对方

    cocos2d-x由Jni实现Java与C++打电话给对方. cocos2d-x与开发商提供一个类JniHelper,提供java与c++之间的互jni解. 笔者所开发的"史上最坑爹的游戏& ...

  10. jQuery.reveal弹出层

    jQuery.reveal弹出层使用 最近用到弹出层,还得自定义UI,原本用的artDialog太庞大,不合适了,于是就找到了这个东西,又小又好用,基础的弹出遮罩都有了,想要什么还不是Coder自己说 ...