C语言的灵魂——指针

一、指针简介

1、什么是指针?

指针是一个变量,其值为另一个变量的地址,即内存地址的直接地址。做个比喻,假设将你比作变量,那么你身份证上的住址就是指针,根据你身份证上的地址可以找到你,即指针存的内容是你身份证上的住址。

指针有两种含义,一是作为数据类型,二是作为实体。

指针作为实体,是一个用来保存一个内存地址的计算机语言中的变量。指针一般出现在比较底层的程序设计语言中,如C语言。高级语言如Java一般避免用指针,而是引用。指针作为数据类型,可以从一个函数类型、一个对象类型或者一个不完备类型中导出。从中导出的数据类型称之为被引用类型(referenced type)。指针类型描述了一种对象,其值为对被引用类型的实体的引用。

指针可以用来有效地表示复杂的数据结构,可以用于函数参数传递并达到更加灵活使用函数的目的。使C语言程序的设计具有灵活、实用、高效的特点。

2、*与&操作符

取地址运算符(&):取变量的地址,即返回操作数的内存地址。&var 读作"var 的地址"。

间接寻址运算符(*):返回操作数所指定地址的变量的值。

3、如何使用指针?

使用指针时会频繁进行以下几个操作:

  1. 定义一个指针变量;
  2. 把变量地址赋值给指针;
  3. 访问指针变量中可用地址的值。

这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。

#include <stdio.h>
int main (){
   int  var = 20;   /* 实际变量的声明 */
   int  *ip;/* 指针变量的声明 */
   ip = &var;  /* 在指针变量中存储 var 的地址 */
   printf("Address of var variable: %x\n", &var  );
   /* 在指针变量中存储的地址 */
   printf("Address stored in ip variable: %x\n", ip );
   /* 使用指针访问值 */
   printf("Value of *ip variable: %d\n", *ip );
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20

4、指针运算符

C 指针是一个用数值表示的地址。因此,您可以对指针执行算术运算。可以对指针进行四种算术运算:++、--、+、-。

假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算:

ptr++

在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 个字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。

5、NULL 指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序:
#include <stdio.h>
int main (){
int *ptr = NULL;
printf("ptr 的值是 %x\n", ptr );
return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

ptr 的值是 0

二、指针与数组

1、区别

C++/C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。数组是连续分配一串单元,数目开始定义的时候就必须固定下来,看起来整洁,但是写的程序是死程序,容易浪费内存。指针是存放一个地址值,表示指向某一个单元,可以用指针来索引单元。数组可以完成栈,堆,树等等的操作,它在编程时候的好处是非常的灵活,在构建思路的时候有很大的灵活性。

2、指针数组与数组指针

指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针。

数组指针:a pointer to an array,数组名本身就是一个指针,指向数组的首地址,即指向数组的指针。

int* a[4] ;   /* 指针数组      
                 表示:数组a中的元素都为int型指针     
                 元素表示:*a[i]   *(a[i])是一样的,因为[]优先级高于*/
int (*a)[4]  ;/* 数组指针      
                 表示:指向数组a的指针
                 元素表示:(*a)[i]   */

#include <stdio.h>
int main(void)
{
    int c[4]={1,2,3,4};
    int *a[4]; //指针数组
    int (*b)[4]; //数组指针
    b=&c;
    //将数组c中元素赋给数组a
    for(int i=0;i<4;i++)
    {
        a[i]=&c[i];
    }
    //输出看下结果
    printf("%d",*a[1]);//输出2就对
    printf("%d",(*b)[2]);//输出3就对
    return 0;
}

三、指针与字符串

C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中。字符数组归根结底还是一个数组,使用指针的方式来输出字符串:

#include <stdio.h>
int main(){
    char str[] = "http://www.jianshu.com/";
    char *pstr = str;
    int len = strlen(str), i;
    //使用*(pstr+i)
    for(i=0; i<len; i++){
        printf("%c", *(pstr+i));
    }
    printf("\n");
    //使用pstr[i]
    for(i=0; i<len; i++){
        printf("%c", pstr[i]);
    }
    printf("\n");
    //使用*(str+i)
    for(i=0; i<len; i++){
        printf("%c", *(str+i));
    }
    printf("\n");
    return 0;
}

四、指针与函数

函数指针:本身是一个指针,指向一个函数入口地址,通过该指针可调用其指向的函数,使用函数指针可实现回调函数。

#include <stdio.h>
void inc(int *val)
{
    (*val)++;
}
int main(void)
{
    void (*fun)(int *);
    int a=3;
    fun=inc;//fun是一个函数指针
    (*fun)(&a);
    printf("%d" , a);
}

指针函数:本身是一个函数,其返回值是一个指针。

#include <stdio.h>
float *find(float(*pionter)[4],int n);//函数声明
int main(void)
{
     static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
     float *p;
     int i,m;
     printf("Enter the number to be found:");
     scanf("%d",&m);
     printf("the score of NO.%d are:\n",m);
     p=find(score,m-1);
     for(i=0;i<4;i++)
         printf("%5.2f\t",*(p+i));
     return 0;
 }
float *find(float(*pionter)[4],int n)/*定义指针函数*/
 {
     float *pt;
     pt=*(pionter+n);
     return(pt);
 }

五、指针与引用

  1. 引用总是指向一个对象,没有所谓的 null reference 。所有当有可能指向一个对象也有可能不指向对象则必须使用指针。由于C++ 要求 reference 总是指向一个对象所以 reference要求有初值.由于没有所谓的 null reference 所以在使用前不需要进行测试其是否有值,而使用指针则需要测试其的有效性。
  2. 指针可以被重新赋值而reference则总是指向最初或地的对象。
  3. 必须使用reference的场合.Operator[]操作符由于该操作符很特别地必须返回 [能够被当做ssignment 赋值对象] 的东西,所以需要给他返回一个 reference。
  4. 其实引用在函数的参数中使用很经常。格式如下:
    void Get***(const int& a){} //这样使用了引用又可以保证不修改被引用的值

区别:

  • 指针是一个实体指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名;
  • 引用使用时无需解引用(*),指针需要解引用;
  • 引用只能在定义时被初始化一次,之后不可变;指针可变;
  • 引用“从一而终”;
  • 引用没有 const,指针有 const,const 的指针不可变;
  • 引用不能为空,指针可以为空;
  • sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定);
  • 指针和引用的自增(++)运算意义不一样。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,312评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,578评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,337评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,134评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,161评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,303评论 1 280
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,761评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,421评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,609评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,450评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,504评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,194评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,760评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,836评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,066评论 1 257
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,612评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,178评论 2 341

推荐阅读更多精彩内容

  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,420评论 3 44
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,499评论 1 51
  • 1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧...
    金巴多阅读 1,718评论 0 9
  • 鲜花伴我行, 一路好春景。 人间四月天, 胜似在仙境。 --2017.4.14
    孙德娟欣欣儿阅读 195评论 0 0
  • 刚下班,脑袋嗡嗡作响,耳朵里就像有一群知了在里面知知的叫,嗡嗡嗡嗡,知知知知,好不讨厌。我知道这是神经性耳鸣,大概...
    莺歌学飞阅读 188评论 0 0