(1)是地址

首先明白一个观点:指针就是地址。这是理解指针的起始一步。

直观感受下。变量的地址

int main()
{
int foo;
int *foo_p;
foo = 5;
foo_p = &foo;
printf(" foo...%d\n", foo);
printf("*foo_p...%d\n", *foo_p);
printf(" &foo...%p\n", &foo);
printf(" foo_p...%p\n", foo_p);
printf("&foo_p...%p\n", &foo_p);
return 0;
}

执行

几点说明:

  1. %p中的p是pointer(指针)的意思。专门用于打印指针变量中的内容。
  2. 有时看到用%x打印指针的。尽管结果一样,但含义全然不同。

    %p:用合适的方式(通常是十六进制)输出指针变量中存放的还有一个变量的地址;%x:用十六进制的方式打印出变量的值。而且在我的环境中使用%x打印指针变量的话,会省略前面的0。

指针变量的示意图
左上角是变量名。右上角是变量地址。中间是变量存储的内容。
能够这样来理解指针:指针是一种特殊的语言机制,它存放的是其他变量的地址,而且能够通过解引用操作符*,来获取该地址的内容。这也造成了一种指向的关系,如上图 foo_p->foo。

高阶指针
如二级指针:指向指针的指针。
int main()
{
int foo = 5;
int *foo_p = &foo;
int **foo_pp = &foo_p;
printf(" foo...%d\n", foo);
printf(" &foo...%p\n", &foo);
printf(" foo_p...%p\n", foo_p);
printf(" &foo_p...%p\n", &foo_p);
printf(" *foo_p...%d\n", *foo_p);
printf(" foo_pp...%p\n", foo_pp);
printf("&foo_pp...%p\n", &foo_pp);
printf("*foo_pp...%p\n", *foo_pp);
printf("**foo_pp...%d\n", **foo_pp);
return 0;
}

执行

由执行结果,画出内存示意图:
各变量的类型推导。foo_p是指针。且指向int,故foo_p的类型是int*。也就是在'*'前加入int;foo_pp也是指针,且指向foo_p。故foo_pp的类型是int**,也就是在'*'前加入int*。
更高阶的指针类型。以此类推。
看看在我的环境中各基本类型分配的内存大小
int main()
{
printf("sizeof(char)...%d\n", sizeof(char));
printf("sizeof(int)...%d\n", sizeof(int));
printf("sizeof(float)...%d\n", sizeof(float));
printf("sizeof(double)...%d\n", sizeof(double));
printf("sizeof(int*)...%d\n", sizeof(int*));
return 0;
}
执行

在我的环境中,指针类型分配的大小是 sizeof(int*)=4;也就是说用4个字节的大小来存储变量的地址,这也是眼下大多数环境下的结果。以后讨论基于这个结果。

至于在c标准中,没有规定指针类型的大小,详细大小依靠详细的环境。

关于 sizeof

首先必须指出:sizeof是操作符,而不是函数。

被误解为函数,可能是大多数情况下。我们都这样使用它:sizeof()。事实上这样用 sizeof 类型,如sizeof int也是能够的。

正确的使用是:假设Type是类型名。则sizeof(Type);假设Type是变量,则加不加括号,都能够。
探讨几个问题
(1)居然指针存放的是变量的地址,而在同一环境中地址是同种类型的整数,如4字节大小的,那为何还有指针类型的说法?
int main()
{
int foo;
int *int_p = &foo;
//在c中以下这句代码会给出警告,但可执行;而在c++中是会直接报错的
double *dou_p = &foo;
foo = 5;
printf("foo...%d\n", foo);
printf("int_p...%p\n", int_p);
printf("dou_p...%p\n", dou_p);
printf("*int_p...%d\n", *int_p);
printf("*int_p...%f\n", *int_p);
printf("*dou_p...%d\n", *dou_p);
printf("*dou_p...%f\n", *dou_p);
return 0;
}

执行

这个结果非常让人凌乱!

为什么会出现这样的情况。关键在于:不同类型的变量有不同的存储方式。

如4字节的int和相同4字节的float,所分配的空间大小一样,但能够表示的数据范围有非常大差距。详细存储方式,大家可查下。

这就说明。在进行解引用时,必须指出相应的类型方式,才可正确获取变量值。
指针是派生类型,它的类型依靠它所指向的对象。
两个概念
指针的类型、指针所指向的类型
用实例说明:int *p;
(i)p是指针,它的类型是 int*
(ii)p是指针。它所指向的类型是 int
还有一个实例:int **p;
(i)p是指针。它的类型是 int**(二级指针,它的使用方法以后会讲到)
(ii)p是指针,它所指向的类型是 int*
方法非常easy:是不是指针类型,就看声明中有没有*;指针的类型就是去掉变量名后。剩下的部分;指针所指向的类型就是去掉变量名和离它近期的*。剩下的就是。
相同提醒我们:不可忽视编译器的警告!

(2)空指针类型:void*
在ANSI C中提供了一种,能够接受不论什么类型的指针类型:void*(空指针类型)
int foo = 5;
void *p = &foo;   //这句话是不会报错的
printf("*p...%d\n", *p);   //这句话无法通过编译
不能通过编译的原因:假设只知道变量的内存地址,但却不知道变量的类型。编译器也就不知道怎样对这段地址上的内容进行解析,也就是无法解引用。

