网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.直接召唤系与IoCfashion使用Spri.
.使用ObjectStream会出现的问题.
.Activemq和Lingo实现JMS和异步调.
.使用JRockit 5.0运行BEA&nb.
.深入讨论JAVA字节码加密技术(2).
.用Java设计浮动按钮程序.
.学习JavaWebStart.
.在JBuilder中使用J2ME开发工具提.
.条件编译.
.在开始时击败递归类强制转换概念.
.抽象PACKAGES增加系统灵活性.
.struts构建文件上传(3).
.Java服务器Tomcat 5.5.15&n.
.实战Java多线程编程精要之限制优.
.将 Java 应用程序迁移到 .NET(2).
.Java核心代码例程之:JNIExample.
.Java Mail API及其应用 —— 一个.
.看 JUnit 中Metedata的巧妙应用.
.jBPM 在定义文件里面设置Action .
.Enterprise JavaBeans导论(3).

水滴石穿C语言之指针步进辨析

发表日期:2008-1-5


基本解释

  通过上一篇的分析,我们已经很清楚地知道:指针不是一个简单的类型,它是一个本身和所指向物相复合的类型。指针的算术运算(如步进)与指针所指向物的类型密切相关。

  问题:指针步进 & 步进单位

  下面的代码中打印出的结果是几?

int arContext[5] ={0,1,2,3,4}, i, *pAr;
pAr = arContext;
printf ("%d\n", *(pAr + 3 * sizeof (int)));
  答案与分析:

  这段代码没有正确答案,因为这段代码是错的,printf将打出无法猜测的内存区的值,其中的原因如下:

  在C语言中,指针总是按照它所指向的对象的大小步进。在上面的例子中,pAr是指向整数类型变量的指针,一个整数是4个字节(默认CPU字长是32位),pAr + 1就指向下一个整数,也就是指针后移4个字节,而不是说将地址只移动一个字节。

  因为C语言编译器知道每个指针的类型,因此对指针的运算是会自动把所指类型的Size考虑进去的。

  pAr + 3 * sizeof (int) = pAr + 3 * 4 = pAr + 12 ,因此pAr指向了数组的第13个整数元素。而数组本身才5个元素,pAr早已经超出了界限,所指向的地方当然就是无人可知道的东西了,具体指向什么东西,各种不同的编译器互不相同。总之,肯定不能打印出我们想要的值就是了。

  指针不是一个简单的类型,它是一个和指针所指物的类型相复合的类型。因此,它的算术运算与指针所指物的类型密切相关,在C++语言中也是同样。

  再比如下面的例子:

int a[8];
int* p = a;
int* q = p + 3;
p++;
  指针的加减并不是指针本身的二进制表示加减,要记住,指针是一个元素的地址,它每加一次,就指向下一个元素。所以:

int* q = p + 3;
  q指向从p开始的第三个整数。

  p++;

  p指向下一个整数。
问题:指针步进 & 步进单位转换

  我有一个char *类型的指针,恰好指向了一个int类型的值,我想让这个指针跳过int指向下一个char,下面的代码可以达到这个目的吗?

((int *)p)++;
  答案与分析:

  可以。

  首先我们要清楚C语言中左值和右值的概念,C语言中左值是指可以放在“=”左侧,即可以被赋值,右值是可以放在“=”的右边,即可以赋给其它变量的值。++是单目操作符,它将一个变量的值加1然后再赋给这个变量,因此它需要的操作数应该既可以放在“=”号的左边,也可以放在“=”的右边。原则上讲,类型强制转换的结果是右值而不是左值。所以,(int *)p的结果在这个表达式中是++的右值,而++的左值依旧是p,而不是(int *)p。

  这个问题的核心正是告诉我们类型强制转换的结果是右值而不是左值。

  另外,我们可以使用一个简单的办法达到相同的目的:

p += sizeof(int);
  p是char *类型的指针,它的步进长度是1,加上一个整数所占的长度,就是跳过了一个整数所占的空间。

  所以,有时候,ULONG *p; 想要增加8个字节,可以作如下强制转换:

(ULONG *)((UCHAR *)p+8
  问题:指针步进 & void 指针

  为什么我对void *类型的指针进行运算,编译器会报告如下错误?

error C2036: 'void *' : unknown size
  答案与分析:

  在C语言中,所有的指针远算,例如+、—、*、/,都是将它所指向的对象的尺寸考虑进取的。例如‘char*’ 类型的指针加1,就是地址向后移动一个字节;而‘int*’类型指针加1,就是移动4个字节。但是,对于‘void*’型的指针呢?‘void *’指针在C标准中被规定可以强制转换成任何类型的指针而不会丢失数据,它的大小具体的编译器各不相同,也就是说,编译器也不知道void到底有多大,因此,无法对‘void*’类型的指针进行算术运算。
上一篇:Java 程序中的多线程 人气:540
下一篇:JXTA技术的设计目标和层次结构 人气:883
浏览全部Java的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