c语言对指针的理解

先来讲一下本人学指针的经历:大一的时候刚接触c语言对指针这东西真的是太迷了,感觉麻烦难懂不想其他语言一样。但是搞懂以后就被指针的魅力吸引甚至喜欢上c语言。不多讲,开始!(文章可能有些长,但放心全是基础的东西,里面有实际的例子。)

理解变量的存储

int main()

{

    int a = 4;

    printf("%d\n", a);

    printf("%p", a);

    return 0;

}

结果:

4

00000004

(1)int a;

c语言在内存的存储是以栈的形式。在栈中先定义了一个变量a并在内存中开辟了大小为4个字节的空间。然后让a指向这片空间。此时小宝贝就有了自己的空间了,就可以放东西了,耶!

(2)a=4;

此时将4的值赋就是将4存到a的那片空间中。

由以上代码可知,第一个输出的是存放的值,第二个输出的是a空间的地址。

但是我们通常是不直接这样给变量赋值,往往是手动输入:

scanf("%d",&a);

用户先输入一个int型的值,&a先找到自己的那片空间(&是取地址符),然后经值转化为二进制存入到这个空间里。(嘿嘿,一个宝藏就这样存了进来)

找到宝藏的法宝——指针

既然有了自己的空间又有了值,那谁能知道我的地址来发现我的宝藏呢?哈哈,指针来了。

他来了,他来了,他真的来了,,,,,,,

首先要知道,指针指向的是地址,是地址,是地址!不要误以为他指的的是变量的值。

指针变量的定义与赋值:

第一种形式:

int *p=&a;

第二种形式:

int *p;

p=&a;

int *p;这里要区分,int*是在一起的,代表指针类型,p指的是指针变量。

多级指针

指向指针的指针,有时人们也管它叫多维指针。既然指针变量是一个变量,指针变量能存变量的内存的地址。

像 int * 存 int 型变量的地址,char * 存 char 型的地址,那指针理所当然可以存指针变量的地址啊。

例如,int ** 存 int * 的地址,int *** 存 int ** 的地址。

这就是一个二级指针存一级指针的地址,三级指针存二级指针的地址,人们把这样的过程叫指向指针的指针,但其实也就是一个上一级的指针存了下一级的指针的地址而已。

因此,像上面说的,你存了它的地址,你就是指向它,所以:

二级指针存一级指针的地址,那么可以说二级指针指向一级指针

三级指针存二级指针的地址,那么可以说二级指针指向一级指针

多级指针用处多多。

唉,怎么说呢,本人也是刚学c语言没多久,能力也有限,只是有自己的理解,例子还是请大家去实践。

指针的应用

1.作为参数的指针(指针变量作为函数参数):我们都知道在使用自定义函数时,每个自定义函数与主函数之间联系都是通过值传递的形式,但是并不能通过在自定义函数中改变参数的值来改变主函数中参数的值。但是通过指针,就能在自定义函数中访问主函数的变量了。

简单的例子:

void  fun(int *p);

int i=0;fun(&i)//因为自定义函数形参是指针,所以调用函数时传入地址。

这样在自定义的函数中就可以通过这个指针访问外面这个i

看几个代码的例子:

(1)不能通过在自定义函数中改变参数的值来改变主函数中参数的值:

