精华内容
下载资源
问答
  • #一级指针二级指针、指针和数组、指针数组总结 ##数组:C 语言中所有的数组都可以看成是一维数组,数组传参的时候会发生降维问题,任何数组传参都会降维成指针。 ##指针:指针存放变量的地址,指向的值是变量的...

    #一级指针、二级指针、指针和数组、指针数组总结
    ##数组:C 语言中所有的数组都可以看成是一维数组,数组传参的时候会发生降维问题,任何数组传参都会降维成指针。
    ##指针:指针存放变量的地址,指向的值是变量的内容。

    指针(一级指针、二级指针、多级指针):
    一级指针用普通变量的地址去接,二级指针用一级指针的地址去接,N级指针用N-1级指针的地址去接。

    我们在一个程序中已经使用了一级指针了,如果想修改这个一级指针或者这个一级指针指向的内容,就会使用到二级指针了,但是,为了代码的可读性,最好用二级以下的指针解决。
    指针变量需要指向一个内存空间,内存空间相当于门牌号,而对一个指针解引用(*),相当于间接访问这个指针变量中存储的地址里面对应的内容。

    //指针指向元素
    int main()
    {
    	char a = 'w';	
    	char* p = &a;	// P 是一级指针,它指向的是 a 的地址。P 里面存放的就是 a 地址的内容。
    	char** pp = &p;//pp是二级
    	printf("%c ",*p);
    	printf("%c ",**pp);
    	return 0;
    }
    输出的结果为:w w
    
    //指针指向数组:
    int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
     int* p = arr;              //  数组在函数中除了 strlen  与  &  这两种情况以外,都代表首元素的地址。
     printf("%d\n", *p);  
     printf("%d\n", *(p + 1));    // 这里面 p +1 其实是 增加了 P 所指向数据类型大小字节的空间,p 开始是 1 的 地址, p +1:  因为 p 是int 型 指针,int 占 4个字节,所以要给 p 里面的地址加上 4,这样 p 的内容就变成给了 2 的地址;
     这里输出结果是:
      1
      2
      
    int arr[5] = { 0,1,2,3,4};
     int* p[] = { arr, arr + 1, arr + 2 };
     int** Q = p;
     printf("%d ", **Q);               
     printf("%d ", **(Q + 1));
     printf("%d ", **(Q + 2));
    输出结果:
    1 2 3
    

    ##指针数组:定义 int (*p)[n]
    ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n。执行p+1时,p要跨过n个整型数据的长度。
    将二维数组赋给一指针:

    int a[3][4];
    int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
     p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
     p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
    

    所以数组指针也称指向一维数组的指针,亦称行指针。

    ##指针数组定义 int p[n];
    **[]优先级高,先与p结合成为一个数组,再由int
    说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,p=a; 这里p表示指针数组第一个元*素的值,a的首地址的值。
    如要将二维数组赋给一指针数组:

    int *p[3];
    int a[3][4];
    p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
    for(i=0;i<3;i++)
    p[i]=a[i]
    

    这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]赋值时需要分别赋值。
    数组指针只是一个指针变量,它占有内存中一个指针的存储空间。
    指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

    展开全文
  • 一级指针二级指针

    千次阅读 2019-08-17 23:34:36
    一、一级指针 如下图所示,整型指针xptr指向变量x的地址。 int *xptr; int x=10; xptr = &x; 源码: #include <stdio.h> int main() { int *xptr = NULL; int x = 10; xptr = &x; printf...

    一、一级指针

    如下图所示,整型指针xptr指向变量x的地址。

    int *xptr;
    int x=10;
    
    xptr = &x;
    
    
    

    在这里插入图片描述
    源码:

    #include <stdio.h>
    int main()
    {
        int *xptr = NULL;
        int x = 10; 
    
        xptr = &x; 
    
        printf("x = %d, *xptr = %d\n", x, *xptr);
        printf("&x = %p, xptr = %p\n", &x, xptr);
    
        return 0;
    }
    
    
    

    在这里插入图片描述

    二、二级指针

    实现方法一
    如下图所示,先为二级整型指针ptr分配空间,然后赋值。

    int  **ptr=NULL;
    int num=4, size=4, i,j;
    
    ptr = (int **)malloc(num*sizeof(int*));
    for(i=0; i<num; ++i)
    {
    	*(ptr+i) = (int *)malloc(size*sizeof(int));
    	*(*(ptr+i) +j)=(i+1)*j;
    }
    
    
    

    在这里插入图片描述
    源码:

    #include <stdio.h>
    #include <stdlib.h>                                                                                                                    
    int main()
    {
        int **ptr = NULL;
        int num=4, size=4, i, j;
        
        ptr = (int **)malloc(num * sizeof(int *));
        for(i=0; i<num; ++i)
        {   
      		*(ptr+i) = (int *)malloc(size * sizeof(int));
      		for(j=0; j<size; ++j)
      		*(*(ptr+i)+j) = (i+1)*j;
        }   
        for(i=0; i<num; ++i)
        {   
            for(j=0; j<size; ++j)
            {
            	printf("(%d, %d) -> %d\t", i, j, *(*(ptr+i)+j));
            }   
            printf("\n");
        }   
        return 0;
    }
    
    

    运行结果:
    在这里插入图片描述
    实现方法二
    如下图所示,先为二级整型指针ptr分配空间,然后赋值。
    与实现方法一的不同之处,在于使用数组形式就行相关操作。

    int  **ptr=NULL;
    int num=4, size=4, i;
    
    ptr = (int **)malloc(num*sizeof(int*));
    for(i=0; i<num; ++i)
    {
    	ptr[i]= (int *)malloc(size*sizeof(int));
    	ptr[i][j]=(i+1)*j;
    }
    
    
    

    在这里插入图片描述
    源码:

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
        int **ptr = NULL;
        int num=4, size=4, i, j;
    
        ptr = (int **)malloc(num * sizeof(int *));
        for(i=0; i<num; ++i)
        {
        	ptr[i] = (int *)malloc(size * sizeof(int));
        	for(j=0; j<size; ++j)
        	{
        		ptr[i][j] = (i+1)*j;
        	}
        }   
        for(i=0; i<num; ++i)
        {   
            for(j=0; j<size; ++j)
            {   
                printf("[%d, %d] -> %d\t", i, j, ptr[i][j]);                                                                
            }   
            printf("\n");
        }   
    
        return 0;
    }
    
    
    

    运行结果:
    在这里插入图片描述

    先看两个例子:

    *p和**p的区别
    int *p :一级指针,表示p所指向的地址里面存放的是一个int类型的值
    int **p :二级指针,表示p所指向的地址里面存放的是一个指向int类型的指针(即p指向的地址里面存放的是一个指向int的一级指针)
    例如:
    int i=10; //定义了一个整型变量
    int *p=&i; //定义了一个指针指向这个变量
    int **p1=&p; //定义了一个二级指针指向p指针
    那么取出10的值方式为:
    printf(“i=[%d]\n”,*p);
    printf(“i=[%d]\n”,**p1);

    void test(char *p)
    
    {
    
           printf("[test1][p]:%p.\n",p);
    
           printf("[test2][p]:%s.\n",p);
    
           p=(char *)malloc(10);
    
           strcpy(p,"ABCDE");
    
           printf("[test3]malloc之后.....\n");
    
           printf("[test4][p]:%p.\n",p);
    
           printf("[test5][p]:%s.\n",p);
    
           free(p);
    
    }
    
     
    
    int main()
    
    {
    
           char b[6] = "abcde";
    
           char *a = b;
    
           printf("[main1][a]:%p.\n",a);
    
           printf("[main2][a]:%s.\n",a);
    
           test(a);
    
           printf("[main3][a]:%p.\n",a);
    
           printf("[main4][a]:%s.\n",a);
    
           return 0;
    
    }
    
    

    输出结果: 注意:(test函数的pde值已改变,main函数的a的值未改变)

    main1][a]:0xbfeaaef6.
    [main2][a]:abcde.
    [test1][p]:0xbfeaaef6.
    [test2][p]:abcde.
    [test3]malloc之后…
    [test4][p]:0x8a52008.
    [test5][p]:ABCDE.
    [main3][a]:0xbfeaaef6.
    [main4][a]:abcde.

    void test(char **p)
    
    {
    
           printf("[test1][p]:%p.\n",p);
    
           printf("[test2][*p]:%p.\n",*p);
    
           *p=(char *)malloc(10);
    
           strcpy(*p,"ABCDE");
    
           printf("[test3]malloc之后.....\n");
    
           printf("[test4][p]:%p.\n",p);
    
           printf("[test5][*p]:%p.\n",*p);
    
           printf("[test6][*p]:%s.\n",*p);
    
           free(*p);
    
    }
    
    
    
     
    
    int main()
    
    {
    
           char b[6] = "abcde";
    
           char *a = b;
    
           printf("[main1][a]:%p.\n",a);
    
           printf("[main2][a]:%s.\n",a);
    
           test(&a);
    
           printf("[main3][a]:%p.\n",a);
    
           printf("[main4][a]:%s.\n",a);
    
           return 0;
    
    }
    
    

    输出结果: 注意:(test函数的pde值已改变,main函数的a的值也已经改变)

    [main1][a]:0xbfaca776.
    [main2][a]:abcde.
    [test1][p]:0xbfaca770.
    [test2][*p]:0xbfaca776.
    [test3]malloc之后…
    [test4][p]:0xbfaca770.
    [test5][*p]:0x9132008.
    [test6][*p]:ABCDE.
    [main3][a]:0x9132008.
    [main4][a]:ABCDE.

    三、形参和实参的概念?

    实参:实实在在的参数,我们自己定义的,比如以上程序中指针a和数组b都是实参,都是自己定义的,基本程序中花括号内定义的所有参数都是实参

    形参:我们定义一个函数时,括号内的参数,比如以上程序中的char *p和char **p中的p就是形参,主要是为了让实参的数据可以传递到函数内,供函数操作

    四、参数传递的实质?

    参数的传递分为两种,一种是值传递,另一种是引用;我们这里说的只主要是值传递,暂时不说引用传递;值传递又分为两种:一种是实际的值传递,int类型的参数传递属于实际值传递;另一种就是地址值传递,实参比实际地址传递给形参,比如指针就是地址值传递。

    这里是参数传递的重点,当实参把实际值或者地址值传递给形参时,实际上不是直接使用实参,而是在栈去开辟内存空间copy一个副本,int a的副本是_a(_a=a),,char *p的副本是_p(_p=p), 所以函数内的操作都是对副本进行操作,改变形参的值不会影响实参的值,函数执行完就释放副本开辟的空间。

    五、为什么要用指向指针的指针?

    指针的概念,指针也是一个参数,和int及char类似,int 参数存放整数,char参数存放字符,指针存放的是一个地址而已;指针就是保存一片内存的起始地址,知道这个指针就可以对这个指针指向的内存进行操作;指向指针的指针即二级指针保存的是一级指针的地址,比如:
    在这里插入图片描述
    p是一级指针,保存的是a的地址;q是指向指针的指针(二级指针),保存的是一级指针(p)的地址;q的内容就是0xbfaca770,q的值即q指向的内容0xbfaca776,即q仍然是一个地址,也就是指针p的内容,即q=p,(好好理清楚),对q操作就是对p指向的内存操作;为什么要使用二级指针呢?下面会有讲述:

    六、为什么第一个程序不能改变a的值,而第二个程序却可以?

    第一个程序:

    我们先看看调用test函数前后,以及malloc之前和malloc之后的指针p的和指针a的地址以及指向情况:

    之前的指向情况:(方块上面是当前变量的地址,方块内是当前变量的值)
    在这里插入图片描述
    之后的指向情况: (方块上面是当前变量的地址,方块内是当前变量的值)
    在这里插入图片描述
    从之前的情况可以看出,函数进行参数传递时,实参把地址传给了形参p(p即是a的副本(_a),p=_a是为了表达更直观,并不会产生变量名_a),两个指针同时指向一片内存;使用malloc之后,空出一遍新内存并把地址赋给p,即p的指向改变,指向了新地址;所以test内对p的内容进行改变不会改变a的值。

    第二个程序:

    同样先看看调用test函数前后,以及malloc之前和malloc之后的指针p的和指针a的地址以及指向情况:

    之前的指向情况:
    在这里插入图片描述
    之后的情况:
    在这里插入图片描述
    好了,我们来看一下,test函数的形参使用的是二级指针,我们把a的地址传给了p,即p指向了a;指针a指向的是数组b,即保存的是b的首地址,见第二个程序第一张图;二级指针p指向一级指针a,所以p的值就是a的首地址,所以改变p的内容就是改变a的内容,即改变a的指向;当malloc一段内存并把首地址保存在p的内容中,就是把malloc内存的首地址直接替换指针a原来的内容,所以a指针的指向发生了改变,见第二个程序第二张图;所以改变p就是改变a的值(要理解*p和a就是同一个变量);

    所以要对实参传进来的指针进行直接操作的话,就可以使用二级指针,把实参的地址传给二级指针,通过二级指针去改变一级指针的值。

    展开全文
  • 指针赋值

    一级指针:指向一段内存
    1、内存变量:a 、*p1;
    2、内存地址:&a、 p1;
    3、指针自身地址: &p1;

    二级指针:指向指针p1的指针p2,
    1、内存变量:a 、*p1 、**p2;
    2、内存地址:&a、 p1、*p2;
    3、指针p1自身地址: &p1、p2;
    4、指向指针p1的指针p2的地址:&p2;

    #define _CRT_SECURE_NO_WARNING
    #include<stdlib.h>
    #include<string.h>
    #include<stdio.h>
    #include<iostream>
    using namespace std;
    
    
    void main()
    {
    	//声明一个指针,并初始化
    	int *p1 = NULL;
    	//声明一个二级指针,并初始化
    	int **p2 = NULL;
    	//声明变量a,并初始化
    	int a = 98;
    	//int b = 100;
    	
    	//把a的地址赋值给p1
    	p1 = &a;
    	//把p1的地址赋值给p2, 那么(*p2)就是p1的值,即a的地址,(**p2)就是变量a的值
    	p2 = &p1;
    
    	cout << "p2(p1的地址): " << p2 << endl;
    	cout << "p1的地址: " << &p1 << endl;
    	cout << "。。。。。\n";
    
    	cout << "*p2(p1的值、a的地址): " << *p2 << endl;
    	cout << "p1(a的地址): " << p1 << endl;
    	cout << "&a : " << &a << endl;
    	cout << "。。。。。\n";
    
    	cout << "**p2(a的值): " << **p2 << endl;
    	cout << "*p1(a的值): " << *p1 << endl;
    	cout << "a : " << a << endl;
    
    	system("pause");
    	return;
    }
    
    展开全文
  • 在数据结构中存在着大量的二级指针这体现了指针与指针之间的关系。 首先要知道一级指针只能用于存放普通变量的地址和一级指针地址。 二级指针只能存放指针的地址和二级指针地址。 同样的三级 甚至是多级指针能...

    在数据结构中存在着大量的二级指针这体现了指针与指针之间的关系。

    首先要知道一级指针只能用于存放普通变量的地址和一级指针地址。

    二级指针只能存放指针的地址和二级指针地址。

    同样的三级 甚至是多级指针能存放的是他前一级指针的地址以及同级指针地址。

    int a=5;

    int *m=Null

    int **p=null;

    int **p=null;

    m=&a;   /  /正确一级指针指向int变量m的内存

    m=&p;    //错误一级指针不能指向二级指针的地址

    p=&m;      //正确二级指针指向一级指针的地址

    p=&a;     // 错误二级指针不能指向int 变量的地址

    当我们要在一个函数中改变一个一级指针所保存的值(地址)的时候我们需要用一个二级指针的形参(参量)来保存实参(参数)的地址,这样我们就能够通过对二级指针解引用(二级指针所保存的地址也就是一级指针的地址)这样我们就能够操作实参的地址来进行修改他的值;

    如图:

    在调用函数的时候会把实参的地址赋值给二级指针变量p=&q=001;我们可以通过二级指针解引用来操作实参例如:

    *P:地址001对应的内容我们可以吧一个地址赋值给*p。

    *p=003;

    对应内存模型为:

    这样我们就能通过二级指针来操作一级指针了,同样我们还能通过二级指针来操作003地址所对应的内容(此时该内容是一个int行变量存放的值,int指针只能指向int变量(不考虑强制内存转换))。

    例如我们在函数中为结构体指针分配内存:

    下面看看利用一级指针形参保存一级指针实参地址情况

    可以看出我们在get、函数中并没有修改到mian中的S的值。

    更多用法自行体会。。。。

    转载请标明原贴出处:https://blog.csdn.net/zj490044512

    展开全文
  • 昨夜,偶遇题,初时甚简,遂乐,不料结果相差毫厘之间。看答案,断点调试竟不能得出原因。改之亦无法,故断然求解于一学长,学长思虑再三,无解。于是,吾今早求助吾师,师看了几眼,变得结果。吾大惑,感学问之境...
  • 三大指针:行指针、指针数组、二级指针

    千次阅读 多人点赞 2017-06-07 00:43:44
    在介绍三个指针之前,一定要牢记下面这个图,也就是二级指针的概念。 1、行指针:数据类型(*p)[m]; 定义:指向由m个元素组成的维数组的行指针变量 经测试,不能直接指向维数组,如: int a[3];
  • 二级指针:int **ptr; 现在开始分析一下: 二维数组名为a,而二维数组名的实际含义是什么:a实际是二维数组第行的首地址,为什么呢,现在来看: a = &(*(a + 0)) = &(a[0])= &a[0],这样看就明显了...
  • 详细的讨论了指针,解引用,取地址,引用,二级指针
  • c语言二级指针与二维数组

    千次阅读 2019-05-20 15:00:56
    、二维数组的地址不能赋给二级指针的原因 int arr[][3] = { { 1,2,3 },{ 4,5,6 },{ 7,8,9 } }; int** p = arr; 二、指针遍历二维数组 int* p1 = arr; for (int i = 0; i < sizeof(arr)/sizeof(arr[0][0]); ...
  • 引用博文:...当指针作为函数参数传递时,在函数内部重新申请了个新指针,与传入指针指向相同地址。在函数内部的操作只能针对指针指向的值。#include &lt;iostream&gt; using namespace st...
  • #include #include #include #include int a=10,b=20; change(int *p) { p=&b; } changepp(int **pp) { *pp=&b; } int main() { int *p=&a; change(p); printf("%d\n",*p);... changepp(&p
  • 给指针赋一个int类型,表示这个指针内存放的内存地址所指向的值是个int值 *加上指针变量名就代表指针中内存地址所指向的值,如下解释: //变量a的值为10 int a = 10; //指针pointer的值为变量a的内存地址 //*...
  • 二级指针

    千次阅读 多人点赞 2018-06-01 15:53:32
    什么是“指针”:在执行C程序的时候,由于我们的数据是存储在内存中的。所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的内存地址是多少,换言之,C程序通过已知的内存地址到相应的内存...
  • 关于C语言中的数组指针、指针数组以及二级指针

    万次阅读 多人点赞 2017-02-05 19:14:18
    概念解释数组指针:首先它是个指针,它指向个数组,即指向数组的指针;在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道。数组指针指向的是数组中的个具体元素...二级指针 : 如果个指针指
  • 函数参数的传递问题(一级指针二级指针) [转] 原以为自己对指针掌握了,却还是对这个问题不太明白。请教!  程序1:  void myMalloc(char *s) //我想在函数中分配内存,再返回  {   s=(char *) ...
  • 本博文为半摘记性质,收集整理自菜鸟教程、《二级C》及其他互联网资料 —— 本文要点: 1. 指针作为函数参数 2. 指向维数组的指针以及指针数组 3. 指向函数的指针 —— 1. 指向变量的指针/指针变量 2. 指向数组的...
  • 注意指针变量只是个特殊的变量,实际上它存的是整数值,但是它是内存中的某个地址。通过它可以访问这个地址。   程序2: void myMalloc(char **s) {  *s=(char *) malloc(100); } ...
  • 二级指针详解

    千次阅读 2014-03-08 19:56:15
    例1:void test(int *b) { *b = 10; } int main() { int a = 5; test(&a);...首先,看这个简单的函数,通过把实参变量a的地址...在传址中,主子函数关系为将实参的地址传形参后,子函数的形参就能够操控主函数中的
  • 二级指针: 指向指针的指针 char* *p 该指针的存储类型为char* 即个字符指针 指针数组: 数组元素为指针的数组 char* arr[] 内部存储多个char* 指针 #include <stdio.h> #include <stdlib.h> #include ...
  • #include /* 在gcc  */ int main(void) { int a[3][4] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};...//定义指针数组,里面从放维数组的3个首地址三个首地址即使 /* *存放维数组的三个地
  • 目录 一.变量的内存实质到 1.1变量的实质 ...3.2.1.改变一级指针指向 3.2.2改变 N-1 级指针的指向 3.2.3二级指针的步长 四. 指针与数组 4.1 指针与数组名 4.1.1 通过数组名访问数组元素 4....
  • 链表二级指针问题前提知识变量内存中都有自己的地址初始化链表需要双指针使用双指针情况使用单指针情况 前提知识 这个问题比较像函数传递时的值传递和引用传递类似,具体可以看下面两段代码,方便理解后面双指针。...
  • 指针参数传递实质及二级指针使用

    千次阅读 多人点赞 2016-10-01 20:59:23
    水平有限,如有错误,欢迎指正,谢谢。 先看两个程序 : ...所以要对实参传进来的指针进行直接操作的话,就可以使用二级指针,把实参的地址传给二级指针,通过二级指针去改变一级指针的值。
  • 二级指针的两种用法

    千次阅读 2013-02-05 22:53:25
    函数形参什么时候用二级指针,什么时候用一级指针二级指针作为函数参数,有两种典型情况: 1.需要传递一级指针的数组时: 例如标准C的main函数: int main(int argc, char* argv []),数组最高维可以退化,...
  • c语言二级指针

    千次阅读 2018-12-13 09:51:41
    二级指针做输入_第1种内存模型 直接利用二级指针 首先看指针数组(变量为指针) 也就是数组中存的都是地址 #include&lt;stdio.h&gt; void main() { int i = 0, j = 0; int num = 0; char *myArray[] ...
  • c++中的悬浮指针和野指针 二级指针

    千次阅读 2014-10-06 20:28:18
    c++中的悬浮指针:声明了但没有被付值的指针,它指向内存中的任意个空间。避免悬浮指针个方法是开始就付值为NULL  “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if...
  • 深入理解C语言指针

    万次阅读 多人点赞 2019-09-28 08:36:51
    指针的概念 要知道指针的概念,要先了解变量在内存中如何存储的。在存储时,内存被分为块的。每块都有个特有的编号。而这个编号可以暂时理解为指针,就像酒店的门牌号一样。 1.1、变量和地址 先写段...
  • 利用二级指针进行链表操作

    千次阅读 多人点赞 2018-10-19 10:27:38
    常规的链表删除除了当前的遍历指针还需要维护个prev指针,用来连接被删除节点的下个节点,但实际上利用二级指针就可以避免多维护个指针,使代码更加简洁。Linus的吐槽没错,到目前为止,我几乎没有在实际工作...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,383
精华内容 14,953
关键字:

一级指针赋给二级指针