1)问题:二级指针到底是什么?怎么用的?怎么存放的?

 #include <stdio.h>

 #define TEST_ADDR 0x12FF40

 void main()
{
int a = 0x5555AAAA;
int* pA = &a;
int** ppA = NULL;
unsigned int * pAddr = (unsigned int *)TEST_ADDR;
ppA = &pA;
printf("0x%p\n",a);
printf("0x%p, 0x%p\n",&a, pA);
printf("0x%p, 0x%p\n",&pA, ppA);
printf("0x%p\n",&ppA); printf("[0x%p]:0x%p 0x%p 0x%p 0x%p\n",TEST_ADDR, *(pAddr), *(pAddr+), *(pAddr+), *(pAddr+));
pAddr = (unsigned int *)(TEST_ADDR+0x10);
printf("[0x%p]:0x%p 0x%p 0x%p 0x%p\n",TEST_ADDR+0x10, *(pAddr), *(pAddr+), *(pAddr+), *(pAddr+));
pAddr = (unsigned int *)(TEST_ADDR+0x20);
printf("[0x%p]:0x%p 0x%p 0x%p 0x%p\n",TEST_ADDR+0x20, *(pAddr), *(pAddr+), *(pAddr+), *(pAddr+));
}

结果如下:

0x5555AAAA
0x0012FF60, 0x0012FF60
0x0012FF54, 0x0012FF54
0x0012FF48
[0x0012FF40]:0xCCCCCCCC 0xCCCCCCCC 0x0012FF54 0xCCCCCCCC
[0x0012FF50]:0xCCCCCCCC 0x0012FF60 0xCCCCCCCC 0xCCCCCCCC
[0x0012FF60]:0x5555AAAA 0xCCCCCCCC 0x0012FFB8 0x00411B36
请按任意键继续. . .

结果怎么看:

  0x0012FF48存放的值是0x0012FF54       ->     ppA = &pA;

  0x0012FF54存放的值是0x0012FF60    ->     pA = &a;

  0x0012FF60存放的值是0x5555AAAA      ->     int a = 0x5555AAAA;

分析:

a.二级指针的用法:正确用法ppA = &pA;    (若用*ppA = pA; 编译无错,运行出错)

         记忆:ppA = &pA这是在搞定指向;而*ppA只 用于取值/赋值    

        (这种用法也是错的int** ppA = &&a;)

        (这种用法也是错的int** ppA = pA;)

b.另一种正确用法:

  int** ppA = &pA;

  这种用法类比于pA = &a,只不过此时pA指向的是一个int,而ppA指向的是一个指针;此时的**可以理解为与int结合跟精密,是一种类型的一部分,因为ppA的类型为int**

c.二级指针是指向指针的指针;(这句只含一层意思:二级指针也是指针,没什么特殊的,要用得先指向,再取值/赋值)

总结:

  形成习惯:定义二级指针的时候先赋值NULL;如果要用,先指向,再进行取值赋值操作;

2)实例——高级些的hello word!

 #include <stdio.h>
#include <stdlib.h>
#include <string.h> #define STR "Hello!\r\n"
#define STR_MAX 10 extern int mallocStr(char** pStr, unsigned int len);
extern int test(char* pStr);
extern void freeStr(char* pStr); int main()
{
char* pStr = NULL; if( != mallocStr(&pStr, STR_MAX))
{
return -;
}
memset(pStr, , STR_MAX);
test(pStr);
freeStr(pStr);
return ;
} int mallocStr(char** ppStr, unsigned int len)
{
char* pMem = NULL;
pMem = (char*)malloc(len);
if (NULL == pMem)
{
return -;
} *ppStr = pMem;
return ;
} int test(char* pStr)
{
strncpy(pStr, STR, STR_MAX); printf("%s", pStr);
return ;
} void freeStr(char* pStr)
{
free(pStr);
pStr = NULL;
}

点评:

  i.在第14行不建议使用二级指针,因为二级指针需要一级指针作媒介来指向实际内存;若此处使用二级指针,此题几乎无解;

  ii.二级指针通常是作返回值用,通常用法是:调用函数定义一级指针,接着用&p调用操作函数,而在操作函数中用二级指针进行操作;