voidchange(intp){printf("%d\n",p);//接受的值为5p=6;//想要改变参数的值}intmain(){intp=5;change(p);printf("%d\n",p);return0;}结果:55//值并没有发生改变

(2)利用指针后:

void change(int *p)

{

    printf("%d\n", *p);//接受的值为5

    *p= 6;//通过指针访问值,把p的值改为6

}

int main()

{

    int p=5;

    change(&p);//传入地址

    printf("%d\n", p);

    return 0;

}

结果:

5

6

//主函数的值发生改变

再看一个例子:利用自定义函数来比较三个数的大小

#include<stdio.h>

//交换

void swap(int* p1, int* p2)

{

    int temp;

    temp = *p1;

    *p1 = *p2;

    *p2 = temp;

}

//compare

void compare(int* p1, int* p2, int* p3)//定义指针变量,利用指针和主函数中的变量联系

{

    if (*p1 > * p2)swap(p1, p2);

    if (*p1> * p3)swap(p1, p3);

    if (*p2> * p3)swap(p2, p3);

}

int main()

{

    int* p1, * p2, * p3, a, b, c;

    scanf_s("%d,%d,%d", &a, &b, &c);

    p1 = &a;//指针变量接收地址

    p2 = &b;

    p3 = &c;

    compare(p1, p2, p3);//自定义函数指针接收的仍是地址

    printf("%d,%d,%d", a, b, c);

    return 0;

}

2.双胞胎——指针还是数组?(用数组名做函数参数):

首先必须了解一个基本知识。

大家都知道一个数组有多个变量,那么如何访问数组中的变量(那么多宝藏怎么找啊)。数组是一个连续的空间,只要将首元素的地址赋给指针,指针通过首元素的地址访问到了数组的首元素,那么通过遍历的方法不就访问到了整个数组。(就像顺腾摸瓜一样)

赋值方式:

int *p;

p=&a[0];

//或者利用元素名:

int *p;

p=a;//a=&a[0]

先看下列伪代码:

代码一

void fun(int arr[],int n )

'''''''

''''''

int main()

int array[10]=,,,,

,,,,,,,

fun(array,10)

代码二

void fun(int *arr,int n )

'''''''

''''''

int main()

int array[10]=,,,,

,,,,,,,

fun(array,10)

这两个伪代码是等价的,即数组名作为函数参数时可以当做是指针。

原理嘛,允许我偷下懒哈哈,况且比我讲的明白,(接图):


代码实例:

逆序输出数组中的数

void reversed(int a[], int n)//数组作为指针变量接收地址,int a[]等价于int *a

{

    int i, j, m = (n - 1) / 2,temp;

    for (i = 0; i <= m; i++)

    {

        j = n - 1 - i;//控制序列j

        temp = a[i];

        a[i] = a[j];

        a[j] = temp;

    }

    for (int i = 0; i < 5; i++)

        printf("%d\t", a[i]);//利用指针访问元素

}

int main()

{

    int a[5];

    int n = 5;

    for(int i = 0; i < 5; i++)

    {

        scanf_s("%d,", &a[i]);

    }

    for (int i = 0; i < 5; i++)

    {

        printf("%d\t", a[i]);

    }printf("\n");

    reversed(a, n);//数组名作为地址对函数进行调用

}

比较数组中数字的大小

void compare(int a[],int len,int *min,int *max)

{

        int i;

        *min =*max=a[0];

        for (i = 1; i < len; i++)

        {

              *max = a[i] > *max ? a[i] : *max;

              *min = a[i] < *min ? a[i] : *min;

        }

}

int main()

{

        int a[] = {1,2,3,4546,7,3,2,1,89,334};

        int i;

        int len = sizeof(a) / sizeof(a[0]);//数组的长度

        int min, max;

        compare(a,len,&min,&max);

        printf("min=%d,max=%d", min, max);

        return 0;

}

3.二维数组元素的地址

首先要明白的一点就是二维数组其实就是一维数组。在普通的一维数组中(a[0]),用数组名a作为数组a[0]的地址,那么在二维数组中(a[3][4]),a[0],a[1],a[2]就表示数组第一个元素的地址。这个结合一下实例可能比较好理解一下

代码实例

以a[0]作为元素地址

int main()

{

    int a[3][4] = {12,2,3,4,56,7,8,9,10,1,9,34};

    //int n = 5;

    int* p;

    for(p=a[0]; p<a[0]+12; p++)//a[0]作为数组的地址传递给指针p。a[0]+12是最后一个元素的地址

    {

        if ((p - a[1]) % 4 == 0)

          printf("\n");

        printf("%d\t", *p);

    }


    return 0;

}

结果:

12      2      3      4

56      7      8      9

10      1      9      34

E:\vs\c++\h\Debug\h.exe (进程 12316)已退出,代码为 0。

按任意键关闭此窗口. . .

若以a[1]作为元素地址

int main()

{

    int a[3][4] = {12,2,3,4,56,7,8,9,10,1,9,34};

    //int n = 5;

    int* p;

    for(p=a[1]; p<a[1]+8; p++)

    {

        if ((p - a[1]) % 4 == 0)

          printf("\n");

        printf("%d\t", *p);

    }


    return 0;

}

结果:

56      7      8      9

10      1      9      34

E:\vs\c++\h\Debug\h.exe (进程 21144)已退出,代码为 0。

按任意键关闭此窗口. . .

以a[2]作为元素地址:

int main()

{

    int a[3][4] = {12,2,3,4,56,7,8,9,10,1,9,34};

    //int n = 5;

    int* p;

    for(p=a[2]; p<a[2]+4; p++)

    {

        if ((p - a[1]) % 4 == 0)

          printf("\n");

        printf("%d\t", *p);

    } 

    return 0;

}

结果:

10      1      9      34

E:\vs\c++\h\Debug\h.exe (进程 19664)已退出,代码为 0。

按任意键关闭此窗口. . .

由此可得如图的结构:


所以,在应用多维数组变量时应将多维数组看作一维数组来解决就容易很多了。

以上就是我对指针的部分理解,当然还有很多,当然存点小私心写得都是我原来不懂得哈哈。真的很有意思整懂了以后。希望有用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351