(3)printf()函数
printf(格式控制,输出表);
功能:依照规定格式输出指定数据。
“格式控制”是用双引號括起来的格式控制转换字符串。“输出表”中的数据能够是合法的常量、变量和表达式,要与“格式控制”中的格式字符一一相应。
几个格式输出符
%d —— 以带符号的十进制形式输出整数
%o —— 以无符号的八进制形式输出整数
%x —— 以无符号的十六进制形式输出整数
%u —— 以无符号的十进制形式输出整数
%c —— 以字符形式输出单个字符
%s —— 输出字符串
%f —— 以小数点形式输出单、双精度实数
%e —— 以标准指数形式输出单、双精度实数
%g —— 选用输出宽度较小的格式输出实数
专栏文件夹:

版权声明:本文博主原创文章,转载,转载请注明出处。

承诺c指针 (1)指针是地址的更多相关文章

  1. 对象布局已知时 C++ 对象指针的转换时地址调整

    在我调试和研究 netscape 系浏览器插件开发时,注意到了这个问题.即,在对象布局已知(即对象之间具有继承关系)时,不同类型对象的指针进行转换(不管是隐式的从下向上转换,还是强制的从上到下转换)时 ...

  2. Little-endian的一个好处:在变量指针转换的时候地址保持不变

    Big-endian 的内存顺序和数字的书写顺序是一致的,方便阅读理解.Little-endian 在变量指针转换的时候地址保持不变,比如 int64* 转到 int32* 各有利弊,统一就好,目前看 ...

  3. 大一C语言学习笔记(7)---指针篇--什么是指针?什么是指针变量?取地址符“&”的作用是什么?地址运算符“*”的作用是什么,怎么理解两者?

    "指针是C语言的灵魂"这句话一开始我没怎么明白,现在接触了指针,终于知道为什么这么说了,因为....难,真难:下面说一下我对这句话的见解: C语言拥有着其他语言所没有的特性---直 ...

  4. C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用

    类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...

  5. C/C++:提升_指针的指针和指针的引用

    C/C++:提升_指针的指针和指针的引用 写在前面 今天在使用指针的时候我发现了一个自己的错误.

  6. 理清C++常量指针和指针常量这团乱麻

    写在前面: 与其说C++中的常量指针和指针常量是一块很有嚼头的语法糖,不如说它是一块相当难啃的骨头.其实本来没什么,这无非是const int *p与int* const p的区别, 但一涉及到起名字 ...

  7. 详解c++指针的指针和指针的引用

    展示一下使用指针的指针和指针的引用修改传递给方法的指针,以便更好的使用它.(这里说的指针的指针不是一个二维数组) 为什么需要使用它们 当我们把一个指针做为参数传一个方法时,其实是把指针的复本传递给了方 ...

  8. 【C语言入门教程】4.9 指向指针的指针

    指针变量可以指向另一个指针变量,这种操作并不是将一个指针变量所指向的内存地址传递给另一个指针变量,而是定义一种指向指针类型的指针变量,可将其称为双重指针.双重指针的定义形式为: 数据类型 **变量名: ...

  9. 指针的指针&指向指针数组的指针

    一.指针的指针    指针的指针看上去有些令人费解.它们的声明有两个星号.例如:        char ** cp;    如果有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针 ...

随机推荐

  1. Eclipse正确导入第三方project

    前言 昨晚,在不同的Android做出最终的在线测试时间,在其他平台上正常升级的提示突然报告出来"java.lang.NoClassDefFoundError"误.拉什adb lo ...

  2. HTML5实际和离线应用分析

    当前离线Web申请书,即,该装置不能访问因特网时的应用的执行.HTML5离线应用重点,主要开发人员希望.步骤离线应用开发有:首先我们应该知道设备是否可以连接;然后,它也应该可以访问某些资源(像.CSS ...

  3. pig询问top k,每个返回hour和ad_network_id最大的两个记录(SUBSTRING,order,COUNT_STAR,limit)

    pig里面有一个TOP功能.我不知道为什么用不了.有时间去看看pig源代码. SET job.name 'top_k'; SET job.priority HIGH; --REGISTER piggy ...

  4. 集差集 哈希表 比较数据库的照片和server画面上,将server垃圾上的图片删除

    SSH 骨架code: public String deleRubbishAd(){ int deleADcount = 0; rubbishADtp = configDao.rubbishADtp( ...

  5. docker-gitlab(转)

    Issues Docker is a relatively new project and is active being developed and tested by a thriving com ...

  6. 【Java收集的源代码分析】Hashtable源代码分析

    Hashtable简单介绍 Hashtable相同是基于哈希表实现的,相同每一个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时.相同会自己主动增长. Has ...

  7. iOS经常使用类别

    我们发现,慢慢积累了很多自己写的各种类别的. .今天,无私.张贴 1.NSDateFomatter @interface NSDateFormatter (MyCategory) + (id)date ...

  8. 玩转Web之JavaScript(一)-----javaScript语法总结(一) 与鼠标操作有关的语法

    click()  对象.click()  使对象被点击. event.clientX  返回最后一次点击鼠标 X 坐标值: event.clientY  返回最后一次点击鼠标 Y 坐标值: event ...

  9. 写hive sql和shell脚本时遇到几个蛋疼的问题!

    错误一: Hive的where后不能用字段的别名, 错误二: hive的groupby中不能用自己定义函数,否则报错(用嵌套select取代) 错误三: 运行:$ ./hive_game_operat ...

  10. Java,JSP,JavaScript三和差异

    JSP代表:java server page,意义是基于JAVA服务器的网络技术,随着asp,php喜欢,我们正在创造的语言网页 JavaScript:它已成为JS,随着JAVA系,就是赶时髦起个这名 ...