【C】二级指针探秘 & 星号的两种用法(1.与基本类型结合形成另一种类型,比如与int结合形成int* 2.取值操作)的更多相关文章

  1. C语言二级指针(指向指针的指针)

    转载:http://c.biancheng.net/cpp/html/85.html 指针可以指向一份普通类型的数据,例如 int.double.char 等,也可以指向一份指针类型的数据,例如 in ...

  2. C语言指针系列 - 一级指针.一维数组,二级指针,二维数组,指针数组,数组指针,函数指针,指针函数

    1. 数组名 C语言中的数组名是一个特殊的存在, 从本质上来讲, 数组名是一个地址, 我们可以打印一个指针的值,和打印一个数组的值来观察出这个本质: int nArray[10] ={ 0 }; in ...

  3. 对线程等待函数pthread_join二级指针参数分析

    分析之前先搞明白,这个二级指针其实在函数内部是承接了上个线程的返回值. 看man手册,发现返回值是个普通指针.人家用二级指针来承接,可能准备干大事.这个可以自己搜索一下.原因嘛,二级指针是保存了这个地 ...

  4. C#中 this关键字 四种用法

    /// <summary> /// 主程序入口 /// </summary> /// <param name="args"></param ...

  5. [Vuex系列] - 细说state的几种用法

    state 存放的是一个对象,存放了全部的应用层级的状态,主要是存放我们日常使用的组件之间传递的变量. 我们今天重点讲解下state的几种用法,至于如何从头开始创建Vuex项目,请看我写的第一个文章. ...

  6. C++二级指针第二种内存模型(二维数组)

    C++二级指针第二种内存模型(二维数组) 二维数组 二维数组本质上是以数组作为数组元素的数组,即“数组的数组”. 定义 类型说明符 数组名[常量表达式][常量表达式] 例如: float a[3][4 ...

  7. C++二级指针第一种内存模型(指针数组)

    二级指针第一种内存模型(指针数组) 指针的输入特性:在主调函数里面分配内存,在被调用函数里面使用指针的输出特性:在被调用函数里面分配内存,主要是把运算结果甩出来 指针数组 在C语言和C++语言中,数组 ...

  8. C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间

    1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...

  9. 深入理解C语言-二级指针三种内存模型

    二级指针相对于一级指针,显得更难,难在于指针和数组的混合,定义不同类型的二级指针,在使用的时候有着很大的区别 第一种内存模型char *arr[] 若有如下定义 char *arr[] = {&quo ...

随机推荐

  1. 【安全测试】sqlmap安装方法

    参考资料:http://jingyan.baidu.com/article/60ccbceb64cc2064cbb19748.html SQLMap是利用Python语言写的,所以需要将Python这 ...

  2. ios cordova报gap://ready 弹出框,一直弹

    The iOS app was not working because there was a plugin missing: https://github.com/apache/cordova-pl ...

  3. .NET 框架程序使用 Win32 API

    .NET 框架程序可以通过静态 DLL 入口点的方式来访问本机代码库.DllImport 属性用于指定包含外部方法的实现的dll 位置.       DllImport 属性定义如下:      na ...

  4. C++ 在容器中存放函数指针

    注意,对一般c++ 98标准编译器而言,容器泛型模板是不支持直接存放函数指针的.需要typedef将函数指针重命名. 比如,一个void返回值参数也为void的函数指针,需要 typedef void ...

  5. centos mongodb cluster install 完全版

    分享一则用yum安装的mongodb初始化脚本. install_mongodb.sh会安装mongodb所需的基本环境. 配置副本集的时候会需要辅助文件hosts.conf. 说明:该示例为一主一丛 ...

  6. css属性的书写

    书写顺序: 注释方式: /* 块状注释文字 * 块状注释文字 * 块状注释文字 */ .m-list{width:500px;} .m-list li{height:20px;line-height: ...

  7. META-INF文件夹是干啥的,META-INF文件夹的作用, META-INF文件夹能删吗

    今天有人问到 META-INF文件夹是干啥的,META-INF文件夹的作用, META-INF文件夹能删吗,还有项目的META-INF下面一般会有个MANIFEST.MF 文件,都是干啥的. 百度搜了 ...

  8. 如何在脚本中获取进程ID(PID)

    我想要知道运行中脚本子shell的进程id.我该如何在shell脚本中得到PID. 当我在执行shell脚本时,它会启动一个叫子shell的进程.作为主shell的子进程,子shell将shell脚本 ...

  9. TFS Workspace 更改电脑名称

    不小心改了计算机名称 导致VS在保存项目的时候,包如下错误: 解决方法: 第一步: 第二步:输入如下片段 tf workspaces /updateComputerName:旧计算机名称  /coll ...

  10. E. Vasya and Beautiful Arrays

    http://codeforces.com/contest/355/problem/E 每个数都可以变成段 [a-k,a], 某一个因子是否被所有的段包含,就是把这个因子以及它的所有倍数看成点, 看是 ...