精华内容
下载资源
问答
  • 比如: buf:pointer//缓存指针;...只给出指针,如果在不复制指针后面的数据的情况下,如何将buffer[1]后面的数据提取出来 copymemroy(@Login,@buf^[1],sizeof(TLogin));//这样是错的。不知道怎么写。
  • void的意思就是“无类型”,void指针则为“无类型指针”,void指针可以指向任何类型的数据。 所以void指针一般被称为通用指针或者泛指针,或者叫做万能指针 void的意思就是“无类型”,void指针则为“无类型指针”...

    概念

        void指针
        数据指针

    void指针

    void指针的基本概念

    void的意思就是“无类型”,void指针则为“无类型指针”,void指针可以指向任何类型的数据。
    所以void指针一般被称为通用指针或者泛指针,或者叫做万能指针

    void的意思就是“无类型”,void指针则为“无类型指针”,void指针可以指向任何类型的数据。
    所以void指针一般被称为通用指针或者泛指针,或者叫做万能指针

    定义形式 :
    void *p;

    **在C语言中在任何时候都可以用void类型的指针来代替其他类型的指针,void指针可以指向任何数据类型的变量**
    **如果要通过void指针去获取它所指向的变量值时候,需要先将void指针强制类型转换成和变量名类型想匹配的数据类型指针后再进行操作;**

    指针的强类类型转化:
        void  *p;
        int *pa = (int *)p;
        然后才能对原来的void指针指向的空间进行操作
    任何类型的指针都可以赋值给void指针,无需进行强制类型转换;
        float f = 1.22f;
        float *p1 = &f;
        p = p1;//将float指针赋值给p

     

    void指针的应用场合:
    当进行纯粹的内存操作的时候,或者传递一个指向未定类型的指针时,可以使用void指针;
    void* memcpy(void *addr1,void *addr2,size_t n);
    该函数只进行纯粹的内存拷贝,包括NULL字符在内的任何内容都将被拷贝

    1:对函数参数的限定
    2:对函数返回的限定
    3:void指针也常用作函数指针

      

    1:对函数参数的限定
    2:对函数返回的限定
    3:void指针也常用作函数指针

    代码如下所示:

    #include<stdio.h>

    int main(void)
    {
        int num1 = 1;
        char char1 = 'b';

        /*定义两个void指针类型*/
        void *void_pointer_1;
        void *void_pointer_2;

        /*给不同的void指针指向不同的数据类型*/
        void_pointer_1 = &num1;
        void_pointer_2 = &char1;

        printf("void_pointer_1:%d,void_pointer_2:%c\n",*((int *)void_pointer_1),*((char *)void_pointer_2));

        void_pointer_2 = &num1;
        printf("void_pointer1:%d\n",*((int *)(void_pointer_2)));

        float float_1 = 1.25f;
        float* float_pointer = &float_1;
        void* void_float_pointer ;
        /**将float类型指针赋值给void类型指针*/
        void_float_pointer = float_pointer;

        printf("float_pointer:%f\n",*((float *)void_float_pointer));

        return 0;
    }

    数据指针

    数据指针的概念:
    在嵌入式编程当中,可能在特定的内存但愿读写内容,汇编有对应的MOV命令,而除了C/C++以外的编程语言基本上没有直接访问内存的能力
    利用数据指针可直接 通过内存地址操作特定的内存

    如:在地址0XFF00FF00对应的内存但愿中写入11
    unsigned int *p = (unsigned int *)0XFF00FF00;
    *p = 11;

    如:在地址0XFF00FF00对应的内存但愿中写入11
    unsigned int *p = (unsigned int *)0XFF00FF00;
    *p = 11;

    数据指针操作特定的内存的时候一定要谨慎,不是所有内存都可以操作,必须要对硬件比较了解后,才能进行操作(可能会出现段错误)

    代码能够run,如果有需要的话,可以直接拉下来run一下,看看结构体数组是怎么进行初始化操作和使用的。谢谢大家的访问,如有写的不好的地方,希望大家能够及时的提出来,谢谢观看
     

    展开全文
  • C/C++指针是个什么鬼? 带着这个问题我们开始, 为什么只有C/C++ (Objective-C 也有指针,也就是C语言的面向对象版本, 所以Objective-C 与c/c++完全通用,oc项目直接添加.c/.cpp文件,这TM扯远了,有机会还是...

    C/C++指针是个什么鬼?

    带着这个问题我们开始, 为什么只有C/C++ (Objective-C 也有指针,也就是C语言的面向对象版本,

    所以Objective-C 与c/c++完全通用,oc项目直接添加.c/.cpp文件,这TM扯远了,有机会还是专门写一篇来讲一下oc指针vs c++指针),其它语言c#/java 都没有这个niao东西,以至学习其它语言的同学

    看到c/c++代码的指针时,那真TM是 “雪花飘飘,北风萧萧”,心里一万个cnm在奔腾!

    指针的定义:

    指针:百度告诉我的,我特么也不是特别明白,来看!

    在信息工程中,指针是一个用来指示一个内存地址的计算机语言的变量或中央处理器(CPU)中的寄存器(Register)。

    1.基本概念

    指针一般指向一个函数或一个变量。在使用一个指针时,一个程序既可以直接使用这个指针所储存的内存地址,又可以使用这个地址里储存的函数的值。

    在计算机语言中,由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。

    有了这个概念呢,那么就理解一点点啦!

    就是说指针这个东西啊, 实际呢,就是一个地址,就是开发编译器这些人想出来的这么一个东西,搞编译器的人肯定是NB的,方方面面都要考虑到,要搞泛化,要开放给开发者一个东西,或者标识而设计出来的这么一个东西!

    说这么多就是总结一句话: 指针就是一个内存地址,是c/c++这种高级语言虚拟出来的一个东西,

    实际低级语言(机器语言/汇编语言)tm和整数差不多就是一样,一个东西!

    来看代码:

    看代码之前呢,你要知道哈,c/c++呢 对变量或函数呢,以tm分声明与定义 ,这个要讲的话,又会扯远了,dan疼,写了一小时了,才

    写出这么点毛毛来 ,惭愧!

    看声明:

    基本数据类型哈

    int* pintval ; int* pintval =nullptr; //指向int类型变量的指针

    double* pintval ; double* pintval =nullptr; //指向double类型变量的指针

    char* pintval ; char* pintval =nullptr; //指向char类型变量的指针

    以上是声明啊!

    那能不能这样写呢

    int* pintval=5;

    double* pintval=8.8;

    指针变量的初始化

    存储类型 数据类型 *指针名=初始地址;

    必须要是一个地址,这就和上面说的它就是一个地址对应起来了, 5,8.8还是一个常数,还没有开辟内存空间,所有没法用指针表示!

    正确要这么写 int intval=5; int* pintval=&intval; 加&就表示地址,具体原因呢,我也不知道,我也不敢问啦!

    int intval=5; 表示定义了这么一个变量, 既然是变量那么就要向操作系统申请内存啦,那么呢,申请了内存了是不是(得像我们人一样

    弄个名字呢),而计算机呢都是以数字作名字, 操作系统 呢随机最一个位置0x40001234 ,让你呢把数据5呢放在这, 那这个时候呢

    pintval 通过这句pintval=&intval,指向的就是这个0x40001234, 然后呢他的数据就是5,这样说可能表达不清,其实这个最好能调试让

    你们看下反汇编 !

    以上这句总结出来就是 pintval=0x40001234; *pintval =5;

    *pintval 官方语法说是 “解引用”, 我tm不懂那么多,就叫取值!

    不知道你理解了没有。。。 是不是真的难懂!

    指针变量的赋值运算

    指针名=地址

    注意:“地址”中存放的数据类型与指针类型必须相符

    • 向指针变量赋的值必须是地址常量或变量,不能是普通整数,例如:

      • 通过地址运算“&”求得已定义的变量和对象的起始地址

      • 动态内存分配成功时返回的地址

    那么我们定义一个指令要怎么赋值呢

    int* pintval = new int(); //c++模式

    int* pintval = new int; //c++模式

    int* pintval = (int*)malloc( sizeof(int)); //c模式

    以上呢就是为了分配内存空间,然后呢你就可以给值了, *pintval =5;

     

    总结:1. 指针就是一个地址

    2.指针的赋值呢(要么自己分配空间,要么呢用别人分配好的,然后你指向它),are you ok?

    这一篇就讲到这里,下篇接着来,还有好多,数组指针,函数指令,二级指针,void指针,this指针等 都会讲!

    反正就是要讲到你受不了!

    展开全文
  • 下图是我用res.data打印出来的,我想获取data数组里面数据,id跟name。然后赋值出来刚刚问题不够详细,现在补充一下我用console.log(res.data.data[1].name)跟用console.log(res.data.data[1].name)打印出来的就是...

    4c09fc24c9db3d0a277e42bac9c93a3e.png

    下图是我用res.data打印出来的,我想获取data数组里面的数据,id跟name。

    然后赋值出来

    52ce9b9897e3955aba4ba52f62c8cecf.png

    刚刚问题不够详细,现在补充一下

    我用console.log(res.data.data[1].name)

    跟用console.log(res.data.data[1].name)

    打印出来的就是我要的东西。不过我要把全部一次性取出来。该怎么做for循环。

    回答

    一个可能:

    res.data 是数据的指针,打印时没有数据,等到展开的时候已经异步填充好了

    如果是这样的话,需要确定异步取 res.data.data 数据的时机

    建议补充一下 log 的时候,res.data.data 返回是什么

    如果要遍历数组的话,for-loop / forEach / while 都行的:

    res.data.data.forEach(item => {

    console.log(item.id, item.name)

    })

    for (let i = 0; i < res.data.data.length; i += 1) {

    console.log(res.data.data[i].id, res.data.data[i].name)

    }

    let i = 0

    while (i < res.data.data.length) {

    console.log(res.data.data[i].id, res.data.data[i].name)

    i += 1

    }

    如果有帮到你,可以点赞采纳打赏哦~

    直接用res.data.data就可以吧?

    data = {data: [{},{}]}

    {data: Array(2)}

    data.data

    (2) [{…}, {…}]

    console.log(…res.data.data)

    展开全文
  • 指针

    万次阅读 多人点赞 2019-07-28 22:08:42
    通过指针变量取得数据 3.关于*和& 二、指针变量运算(加法、减法、比较运算) 三、数组指针(指向数组的指针) 假设 p 是指向数组 arr 中第 n 个元素的指针,那么 *p++、*++p、(*p)++ 分别是什么意思呢? 四...

    目录

    一、指针变量的定义和使用

           1.定义指针变量

           2.通过指针变量取得数据

           3.关于*和&

    二、指针变量运算(加法、减法、比较运算)

    三、数组指针(指向数组的指针)

           假设 p 是指向数组 arr 中第 n 个元素的指针,那么 *p++、*++p、(*p)++ 分别是什么意思呢?

    四、字符串指针(指向字符串的指针)

           字符数组&&字符串常量

    五、数组灵活多变的访问形式

    六、指针变量作为函数参数

    七、指针作为函数返回值

    八、二级指针(指向指针的指针)

    九、空指针NULL与void指针

           1.空指针NULL

           2.void 指针

    十、数组≠指针

           1.数组在什么时候会转换为指针

           2.关于数组和指针可交换性的总结

    十一、C语言指针数组(每个元素都是指针)

    十二、函数指针(指向函数的指针)

    十三、总结


     

           所谓指针,也就是内存的地址;所谓指针变量,也就是保存了内存地址的变量

           需要注意的是,虽然变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符,但在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名字符串名数组名表示的是代码块或数据块的首地址

    一、指针变量的定义和使用

           数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量

           在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。指针变量的值就是某份数据的地址,这样的一份数据可以是数组、字符串、函数,也可以是另外一个普通变量或者指针变量。

           假设有一个char类型的变量c,它存储了字符'K',并占用了地址为0x11A的内存(地址通常用十六进制表示)。另外有一个指针变量p,它的值为0x11A,正好等于变量c的地址,这种情况我们就称p指向了c,或者说p是指向变量c的指针。

           1.定义指针变量

           定义指针变量与定义普通变量非常类似,不过要在变量名前面加星号*,格式为:

    datatype *name;  或者  datatype *name = value;
    其中,*表示这是一个指针变量,datatype表示该指针变量所指向的数据的类型。

           *是一个特殊符号,表明一个变量是指针变量,定义指针变量时必须带*。而给指针变量赋值时,因为已经知道了它是一个指针变量,就没必要多此一举再带上*,后边可以像使用普通变量一样来使用指针变量。也就是说,定义指针变量时必须带*,给指针变量赋值时不能带*

    int *p1;//p1 是一个指向 int 类型数据的指针变量
    
    int a = 100;
    int *p_a = &a;//在定义指针变量 p_a 的同时对它进行初始化,并将变量 a 的地址赋予它,此时 p_a 就指向了 a。值得注意的是,p_a 需要的一个地址,a 前面必须要加取地址符&,否则是不对的。
    
    //定义普通变量
    float a = 99.5, b = 10.6;
    char c = '@', d = '#';
    //定义指针变量
    float *p1 = &a;
    char *p2 = &c;
    //修改指针变量的值
    p1 = &b;
    p2 = &d;
    //*是一个特殊符号,表明一个变量是指针变量,定义 p1、p2 时必须带*。而给 p1、p2 赋值时,因为已经知道了它是一个指针变量,就没必要多此一举再带上*,后边可以像使用普通变量一样来使用指针变量。也就是说,定义指针变量时必须带*,给指针变量赋值时不能带*。
    注:需要强调的是,p1、p2 的类型分别是float*和char*,而不是float和char,它们是完全不同的数据类型,要引起注意。

           指针变量也可以连续定义:

    int *a, *b, *c;  //a、b、c 的类型都是 int*
    注意每个变量前面都要带*。如果写成下面的形式,那么只有 a 是指针变量,b、c 都是类型为 int 的普通变量:
    int *a, b, c;

           2.通过指针变量取得数据

           指针变量存储了数据的地址,通过指针变量能够获得该地址上的数据,格式为:

    *pointer;  其中,*称为指针运算符,用来取得某个地址上的数据,

      *在不同的场景下有不同的作用:*可以用在指针变量的定义中,表明这是一个指针变量,以和普通变量区分开;使用指针变量时在前面加*表示获取指针指向的数据,或者说表示的是指针指向的数据本身。 

    //通过指针变量取得数据
    #include <stdio.h>
    int main(){
    	int a = 15;
    	int *p = &a;
    	printf("%d,%d\n",a,*p);//两种方式均可输出a的值
    	return 0;
    }
    //运行结果:15,15
    //解析:假设 a 的地址是 0X1000,p 指向 a 后,p 本身的值也会变为 0X1000,*p 表示获取地址 0X1000 上的数据,也即变量 a 的值。从运行结果看,*p 和 a 是等价的。

           我们知道CPU 读写数据必须要知道数据在内存中的地址,普通变量和指针变量都是地址的助记符,虽然通过 *p 和 a 获取到的数据一样,但它们的运行过程稍有不同:a 只需要一次运算就能够取得数据,而 *p 要经过两次运算,多了一层“间接”。
           假设变量 a、p 的地址分别为 0X1000、0XF0A0,它们的指向关系如下图所示:

           程序被编译和链接后,a、p 被替换成相应的地址。使用 *p 的话,要先通过地址 0XF0A0 取得变量 p 本身的值,这个值是变量 a 的地址,然后再通过这个值取得变量 a 的数据,前后共有两次运算;而使用 a 的话,可以通过地址 0X1000 直接取得它的数据,只需要一步运算。也就是说,使用指针是间接获取数据,使用变量名是直接获取数据,前者比后者的代价要高。

    //指针修改内存上的数据
    #include <stdio.h>
    int main(){
    	int a = 15, b = 99, c = 222;
    	int *p = &a;//定义指针变量
    	*p = b;//通过指针变量修改内存上的数据
    	c = *p;//通过指针变量获取内存上的数据
    	printf("%d, %d, %d, %d\n",a,b,c,*p);
    	return 0;
    }
    //运行结果:15,15
    //解析:p指向a,这时*p值为15,*p=b,内存上的值变为99,此时a中的值也变为99。最后c=*p,c中的值也变为99

            定义指针变量时的 * 和使用指针变量时的 * 区别: 

    int *p = &a;//*用在指针变量的定义中,表明这是一个指针变量,以和普通变量区分开;
    *p = 100;//在指针变量前面加*表示获取指针指向的数据
    
    需要注意的是,给指针变量本身赋值时不能加*,如:
    int *p;
    p = &a;//如果写成*p = &a,报错!!!
    *p = 100
    //通过指针交换两个变量的值
    #include <stdio.h>
    int main(){
    	int a = 100, b = 999, temp;
    	int *pa = &a, *pb = &b;
    	printf("a=%d,b=%d\n", a, b);
    	//开始交换
    	temp = *pa;
    	*pa = *pb;
    	*pb = temp;
    	//结束交换
    
    	printf("a=%d,b=%d\n", a, b);
    	return 0;
    }
    //运行结果:
    a=100,b=999
    a=999,b=100

           3.关于*和&

    int a;
    int *p = &a;
    *&a表示什么?*&a可以理解为*(&a),&a表示取变量a的地址(即p),*(&a)表示取这个地址上的数据(即*p),绕来绕去,*&a仍然等于a。
    &*p表示什么?&*p可以理解为&(*p),*p表示取得p指向的数据(即a),&(*p)表示数据的地址(即&a),所以等于p。

           星号*主要有三种用途:

           ①表示乘法,例如int a = 3, b = 5, c;  c = a * b;,这是最容易理解的。

           ②表示定义一个指针变量,以和普通变量区分开,例如int a = 100;  int *p = &a;

           ③表示获取指针指向的数据,是一种间接操作,例如int a, b, *p = &a;  *p = 100;  b = *p;

    二、指针变量运算(加法、减法、比较运算)

           指针变量保存的是地址,而地址本质上是一个整数,所以指针变量可以进行部分运算,例如加法、减法、比较等。但是不能对指针变量进行乘法、除法、取余等其他运算,除了会发生语法错误,也没有实际的含义。

    #include <stdio.h>
    int main(){
    	int a = 10, *pa = &a, *paa = &a;
    	double b = 99.9, *pb = &b;
    	char c = '@', *pc = &c;
    	//最初的值
    	printf("&a=%#X,&b=%#X,&c=%#X\n",&a,&b,&c);
    	printf("pa=%#X,pb=%#X,pc=%#X\n",pa,pb,pc);
    	//加法运算
    	pa++; pb++; pc++;
    	printf("pa=%#X,pb=%#X,pc=%#X\n",pa,pb,pc);
    	//减法运算
    	pa -= 2; pb -= 2; pc -= 2;
    	printf("pa=%#X,pb=%#X,pc=%#X\n",pa,pb,pc);
    	//比较运算
    	if (pa == paa){
    		printf("%d\n", *paa);//比较的是指针变量本身的值,也就是数据的地址。如果地址相等,那么两个指针就指向同一份数据.
    	}
    	else{
    		printf("%d\n",*pa);
    	}
    	return 0;
    }
    //运行结果:
    &a=0X98FB00,&b=0X98FAD8,&c=0X98FAC3
    pa=0X98FB00,pb=0X98FAD8,pc=0X98FAC3
    pa=0X98FB04,pb=0X98FAE0,pc=0X98FAC4
    pa=0X98FAFC,pb=0X98FAD0,pc=0X98FAC2
    -858993460

    三、数组指针(指向数组的指针)

           数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存。以int arr[] = { 99, 15, 100, 888, 252 };为例,该数组在内存中的分布如下图所示:

           定义数组时,要给出数组名和数组长度,数组名可以认为是一个指针,它指向数组的第 0 个元素。在C语言中,我们将第 0 个元素的地址称为数组的首地址。以上面的数组为例,下图是 arr 的指向:

           数组名的本意是表示整个数组,也就是表示多份数据的集合,但在使用过程中经常会转换为指向数组第 0 个元素的指针,所以上面使用了“认为”一词,表示数组名和数组首地址并不总是等价。初学者可以暂时忽略这个细节,把数组名当做指向第 0 个元素的指针使用即可。

           如果一个指针指向了数组,我们就称它为数组指针(Array Pointer),定义一个指向数组的指针例子如下:

    int arr[] = {23, 56, 4, 34, 45 };
    int *p = arr;
    arr 本身就是一个指针,可以直接赋值给指针变量 p。arr 是数组第 0 个元素的地址,所以int *p = arr;也可以写作int *p = &arr[0];。也就是说,arr、p、&arr[0] 这三种写法都是等价的,它们都指向数组第 0 个元素,或者说指向数组的开头。

           数组指针指向的是数组中的一个具体元素,而不是整个数组,所以数组指针的类型和数组元素的类型有关,上面的例子中,p 指向的数组元素是 int 类型,所以 p 的类型必须也是int *

    //①使用指针的方式遍历数组元素
    #include <stdio.h>
    int main(){
    	int arr[] = { 23, 56, 4, 34, 45 };
    	int len = sizeof(arr) / sizeof(int);//求数组长度,sizeof(arr) 会获得整个数组所占用的字节数,sizeof(int) 会获得一个数组元素所占用的字节数,它们相除的结果就是数组包含的元素个数,也即数组长度。
    	int i;
    	for (i = 0; i < len; i++){
    		printf("%d ", *(arr + i));//*(arr+i)等价于arr[i],arr 是数组名,指向数组的第 0 个元素,表示数组首地址, arr+i 指向数组的第 i 个元素,*(arr+i) 表示取第 i 个元素的数据,它等价于 arr[i]。
    	}
    	printf("\n");
    	return 0;
    }
    //运行结果:23 56 4 34 45
    
    //②使用数组指针来遍历数组元素
    #include <stdio.h>
    int main(){
    	int arr[] = { 23, 56, 4, 34, 45 };
    	int i, *p = arr, len = sizeof(arr) / sizeof(int);
        //求数组的长度时不能使用sizeof(p) / sizeof(int),因为 p 只是一个指向 int 类型的指针,编译器并不知道它指向的到底是一个整数还是一系列整数(数组),所以 sizeof(p) 求得的是 p 这个指针变量本身所占用的字节数,而不是整个数组占用的字节数。
    
    	for (i = 0; i < len; i++){
    		printf("%d ", *(p + i));
    	}
    	printf("\n");
    	return 0;
    }
    //运行结果:23 56 4 34 45
    
    //③让 p 指向数组中的第三个元素
    #include <stdio.h>
    int main(){
    	int arr[] = { 23, 56, 4, 34, 45 };
    	int *p = &arr[2];//也可以写做int *p = arr +2,这里指向第三个元素
    	printf("%d,%d,%d\n",*(p-2),*p,*(p+2));
    	return 0;
    }
    //运行结果:23,4,45

           引入数组指针后,我们就有两种方案来访问数组元素了,一种是使用下标,另外一种是使用指针。

           (1) 使用下标

           也就是采用 arr[i] 的形式访问数组元素。如果 p 是指向数组 arr 的指针,那么也可以使用 p[i] 来访问数组元素,它等价于 arr[i]。

           (2) 使用指针

           也就是使用 *(p+i) 的形式访问数组元素。另外数组名本身也是指针,也可以使用 *(arr+i) 来访问数组元素,它等价于 *(p+i)。

           不管是数组名还是数组指针,都可以使用上面的两种方式来访问数组元素。不同的是,数组名是常量,它的值不能改变,而数组指针是变量(除非特别指明它是常量),它的值可以任意改变。也就是说,数组名只能指向数组的开头,而数组指针可以先指向数组开头,再指向其他元素

           假设 p 是指向数组 arr 中第 n 个元素的指针,那么 *p++、*++p、(*p)++ 分别是什么意思呢?

    //*p++
    #include <stdio.h>
    int main(){
    	int arr[] = { 23, 56, 4, 34, 45 };
    	int i, *p = arr, len = sizeof(arr) / sizeof(int);
    
    	for (i = 0; i < len; i++){
    		printf("%d ", *p++);
    	}
    	printf("\n");
    	return 0;
    }
    //运行结果:23 56 4 34 45
    //解析:*p++ 应该理解为 *(p++),每次循环都会改变 p 的值(p++ 使得 p 自身的值增加),以使 p 指向下一个数组元素。该语句不能写为 *arr++,因为 arr 是常量,而 arr++ 会改变它的值,这显然是错误的。
    
    //*++p
    #include <stdio.h>
    int main(){
    	int arr[] = { 23, 56, 4, 34, 45 };
    	int i, *p = arr, len = sizeof(arr) / sizeof(int);
    
    	for (i = 0; i < len; i++){
    		printf("%d ", *++p);
    	}
    	printf("\n");
    	return 0;
    }
    //运行结果:56 4 34 45 -858993460
    //解析:*++p 等价于 *(++p),会先进行 ++p 运算,使得 p 的值增加,指向下一个元素,整体上相当于 *(p+1),所以会获得第 n+1 个数组元素的值。最后一个值为随机值。
    
    //(*p)++
    #include <stdio.h>
    int main(){
    	int arr[] = { 23, 56, 4, 34, 45 };
    	int i, *p = arr, len = sizeof(arr) / sizeof(int);
    
    	for (i = 0; i < len; i++){
    		printf("%d ", (*p)++);
    	}
    	printf("\n");
    	return 0;
    }
    //运行结果:23 24 25 26 27
    //解析:(*p)++ 就非常简单了,会先取得第1个元素的值,再对该元素的值加 1。这里第1个元素的值为 23,执行完该循环语句后,第 1个元素的值依次会变为 24 25 26 27。

    四、字符串指针(指向字符串的指针)

           C语言没有字符串类型,通常是将字符串放在一个字符数组中。使用指针的方式输出字符串:

    #include <stdio.h>
    #include <string.h>
    int main(){
    	char str[] = "www.baidu.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;
    }
    //运行结果:
    www.baidu.com
    www.baidu.com
    www.baidu.com

           除了字符数组,C语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,例如:

    char *str = "www.baidu.com";
    或者
    char *str;
    str = "www.baidu.com";
    //字符串中的所有字符在内存中是连续排列的,str 指向的是字符串的第 0 个字符;我们通常将第 0  个字符的地址称为字符串的首地址。字符串中每个字符的类型都是char,所以 str 的类型也必须是char *。
    //输出字符串:使用%s输出整个字符串,使用*或[ ]获取单个字符
    #include <stdio.h>
    #include <string.h>
    int main(){
    	char *str = "www.baidu.com";
    	int len = strlen(str), i;
    	//直接输出字符串
    	printf("%s\n", str);
    
    	//使用*(str+i)
    	for (i = 0; i < len; i++){
    		printf("%c",*(str+i));
    	}
    	printf("\n");
    
    	//使用str[i]
    	for (i = 0; i < len; i++){
    		printf("%c", str[i]);
    	}
    	printf("\n");
    
    	return 0;
    }
    //运行结果:
    www.baidu.com
    www.baidu.com
    www.baidu.com

           字符数组&&字符串常量

           在编程中如果只涉及到对字符串的读取,那么字符数组字符串常量都能满足需求;如果有写入(修改)操作,那么只能使用字符数组,不能使用字符串常量。

           获取用户输入的字符串就是一个典型的写入操作,只能使用字符数组,不能使用字符串常量,请看下面的代码:

    #include <stdio.h>
    int main(){
    	char str[30];
    	gets(str);
    	printf("%s\n", str);
    
    	return 0;
    }
    //运行结果:
    www.baidu.com
    www.baidu.com

           总结:C语言有两种表示字符串的方法,一种是字符数组,另一种是字符串常量,它们在内存中的存储位置不同,使得字符数组可以读取修改,而字符串常量只能读取不能修改。

    五、数组灵活多变的访问形式

    #include <stdio.h>
    int main(){
    	char str[20] = "www.baidu.com";
    	char *s1 = str;
    	char *s2 = str + 4;
    	char c1 = str[4];
    	char c2 = *str;
    	char c3 = *(str + 4);
    	char c4 = *str + 2;
    	char c5 = (str + 1)[5];
    
    	int num1 = *str + 2;
    	long num2 = (long)str;
    	long num3 = (long)(str + 2);
    
    	printf("s1=%s\n", s1);
    	printf("s2=%s\n", s2);
    	printf("c1=%c\n", c1);
    	printf("c2=%c\n", c2);
    	printf("c3=%c\n", c3);
    	printf("c4=%c\n", c4);
    	printf("c5=%c\n", c5);
    	printf("num1=%d\n", num1);
    	printf("num2=%ld\n", num2);
    	printf("num3=%ld\n", num3);
    
    	return 0;
    }
    //运行结果:
    s1=www.baidu.com
    s2=baidu.com
    c1=b
    c2=w
    c3=b
    c4=y
    c5=i
    num1=121
    num2=17824436
    num3=17824438
    //解析:
    (1) str既是数组名称,也是一个指向字符的指针;指针可以参加运算,指针加1相当于数组下标加1。
        printf() 输出字符串时,要求给定一个起始地址,并从这个地址开始输出,直到遇见NUL(\0)停止。s1 为字符串str第1个字符的地址,s2 为第4个字符的地址,所以 printf() 的结果分别为 www.baidu.com 和 baidu.com。
    (2) 数组元素的访问形式可以看做 address[offset],address 为起始地址,offset 为偏移量,所以:
    c1 = str[4] 表示以地址 str 为起点,向后偏移4个字符,为b;
        str表示第0个字符的地址,*str表示第0个字符,即c2=w;因为指针可以参加运算,所以 str+4 表示第4个字符的地址,c3 = *(str+4) 表示第4个字符,即b。
        字符与整数运算时,先转换为整数(字符对应的ASCII码)。对于c4,*str为字符w(同c2),w对应的ASCII为119,所以c4=119+2=121,转化为字符对应为y。
        c5 = (str+1)[5] 表示以地址 str+1 为起点,向后偏移5个字符,等价于str[6],为i。
    (3) 字符与整数运算时,先转换为整数(字符对应的ASCII码)。对于 num1,*str+2 == w+2 == 119+2 == 121,即num1为121;num2和num3分别为字符串str的首地址和第2个元素的地址。
    

    六、指针变量作为函数参数

           在C语言中,函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针。用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。

    //使用指针变量作参数交换两个变量的值
    #include <stdio.h>
    void swap(int *p1, int *p2){
    	int temp;//临时变量
    	temp = *p1;
    	*p1 = *p2;
    	*p2 = temp;
    }
    
    int main(){
    	int a = 10, b = 20;
    	swap(&a, &b);
    	printf("a=%d,b=%d\n",a,b);
    	return 0;
    }
    //运行效果:a=20,b=10
    //解析:调用 swap() 函数时,将变量 a、b 的地址分别赋值给 p1、p2,这样 *p1、*p2 代表的就是变量 a、b 本身,交换 *p1、*p2 的值也就是交换 a、b 的值。函数运行结束后虽然会将 p1、p2 销毁,但它对外部 a、b 造成的影响是“持久化”的,不会随着函数的结束而“恢复原样”。

    七、指针作为函数返回值

           C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。

    //定义函数 strlong(),用来返回两个字符串中较长的一个
    #include <stdio.h>
    #include <string.h>
    
    char *strlong(char *str1, char *str2){
    	if (strlen(str1) >= strlen(str2)){
    		return str1;
    	}
    	else{
    		return str2;
    	}
    }
    
    int main(){
    	char str1[30], str2[30], *str;
    	gets(str1);
    	gets(str2);
    	str = strlong(str1, str2);
    	printf("Longer string:%s\n", str);
    
    	return 0;
    }
    //运行结果:
    www.baidu.com
    www.ali.com
    Longer string:www.baidu.com

           用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程中可能会引发运行时错误。

    八、二级指针(指向指针的指针)

           指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针
          假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:

    C语è¨äºçº§æéï¼æåæéçæéï¼æ¼ç¤ºå¾

           指针变量也是一种变量,也会占用存储空间,也可以使用 &获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号 *。p1 是一级指针,指向普通类型的数据,定义时有一个 *;p2 是二级指针,指向一级指针 p1,定义时有两个*。将这种关系转换为C语言代码:

    int a =100;
    int *p1 = &a;
    int **p2 = &p1;
    //如果我们希望再定义一个三级指针 p3,让它指向 p2,那么可以这样写:
    int ***p3 = &p2;
    //四级指针也是类似的道理:
    int ****p4 = &p3;

           想要获取指针指向的数据时,一级指针加一个*,二级指针加两个*,三级指针加三个*,以此类推,请看代码:

    #include <stdio.h>
    int main(){
    	int a = 100;
    	int *p1 = &a;
    	int **p2 = &p1;
    	int ***p3 = &p2;
    
    	printf("%d,%d,%d,%d\n",a,*p1,**p2,***p3);
    	printf("&p2=%#X,p3=%#X\n", &p2, p3);
    	printf("&p1=%#X,p2=%#X,*p3=%#X\n", &p1, p2, *p3);
    	printf("&a=%#X,p1=%#X,*p2=%#X,**p3=%#X\n", &a, p1, *p2, **p3);
    	return 0;
    }
    //运行结果:
    100,100,100,100
    &p2=0X75FB70,p3=0X75FB70
    &p1=0X75FB7C,p2=0X75FB7C,*p3=0X75FB7C
    &a=0X75FB88,p1=0X75FB88,*p2=0X75FB88,**p3=0X75FB88
    //解析:以三级指针 p3 为例来分析上面的代码。***p3等价于*(*(*p3))。*p3 得到的是 p2 的值,也即 p1 的地址;*(*p3) 得到的是 p1 的值,也即 a 的地址;经过三次“取值”操作后,*(*(*p3)) 得到的才是 a 的值。
    

           假设 a、p1、p2、p3 的地址分别是 0X00A0、0X1000、0X2000、0X3000,它们之间的关系可以用下图来描述(方框里面是变量本身的值,方框下面是变量的地址。):

    C语è¨å¤çº§æéæ¼ç¤ºå¾

    九、空指针NULL与void指针

           1.空指针NULL

           一个指针变量可以指向计算机中的任何一块内存,不管该内存有没有被分配,也不管该内存有没有使用权限,只要把地址给它,它就可以指向,C 语言没有一种机制来保证指向的内存的正确性,程序员必须自己提高警惕。

           很多初学者会在无意间对没有初始化的指针进行操作,这是非常危险的,请看下面的例子:

    #include <stdio.h>
    int main(){
    	char *str;
    	gets(str);
    	printf("%s\n", str);
    	return 0;
    }

           这段程序没有语法错误,但在Windows下编译连接会有警告,没有对指针进行初始化!我们知道,未初始化的局部变量的值是不确定的,C 语言并没有对此作出规定,不同的编译器有不同的实现,大家不要直接使用未初始化的局部变量。上面的代码中, str  就是一个未初始化的局部变量,它的值是不确定的,究竟指向哪块内存也是未知的,大多数情况下这块内存没有被分配或者没有读写权限,使用  gets()  函数向它里面写入数据显然是错误的。

           C语言中可以对没有初始化的指针赋值为 NULL ,例如:char *str = NULL;NULL  是 “ 零值、等于零 ” 的意思,在 C 语言中表示空指针。从表面上理解,空指针是不指向任何数据的指针,是无效指针,程序使用它不会产生效果。注意区分大小写,null  没有任何特殊含义,只是一个普通的标识符。

    //给str赋值NULL
    #include <stdio.h>
    int main(){
    	char *str = NULL;
    	gets(str);
    	printf("%s\n", str);
    	return 0;
    }
    //貌似也会报错

           注意,C 语言没有规定 NULL 的指向,只是大部分标准库约定成俗地将 NULL 指向  0 ,所以不要将 NULL 和 0 等同起来,例如这种写法是不专业的:int *p = 0; 而应该坚持写为:int *p = NULL;

           注意 NULL 和 NUL 的区别:NULL 表示空指针,是一个宏定义,可以在代码中直接使用。而 NUL 表示字符串的结束标志  ’\0’ ,它是 ASCII 码表中的第  0  个字符。 NUL 没有在C语言中定义,仅仅是对  ’\0’ 的称呼,不能在代码中直接使用。

           2.void 指针

           void 用在函数定义中可以表示函数没有返回值或者没有形式参数,用在这里表示指针指向的数据的类型是未知的。也就是说,  void *  表示一个有效指针,它确实指向实实在在的数据,只是数据的类型尚未确定,在后续使用过程中一般要进行强制类型转换。C 语言动态内存分配函数  malloc()  的返回值就是  void * 类型,在使用时要进行强制类型转换。

    #include <stdio.h>
    #include <malloc.h>
    int main(){
    	//分配可以保存30个字符的内存,并把返回的指针转换为char *
    	char *str = (char *)malloc(sizeof(char) * 30);
    	gets(str);
    	printf("%s\n",str);
    
    	return 0;
    }
    //运行结果:
    www.baidu.com
    www.baidu.com

           注意:void * ,它不是空指针的意思,而是实实在在的指针,只是指针指向的内存中不知道保存的是什么类型的数据。

    十、数组≠指针

           数组和指针不等价,数组是另外一种类型。数组和指针不等价的一个典型案例就是求数组的长度,这个时候只能使用数组名,不能使用数组指针:

    #include <stdio.h>
    int main(){
    	int a[6] = { 0, 1, 2, 3, 4, 5 };
    	int *p = a;
    	int len_a = sizeof(a) / sizeof(int);
    	int len_p = sizeof(p) / sizeof(int);
    	printf("len_a=%d,len_p=%d\n",len_a,len_p);
    
    	return 0;
    }
    //运行结果:len_a=6,len_p=1

           数组是一系列数据的集合,没有开始和结束标志,p 仅仅是一个指向 int 类型的指针,编译器不知道它指向的是一个整数还是一堆整数,对 p 使用 sizeof 求得的是指针变量本身的长度。也就是说,编译器并没有把 p 和数组关联起来,p 仅仅是一个指针变量,不管它指向哪里,sizeof 求得的永远是它本身所占用的字节数。

           1.数组在什么时候会转换为指针

           数组名的本意是表示一组数据的集合,它和普通变量一样,都用来指代一块内存,但在使用过程中,数组名有时候会转换为指向数据集合的指针(地址),而不是表示数据集合本身,这在前面的例子中已经被多次证实。

           数据集合包含了多份数据,直接使用一个集合没有明确的含义,将数组名转换为指向数组的指针后,可以很容易地访问其中的任何一份数据,使用时的语义更加明确。

           C语言标准规定,当数组名作为数组定义的标识符(也就是定义或声明数组时)、sizeof 或 & 的操作数时,它才表示整个数组本身,在其他的表达式中,数组名会被转换为指向第 0 个元素的指针(地址)。

           2.关于数组和指针可交换性的总结

           (1) 用 a[i] 这样的形式对数组进行访问总是会被编译器改写成(或者说解释为)像 *(a+i) 这样的指针形式。

           (2) 指针始终是指针,它绝不可以改写成数组。你可以用下标形式访问指针,一般都是指针作为函数参数时,而且你知道实际传递给函数的是一个数组。

           (3) 在特定的环境中,也就是数组作为函数形参,也只有这种情况,一个数组可以看做是一个指针。作为函数形参的数组始终会被编译器修改成指向数组第一个元素的指针。

           (4) 当希望向函数传递数组时,可以把函数参数定义为数组形式(可以指定长度也可以不指定长度),也可以定义为指针。不管哪种形式,在函数内部都要作为指针变量对待。

    十一、C语言指针数组(每个元素都是指针)

           注意区别: 
           数组指针:指的是指针指向的是一个数组; 
           指针数组:表示的是数组的每个元素都是指针。

           如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。指针数组的定义形式一般为: 

    dataType *arrayName[length]; 其中,[ ]的优先级高于*,该定义形式应该理解为: 
    dataType *(arrayName[length]); 括号里面说明arrayName是一个数组,包含了length个元素,括号外面说明每个元素的类型为dataType *。

           除了每个元素的数据类型不同,指针数组和普通数组在其他方面都是一样的,下面是一个简单的例子:

    include <stdio.h>
    int main(){
        int a = 16, b = 932, c = 100;
        //定义一个指针数组
        int *arr[3] = {&a, &b, &c};//也可以不指定长度,直接写作 int *parr[]
        //定义一个指向指针数组的指针
        int **parr = arr;
        printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
        printf("%d, %d, %d\n", **(parr+0), **(parr+1), **(parr+2));
    
        return 0;
    }
    //运行结果:
    16, 932, 100
    16, 932, 100
    //解析:
    1. arr 是一个指针数组,它包含了 3 个元素,每个元素都是一个指针,在定义 arr 的同时,我们使用变量 a、b、c 的地址对它进行了初始化,这和普通数组是多么地类似。
    2. parr 是指向数组 arr 的指针,确切地说是指向 arr 第 0 个元素的指针,它的定义形式应该理解为int (*parr),括号中的表示 parr 是一个指针,括号外面的int 表示 parr 指向的数据的类型。arr 第 0 个元素的类型为 int ,所以在定义 parr 时要加两个 *。
    3. 第一个 printf() 语句中,arr[i] 表示获取第 i 个元素的值,该元素是一个指针,还需要在前面增加一个 * 才能取得它指向的数据,也即 *arr[i] 的形式。
    4. 第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),*(parr+i) 表示获取第 i 个元素指向的数据。
    

           指针数组还可以和字符串数组结合使用,请看下面的例子:

    #include <stdio.h>
    int main(){
        char *str[3] = {
            "google.com",
            "hello world",
            "C Language"
        };
        printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
        return 0;
    }
    //运行结果:
    google.com
    hello world
    C Language
    //需要注意的是,字符数组 str 中存放的是字符串的首地址,不是字符串本身,字符串本身位于其他的内存区域,和字符数组是分开的。也只有当指针数组中每个元素的类型都是char *时,才能像上面那样给指针数组赋值,其他类型不行。
    //为了便于理解,可以将上面的字符串数组改成下面的形式,它们都是等价的。
    #include <stdio.h>
    int main(){
    	char *str0 = "google.com";
    	char *str1 = "hello world";
    	char *str2 = "C Language";
    	char *str[3] = { str0, str1, str2 };
    	printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
    	return 0;
    }
    //运行结果:
    google.com
    hello world
    C Language

           指针数组和二维数组指针的区别

           指针数组和二维数组指针在定义时非常相似,只是括号的位置不同:

           int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5];

           int (*p2)[5]; //二维数组指针,不能去掉括号

    十二、函数指针(指向函数的指针)

           一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针

           函数指针的定义形式为:

    returnType (*pointerName)(param list);
    其中,returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。
    注意( )的优先级高于*,第一个括号不能省略,如果写作returnType *pointerName(param list);就成了函数原型,它表明函数的返回值类型为returnType *。
    //用指针来实现对函数的调用
    #include <stdio.h>
    //返回两个数中较大的一个
    int max(int a, int b){
        return a>b ? a : b;
    }
    int main(){
        int x, y, maxval;
        //定义函数指针
        int (*pmax)(int, int) = max;  //也可以写作int (*pmax)(int a, int b)
        printf("Input two numbers:");
        scanf("%d %d", &x, &y);
        maxval = (*pmax)(x, y);
        printf("Max value: %d\n", maxval);
        return 0;
    }
    //运行结果:
    Input two numbers:10 30
    Max value: 30
    //解析:第 13 行代码对函数进行了调用。pmax 是一个函数指针,在前面加 * 就表示对它指向的函数进行调用。注意( )的优先级高于*,第一个括号不能省略。
    

    十三、总结

           指针(Pointer)就是内存的地址,C语言允许用一个变量来存放指针,这种变量称为指针变量。指针变量可以存放基本类型数据的地址,也可以存放数组、函数以及其他指针变量的地址。

           程序在运行过程中需要的是数据和指令的地址,变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符:在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、字符串名和数组名表示的是代码块或数据块的首地址;程序被编译和链接后,这些名字都会消失,取而代之的是它们对应的地址。

           (1) 指针变量可以进行加减运算,例如p++p+ip-=i。指针变量的加减运算并不是简单的加上或减去一个整数,而是跟指针指向的数据类型有关。
           (2) 给指针变量赋值时,要将一份数据的地址赋给它,不能直接赋给一个整数,例如int *p = 1000;是没有意义的,使用过程中一般会导致程序崩溃。
           (3) 使用指针变量之前一定要初始化,否则就不能确定指针指向哪里,如果它指向的内存没有使用权限,程序就崩溃了。对于暂时没有指向的指针,建议赋值NULL
           (4) 两个指针变量可以相减。如果两个指针变量指向同一个数组中的某个元素,那么相减的结果就是两个指针之间相差的元素个数。
           (5) 数组也是有类型的,数组名的本意是表示一组类型相同的数据。在定义数组时,或者和 sizeof、& 运算符一起使用时数组名才表示整个数组,表达式中的数组名会被转换为一个指向数组的指针。

     

     

     

    参考文献:C语言中文网

    展开全文
  • 1、共享内存中用指针一般是用对首地址的偏移量,这样就好了,每个进程映射的地址不一样   2、交换用的数据中,永远都不要出现指针
  • 后台传回来的Json数据,程序中不做判断就直接赋值操作,很有可能出现崩溃闪退。为了解决空指针的问题,治标的方法就是遇到一个处理一个。这样业务代码里面就插了很多判断语句,费时又费力。现在有一个简单的办法...
  • 1、定义指针函数 typedef int (* fun) (); static fun f; 2、代码实现 ...在a.h文件里面里面定义函数指针,并且有个传递函数指针的方法 typedef std::string (*fun)(); void f2(fun f 1);
  • 0.0 什么是指针 对于初学者来说,常常不能准确认识指针,分不清指针和数组之前的区别,这在学习C语言过程中是灾难性的。因为指针是C语言的精髓,有些问题必须通过指针,才能有效进行处理。那到底指针是什么呢?我们...
  • 在我们数据结构中,我们主要研究的是数据变量以及之间关系的学科,在计算机中数据的存储是基于连续存储和离散存储机制实现的,其中连续存储顾名思义就是在计算机存储设备上开辟连续的物理存储空间来存储数据,使得...
  • php函数里面指针

    千次阅读 2018-08-08 19:22:41
    今天在代码里面看到一个迷惑的地方,函数形参是个指针。想一想也是对的,传指针可以修改在函数之外的变量,这个跟在foreach里面用用指针&amp;key赋值,之后unset一样的道理,mark一下 $pc = new \...
  • 2,然后自己又想到了难道map中获取不存在的key时会报空指针异常?也不应该呀,如果key不存在,get会返回null,然后程序应该输出null才对。 后来,经过分析,发现这里面还有一个自动拆箱的过程。正是这个过程,才...
  • C++自定义数据类型之指针

    千次阅读 2015-02-15 18:37:11
    好像这方面的知识理解起来很费劲儿,看了三四遍了吧,还是模模糊糊的,没有条理性,所以就开始翻看博客里这方面的内容,可能是看的少吧,还是不能让我彻底的明白,因此就度娘了一下,看了几篇关于指针的文章,觉得有...
  • 最近在开发中碰到用SharedPreferences 存储一些临时数据的时候发现这样一个问题:在Activity中使用SharedPreferences似乎很简单,只要把获得 ...PRIVATE) 这句话放在 onCreate()方法里面一般不会有报空指针
  • C语言指向结构体的指针,如何通过指针获取结构体当中的值 格式: 结构体类型 变量名称 ,* 指针名称 = &变量名称; 案例如下 定义结构体并定义结构体指针让其指向结构体 #include<stdio.h> #include<...
  • 不了解的对指针的理解就停留在“指针就是变量的地址”这句话,会比较害怕使用指针,特别是各种高级操作。 而了解内存模型的则可以把指针用得炉火纯青,各种 byte 随意操作,让人直呼 666。 一、内存本质 编程的本质...
  • 今天做项目时,其中一个环节是提交图片,一开始检查了提交路径,Servlet等均为正确,但是在Servlet method="XXXX"中 method一直是报空指针异常,后面发现终于找到了原因 首先 当input类型为file时,enctype设为...
  • 二级指针(指向指针指针

    千次阅读 多人点赞 2019-09-26 11:27:52
    指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针指针。 ...
  • 本文承接上一篇博文完整的介绍了关于C语言指针的核心内容 ,欢迎各位老铁批评指正!
  • 指针数组保存数据的地址,任何存入指针...a 本身的地址由编译器另外存储,存储在那里并不知道间接访问数据,首先取得指针变量 p 的内容,把它作为地址,然后这个地址提取数据或向这个地址写入数据。指针可以以指针...
  • Integer类型数据为null,报空指针异常

    千次阅读 2020-09-09 15:27:20
    Integer类型数据为null,报空指针异常 最近写代码,发现一直报空指针异常。一点点debug,发现是我的if语句里面表达式有问题(其中v的值为null),原码如下: if(v == 1){ ... }else if(v == 0){ ... }els
  • C++构造数据类型----指针

    千次阅读 2015-02-24 14:05:38
    C++中提供了用基本数据类型构造的构造数据类型来对复杂的数据进行描述与处理。这些构造数据类型包括枚 举、数组、结构、联合、指针、引用。 接下来结合我对指针的认识来说说指针。   一、指针的由来    要...
  • //获取到bindler 了 可以并转成service 可以调用里面的方法了 msbinder= (MusicPlayService.PlayServiceBinder) service; msbinder=getbinder(); Log.d("返回bindler",""+msbinder.toString()); } @...
  • 指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针指针...
  • 指针:在C语言之父Dennis MacAlistair Ritchie写的《C程序设计语言》种是这样定义指针的——指针是一种保存变量地址的变量。用图的形式来表述可能更清晰:如下图所示,c是一个char类型的变量,p是指向c的指针。图中...
  • 采用MFC编程时,子对话框常常要向主窗口传递数据获取主窗口的对象指针便显得非常重要了。 void CMyView::OnModel() //点击菜单,创建对话框的几种变量设置,总共是4种方法,模态的一种,非模态的三种 { // TODO: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 172,016
精华内容 68,806
关键字:

从指针里面获取数据