c语言指针范文
时间:2023-04-03 09:59:48
导语:如何才能写好一篇c语言指针,这就需要搜集整理更多的资料和文献,欢迎阅读由公务员之家整理的十篇范文,供你借鉴。
篇1
“指针”是C语言中广泛使用的一种数据类型,运用指针编程是C语言最主要的风格之一。利用指针可以表示各种数据结构,它与函数、数组的使用和传递数据有密切联系,能方便地访问数组,还能像汇编语言一样处理内存地址,从而编出精致而高效的程序。指针极大地强化了C语言的功能。学习指针是学习C语言最重要的一环,能否正确理解和使用指针是判断是否掌握了C语言的重要标志。但是指针也是C语言最危险的特性,如果使用不当,则很容易指到意想不到的地方,产生错误也很难发现。因此,对于初学者来说,应特别注意指针的应用。怎样才能应用好指针呢?下面笔者以在计算机C语言教学中的体会与大家进行探讨。
一、理解指针
在C语言中任何数据只要定义了,在内存中就是有一定的存储单元的。存储单元就是变量在计算机中的存储地址,指针就是用来表示这些地址的变量。所以简单地说,指针就是地址,变量的指针就是变量的地址,这里还涉及一个概念就是指针变量,所谓指针变量就是用来存放指针(地址)的变量。例如:int a;假设a的地址是2000,而2000又存储在变量point中,那么变量point就是指针的变量简称指针变量,a就是指针变量所指向的变量。很多初学者都存在这样的误区:既然指针放的是地址,而2000正好是变量a的地址,那么对于指针point就可以这样赋值:point=2000,这是错误的,这里的2000表示的不是地址是一个整型数据。所以对于指针变量的赋值只能用取地址运算符“&”进行赋值即:point=&a;&a即为a的地址。
二、指针与函数
指针作为C语言的精华有很多用途,除具有一般的功能外,其中具体特殊功能的应用总结起来有三个方面:一是用于在函数中可以返回多个值;二是可以实现动态调用函数;三是实现数组的动态定义。其中,普通变量作为函数的参数,传递的是变量的值,因此只能带回一个返回值,但在有些场合需要返回多个值,这就必须用到指针做函数的参数,因为指针作为参数传递的是地址,让实参和形参指向同一个变量的地址,N个形参所指向的变量的值改变了,N个实参的值也自然改变了,从而实现了带回多个返回值。这里举个例子,编写一个函数实现两个数从小到大输出。这个程序需要子函数实现两个数的交换,把交换后的两个值通过指针传回主函数输出,传回来的是两个值。所以普通变量做函数的参数是无法实现的,只能用指针作为函数的参数。具体实现:
子函数实现交换:
swap(p1,p2)
int *p1,*p2;
{int p;
p=*p1;
*p1=*p2;
*p2=p;
}
主程序实现调用,输出:
main()
{int a,b;
int *pointer_1,*pointer_2;
scanf(“%d,%d”,&a,&b);
point_ 1=&a;
point_2=&b;
if(a
swap(point_1,point_2);
printf(“%d,%d”,a,b);
}
由此可见,要通过函数调用得到N个返回值可以通过以下三步实现:(1)主调函数中设N个变量,用N个指针指向他们;(2)将指针变量作实参,将N个变量的地址传给形参;(3)通过形参指针变量指向的改变,改变N个变量的值。最后主调函数中就可以得到N个变量的返回值。
三、指针与数组
前面提到任何数据都有存储单元,都有指针。所以,从这个角度出发可以将指针分为:指向变量的指针、数组指针、字符指针、指向指针的指针、函数指针、结构变量的指针及文件指针,等等。其中,指向变量的指针就是存储变量的地址的,这是指针最简单的一种类型。那么一个变量有地址,一个数组有若干个元素,每个元素都有一个地址,所谓数组的指针,就是指数组的名称,实际上是指向整个数组空间的起始地址。数组元素的指针是数组元素的地址。例如:int a[10];int*p;这里的数组名a就是数组的首地址,本质上是一个指针。a[2]表示距离a指向空间向后2个位置所在空间中的存放的值,所以a[2]=*(a+2)。那么如果让p=a,p就是指向数组的指针,对于a我们可以做加减整数运算,利用它表示数组中任何数据的值。那么对于指针也可以通过加减整数运算来表示数组中的任何数据。指针变量加上或减区一个整数n表示把指针指向的当前位置向前或向后移动n个位置。具体移动的字节数和指针数组的类型在内存所占的字节数有关系,如果指针数组类型为整型,在内存中占2个字节,那么,指针p+1,实际上的地址值就是原址加2,对于数组元素来说就是指针向后移动一个元素。如int a[10],*p,*s;p=a;s=p+2;其中s的值表示数组中首地址向后移动2个数组元素的位置,表示a[2]对应的地址,而具体移动的字节数则为4个字节。为了表示两个地址间存在的距离,可以通过指针间的减法实现。指针之间是不能有加法操作的,指针的加减运算只能对数组指针变量进行,对指向其他类型的变量的指针变量做加减运算是毫无意义的。而且两个指针变量之间的运算只有指向同一数组时它们之间才能进行运算,否则运算将失去意义。
四、结语
C语言是到目前为止学习最多的程序设计语言之一,也是国外大学计算机专业唯一的必修课程。在整个C语言教学中,指针是一个十分重要的部分,也是最难掌握的部分之一。本文从对指针概念的理解、指针在函数和数组的使用等方面系统论述了指针,目的是让大家清晰地了解指针、掌握指针,从而高效地应用指针。只有掌握好指针,才能充分发挥C语言的优势。
参考文献:
[1]谭浩强.C程序设计教程.北京:清华大学出版社,2008,11.
[2]陈刚.C语言程序设计.清华大学出版社,2010,2.
篇2
【关键词】C语言 指针 反汇编 间接寻址 寄存器 栈
1 引言
C语言诞生于20世纪70年代的美国贝尔实验室,它是面向过程的,可移植的,功能强大的高级程序设计语言。尽管现如今有许多功能更强大的面向对象的高级程序设计语言(如C++,Java,C#等),C语言仍然具有旺盛的生命力,其仍是计算机领域的通用程序设计语言,特别是在底层的硬件驱动领域。这一切都要归功于指针,指针是C语言最重要的特性之一,利用它可以直接操作硬件,这是它的优点,也是它的缺点,因为直接操作硬件稍有不慎,就会导致非常严重的后果。
2 C语言指针简介
现代计算机中大部分都是按字节划分内存的,每个字节都有唯一的地址,C语言中的所有指针操作都是基于这些地址的。在C程序中一个变量会占用一个或多个字节,第一个字节的地址就是该变量的地址,将该地址赋值给某个变量后,就称其为指针。指针在C程序开发过程中发挥着举足轻重的作用,其基本应用有如下三点:
2.1 指向基本数据类型
假设我们定义int i = 10,则我们就占用了4个字节的内存(假设是在32位架构下),这4个字节就和变量名i建立了某种特殊联系,就可以通过该变量i对这4个字节进行读写操作。或者可以通过指针方式操控这4个字节。定义int*p = &i,就将该变量的首地址赋值给了指针变量p。然后就可以通过*p,对这4个字节进行读写操作。此时*p和i是完全等价的,即*p是变量i的别名。这是指针最基础的应用。
2.2 当指针作为函数参数时,它就可以发挥出强大的作用,特别是在数组,字符串,文件等的处理中
主要作用有如下两点:
2.2.1 让函数返回多个值。假设有如下函数声明
int foo(double * a,double * b);
则我们可以在函数内部修改a和b,在函数返回时,除了返回一个整型值外,还可以返回这两个被修改过的浮点数。假如不希望修改这两个浮点数,可以加上const修饰,如下所示:
int foo(const double *a,const double *b);
则在函数内部就不可以对变量a和b进行修改。这种技术在字符串处理函数中应用的特别多,是因为不希望源字符串被误改。例如:
char * strcpy(char *dest,const char *src);
2.2.2 节约内存空间,提高运行速度
在函数间传递数组,结构体或文件时,如果像传递普通变量那样,将参数复制一个副本到函数栈帧,就会给程序带来很大的开销,浪费空间和时间,因为这几个变量不再像普通变量那样只占几个字节,特别是文件通常都是很大的,从几K到几百M。这时最好的解决方法就是把该结构体变量或文件的地址传递出去,即多个函数操作的是同一个内存块。
2.3 指针还可应用于动态内存分配,从而修补数组在程序运行期间无法动态改变大小这一缺陷。动态内存分配主要用于构建链表,数,图等数据结构
但指针的操作需要很仔细,稍有疏忽就会导致程序崩溃。例如当我们申明了一个指针,而没有及时初始化,此时它就是一个野指针,对野指针指向的位置进行读写就会导致程序出错,因为有可能程序关键部分被无意修改了。再比如在某个函数内部动态申请一块内存,但在函数退出之前却忘记了及时的回收它,就会导致指向那块内存的指针丢失,即程序失去了对那块内存的控制,但那块内存仍然被占用着,如果继续重复执行该函数,就会导致内存大量被占用,而无法释放,直到系统崩溃。还有就是我们动态申请内存时,没有判断申请是否成功(即判断是否为NULL),而刚好此时系统无法提供我们所需的内存块,就直接操作指针,也会导致程序出错。正是基于这方面的考量,后来许多基于C语言发展起来的语言(如Java,C#),都舍弃了指针操作。
3 寄存器间接寻址模式简介
C语言函数的执行都是依赖于栈的,每个函数在执行之前都需要在栈上开辟一块属于自己的空间,这个空间就是栈帧。这个栈帧的建立和释放是依靠编译器在函数头部和尾部添加的一段汇编代码完成的。这就是任何高级语言编写的程序在链接成为可执行程序之前都必须被编译为汇编语言程序的原因之一。当栈帧建立完成后,寄存器ESP指向栈帧的头部,EBP指向栈帧的尾部,即此时ESP和EBP分别保存栈帧的头部和尾部的内存地址。随着数据的压栈和出栈,会导致栈顶会不断变化,即ESP保存的内存地址会不断变化,而栈底在整个函数执行期都保持不变,所以EBP可以作为访问当前栈底前后内存块的基准。例如:movl 0xa,-0x14(%ebp)就表示从EBP指向的内存位置向下偏移20个字节处开始保存0xa,这就是寄存器间接寻址。
4 分析反汇编代码
测试代码如下:
int main(void)
{
int i = 10;
int *p = &i;
*p = 123;
printf("%d\n",*p);
return 0;
}
本次测试的环境是32位架构Ubuntu 4.2.0-42-generic,gcc版本是: 5.2.1 20151010。不同的版本在生成的汇编代码上可能略有差别,但基本原理是不变的。
对上述代码进行反汇编,在段截取一段与本文相关的代码。这是在Linux下的反汇编结果,所以是AT&T汇编格式。
......
1. movl $0xa,-0x14(%ebp)
2. lea -0x14(%ebp),%eax
3. mov %eax,-0x10(%ebp)
4. mov -0x10(%ebp),%eax
5. movl $0x7b,(%eax)
6. mov -0x10(%ebp),%eax
7. mov (%eax),%eax
8. sub $0x8,%esp
9. push %eax
10. push $0x8048560
11. call 8048330
......
Main函数执行时,其栈帧会不断变化,其变化过程如图1和图2所示。为了叙述的方便,假设栈帧-0x14(%ebp)处的内存地址为0x12345678,即灰色部分。这11行汇编代码具体功能详述如下:
(1)在栈低下方偏移0x14处保存数字10。
(2)将内存地址0x12345678,存入到CPU的寄存器EAX中。
(3)将地址0x12345678存入到-0x10(%ebp)中。
(4)再将地址0x12345678存储到EAX中。
(5)在地址0x12345678地址处保存0x7b。
(6)将地址0x12345678保存到EAX中。
(7)从地址0x12345678处加载4字节的数据到EAX中。
(8)更新ESP,因为-0x10(%ebp)和-0x14(%ebp)处这8个字节被占用了。
(9)将EAX压栈,为调用printf做准备。
(10)将字符串“%d\n”的地址压栈。
(11)调用printf函数。
简单来说,就是把某个需要操作的对象的内存地址保存到了栈帧中,当需要读写该对象时,就把该地址加载到寄存器中,然后通过寄存器间接寻址实现读写。另外,汇编语言中并没有局部变量这一概念,C语言程序中的局部变量也是通过寄存器间接寻址实现读写的。例如上述汇编代码的第一句就是通过寄存器间接寻址找到0x12345678这个内存位置,然后写入数字10的。
而在嵌入式系统中,需要读写大量的寄存器,此时最好的方法就是通过指针操控它们。要操控这些寄存器的唯一的方法就是通过地址访问它们,即通过指针读写寄存器。跟一般桌面应用开发相比,唯一不同的就是需要先把由CPU厂商提供的寄存器编号强制转换为地址(桌面应用开发中,由于系统保护,不允许直接把一个整数强转为地址)。该强转一般是通过宏定义来实现的,如下所示:
#define GPJ0CON = (*(volatile unsigned int *)0xXXXXXXXX)
然后在程序中就可以像对待普通变量一样对它进行写入和读取工作。而在汇编层,依然是寄存器间接寻址,在此不再赘述。因为涉及到大量的寄存器的读写,所以通常的做法就是把大量的与寄存器读写有关的宏定义放在一个单独的文件,便于查找和修改。
5 总结
指针运算就是对寄存器间接寻址的封装,目的是隐藏汇编层的寄存器,栈帧,栈顶和栈底等复杂概念,从而为开发人员提供一个更加友好,逻辑上更接近人类思维的操作。而寄存器间接寻址依赖的是内存地址,即指针运算依赖的就是内存地址。所以说指针的本质就是内存地址。则对指针执行乘法或除法运算在逻辑上是无法说通的,当然编译器也会报错。因此指针的合法算术运算只能是加减整数或两个指针相减,这在数组运算别有用。通过指针加减整数就可以读写数组中不同的元素,但一定要注意不能越界。当两个指针指向同一个数组的不同元素时,可以执行指针相减运算,得出它们之间相差几个元素。理解了指针的本质就是内存地址之后,对数组指针,函数指针,多级指针的理解会有很大的帮助。
参考文献
[1][美]K.N.King著.吕秀锋,黄倩,译.C语言程序设计现代方法(第2版)[M].北京:人民邮电出版社,2010.
[2][美]Richard Blum著.马朝辉,等译.汇编语言程序设计[M].北京:机械工业出版社,2006.
[3]韦东山.嵌入式Linux语言程序开发完全手册[M].北京:人民邮电出版社,2008.77-78.
篇3
关键词:指针变量 数组 字符串 函数 常见问题
中图分类号:TP312 文献标识码:A 文章编号:1673-9795(2013)08(b)-0163-01
指针是C语言中广泛使用的一种数据类型。运用指针编程是C语言最主要的特点之一。利用指针变量可以表示各种数据结构,也能很方便地使用数组和字符串,更加能像汇编语言一样处理内存地址,[1]从而编写出精练而高效的程序。
1 指针变量的使用优势及常规用法
(1)使用指针指向数组首地址,简化了数组相关的程序内容的书写,避免了整体使用数组,在程序执行中减少了先找数组元素的地址再取数组元素内容的过程,直接在数组所在的地址范围内操作数组元素,提高了程序的执行效率。(2)使用指针指向字符串(即字符数组),把一个字符串整体当作一个数组元素,多个字符串的指针变量就构成了指针数组,不仅节省了内存空间,还大大地提高了程序的执行效率。(3)指向单变量的指针变量作为函数参数,可以在程序执行过程中及时转向调用函数的入口。节省内存空间的同时,把指针变量替代单变量作为直接变量在调用函数执行过程中执行相应程序操作,免去了返回值的执行时间与过程。(4)指向结构体复合变量的指针变量作为函数参数,可以通过变化结构体变量灵活使用指针变量在调用函数中执行函数的程序操作,不仅节省内存空间与执行时间,而且方便程序变量的修改,提高了程序的可移植性。(5)指向函数的指针变量作为函数的参数,可以在一个主函数中实现多个自定义函数功能间的调用,大大地提高了程序的灵活性与可移植性及程序执行的效率。(6)使用指针指向文件类型结构体,可以找到与之相关的文件,实现文件的访问,在主函数执行过程中灵活转向其它文件的执行。
2 指针变量使用常见问题及解决方法的探求
2.1 指针变量的初始化
同其他变量的初始化相似,在指针变量的定义之后就应该给指针变量赋一个初始的地址值。如果没有给定义的指针变量赋初值的话,指针变量的值不定,可能会导致一些隐藏在某些地址号的内存中的难以跟踪的漏洞(bug)运行。如:
int *p; *p=100;
p定义为一个指向整型变量的指针变量,但是却没有给p赋予一个初始的地址值,只是把一个存储100的常量的存储单元的首地址赋给了p,而这个存储单元的首地址可能在程序其它位置另作它用,就会产生隐形的难以追踪的bug的运行。因此,为了避免可能性的发生,就要和其他变量的使用一样,在定义指针变量的时候就要同时给予指针变量一个初值,以确定指针变量的初始的地址,即指针变量的初始化。将上述例子修改为:
int a=100; int *p=&a;
还要注意把“int *p=&a;”和“*p=&a;”混淆,前者是指针变量的初始化语句,即定义的同时给指针变量赋初值,而后者是一个旨意错误的赋值语句,把整型变量a的首地址赋给了p所指向的整型变量。
2.2 指针变量的赋值
给指针变量赋予的初值一定是地址。同样,在程序中给指针变量重新赋予的值也只能是地址或使指针变量指向同类型的变量值的首地址。如:
int a,*p; p=a;
要使p指向a,就要有地址运算符&对a取首地址后赋给p,或者把变量取内容赋给p,而不是直接把a赋给p。C语言编译器会提示指出这是个语法错误,给指针变量赋予的内容和指针变量不匹配。正确的赋值一般形式为:
int a,*p; p=&a;
或 int a,*p; *p=a;
还要说明的是指针的指向要有具体类型说明。不能给指针赋予与其基类型不符的地址,否则也会出现语法上错误。如:
int a=100; double *p; p=&a;
在给指针赋值时,不只要求是地址,还要是一个与该指针类型相符的变量或常量的首地址。而上述例子中,a是整型的变量,p是基类型为双精度型的变量。二者不相匹配,这种赋值在编译时就会发生语法错误。因此,给指针变量的赋值要注意指针变量的基类型,即指针变量能够指向的变量类型。
2.3 指针在函数之间值的传递
#include “stdio.h”
void swap(int *a, int *b)
{int t; t=*a; *a=*b; *b=t;}
void main( )
{int x,y; printf(“请输入两个整数:”);
scanf(&x,&y); printf(“x=%d, y=%d\n”,x,y);
swap(&x,&y); printf(“x=%d, y=%d\n”,x,y);}
函数间的值传递也可以通过实参的地址单向传递给形参的指针变量,直接调用函数,完成函数间数据传递的目的。主函数main( )在调用函数swap( )的同时,把变量x和y的地址分别单向传递给了指针变量a和b。也就是主函数中对整型变量x和y的操作,通过地址的传递,虽然在调用函数过程中形式上是对指向整型变量x和y的指针变量a和b的内容(即x和y)的操作,实质上仍然是继续对整型变量x和y调用函数的操作。也就没有必要给主函数返回x和y的值了。省去了返回的时间和操作过程,提高了程序的执行效率与正确率。
2.4 指向指针变量的指针变量
*p,**p,***p分别叫做一级指针、二级指针和三级指针。如果这样定义:
int a, *p, **q, ***r;
则第一个*p中的p可以用来存放普通整型变量的地址,例如赋值:p=&a。第二个**q中的q可以用来存放整型变量地址的地址,例如指针变量p的地址,p是指针变量,变量的值是整型变量a的地址,那么p这个指针变量的地址就需要一个比p高一层的指针来存放。因此可以这样赋值:q=&p。第三个***r,道理相同,可以这样赋值 r=&q。指针的嵌套使用,使程序在执行时更灵活,更有效率。
3 指针的使用是C语言程序设计中最重要的一环
能否正确理解和使用指针是我们是否真正掌握C语言的一个标志。C语言中指针的使用比较灵活,很多人在实际编程中很容易出错,而且这种错误恰恰又难以发现,所以建议初学者大量地上机调试程序,以弄清一些细节,并积累经验,为后续编程内容的学习打好坚实的基础。同时,指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要多编程并上机调试。只要做到这些,指针也是不难掌握的。
参考文献
篇4
关键词:存储空间图;间接寻址;一级指针;二级指针;存储单元
中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)16-31093-03
A Discussion about the Relation of C Language Pointer and Assemble Language Indirect Addressing――Giving Analysis from the Storage Space Digraph
WANG Hai-yan
(Computer Science Department of Suqian College, Suqian 223800, China)
Abstract: C language is a user-oriented procedural language. Pointer is the most flexible part in this language. Assemble language is a language which is processor-oriented and there is no definite conception of pointer, but the similar conception of pointer emergences everywhere. In this paper, it present the application of pointer in assemble language through indirect addressing mode. Depending on the storage space digraph and the relation between pointer of C language and indirect addressing of assemble language, it makes it easier to understand the application and relation between the two languages.
Keywords: Storage Space Digraph; Indirect Addressing; Pointer; Second Rank Pointer; Storage Unit
1 引言
作为最基本的编程语言之一,汇编语言的重要性勿庸置疑,即使是 Linux 程序员有时也需要使用汇编语言解决实际问题,理由很简单:精简、高效和 libc 无关性。假设要移植 Linux 到某一特定的嵌入式硬件环境下,首先必然面临如何减少系统大小、提高执行效率等问题,此时或许只有汇编语言能帮上忙了。我们常说汇编语言的抽象是C语言, 而C语言中最灵活是C语言中拥有“指针”这个数据类型。那么汇编语言和C语言中的指针有什么样的关系呢?我们也知道在汇编语言中,几乎所有对内存的操作都是对给定地址的内存进行访问来完成的,那么在汇编语言中,绝大多数操作也必然和地址(即指针)产生或多或少的联系。汇编语言和CPU以及内存,端口等硬件知识是连在一起的。汇编语言中存储数据的地方不仅有寄存器而且还有存储单元,更多的数据则保存在存储单元中。因此,对编程人员而言,他肯定迫切地希望访问内存,以保存
更多的数据,本文将重点阐述访问数据的方式。
2 存储空间图的概念
画一个图形,或者观察一个图形,能帮助我们把复杂的程序设计具体化、形象化,有利于掌握程序之间的内在联系,从而更好的理解程序,激发大家对程序设计语言的兴趣。本文用形象的图形解释C语言中指针以及汇编语言中间接寻址方式之间的相互关系。文中运用类似于存储空间图的方法对两门语言进行解释。说它类似于存储空间图是因为这种图形没有用真正二进制描述空间的值和空间的地址,姑且我把这种图形叫做存储空间图。
3 两门语言之间的内在联系
我们知道在计算机中,所有的数据都是存放在存储器中的,访问数据的方式并不是唯一的。在C语言中访问单元数据有两种常见方式,一是通过名字直接访问单元数据;二是通过指针访问单元数据。直接通过单元名字访问数据,两种语言都很简单,我在这篇文章中不加以阐述。接下来我就分一级指针和二级指针分别阐述汇编语言和C语言是如何间接访问内存单元数据,又是以怎样的形式加以表现的。
3.1 C语言中的一级指针和汇编语言中一次间接寻址的联系
3.1.1 C语言中一级指针定义
指针定义形如:数据类型 *指针变量,它的存储空间图表示如下:
图1中X就是一级指针,Y是一个整形变量,X、Y的本质区别在于X单元的值是用于存放内存单元的地址,Y单元是存放任意类型的数据。X之所以指向Y,是因为Y单元的地址赋予了X,同时X所指向的类型和Y同类型。
图1
3.1.2 汇编语言中的一次间接寻址是指通过寄存器或存储单元一次间接寻找操作数。
它的存储空间图表示如下:
图2中si是cpu中的一个寄存器,si中存放着Y所在单元的地址,Y是一个单元的名称,Y单元存放着普通操作数,si之所以指向Y,是因为Y单元的地址赋予了si。
图2
图1、图2中X和si都是用于存放内存单元的地址,我们从中可以得到启迪,汇编语言中也存在着类似C语言的指针。
3.1.3 以下从编程角度深入探悉二者之间的联系。
例1 用C语言指针的方法输出a单元中的数据:
main()
{int a=3,*p;
p=&a
printf("%d",*p); 3
}
例2 用间接寻址方法把a单元中的数据送往al寄存器中:
data segment
a db 3
data ends
……
lea si, a
mov al, [si]
……
以上程序均是操作存储单元中的数据,但都不是通过单元名字操作的。例1用C语言中一级指针的方法,例2用汇编语言中的寄存器间接寻址的方法。那么二者有怎样的联系呢?为了讲清楚这个问题,我把这两个程序分别用以下存储空间图表示:
图3 C语言编程的存储空间图图4 汇编语言编程的存储空间图
上图中p和si其实质都是一级指针,在C语言中是用指针指向的内容,即用*p的形式来取得单元的数据,而汇编语言是通过寄存器一次间接寻址方式来取得单元内容,当然这都要求指针p和寄存器si首先获得单元的地址。(p=&a/lea si, a)。
3.2 C语言中的二级指针和汇编语言中二次间接寻址的联系
3.2.1 C语言中二级指针的定义。
指针定义形如:数据类型 **指针变量,它的存储空间图表示如下:
图5中X相对与Z这个变量是二级指针,它和一级指针的区别在于X这个指针所指向的内容仍然是某个单元的地址(图中是Z单元的地址)。要想输出Z单元的内容,则需要通过两次指向才能完成。
图5
3.2.2 汇编语言中二次间接寻址是指通过寄存器或存储单元两次间接寻找操作数。
它的存储空间图表示如下:
图6中si其实就等价于图5中定义的X,都是二级指针。但在汇编语言中si是一个指针寄存器,无论是作为一级指针还是作为二级指针,我们在使用的时候都是不需要定义的。事实上汇编语言中根本没有一级指针和二级指针的定义,也就是说汇编语言中没有C语言中定义上的繁琐,但你仍可以用C语言的思想来解释汇编语言中的指针问题。
图6
3.2.3 以下从编程角度深入探悉二者之间的联系。
例3 输出以下字符串
main()
{char *p[] = {"ab", "cd", "ef"};
char **sp = p;
int i;
for(i=0; i
printf("%s", **(sp+i));
}
图7 C语言编程的存储空间图
例4 累加数组array中元素和的程序段
data segment
array dw 10,20,30,40,50,60,70,80,90,100
count dw 10
sum dw?
table dw 3 dup(?);地址表
data ends
code segment
main proc far
assume cs:code, ds:data
start:push ds
……
mov table, offset ary
mov table+2, offset count
mov table+4, offset sum
mov bx, offset table
call proadd
ret
main endp
proadd procnear
……
mov si, [bx]
mov di, [bx+2]
mov cx, [di]
mov di, [bx+4]
xor ax, ax
next: add ax, [si]
add si, 2
loop next
mov [di], ax
……
proadd endp
code ends
end start
图8 汇编语言编程的存储空间图
以上程序均是通过两次操作才找出单元中的数据,前者是用C语言中二级指针二次指向的方法,后者是用汇编语言中的两次间接寻址的方法寻找操作数。从上图可知这两门语言的内在联系,即两门语言最终都是通过指针两次寻址来访问操作数。所不同的是:前者是二级指针的概念,后者是两次间接寻址。这种本质相同,只是语言描述上有所不同的概念,从存储空间图的视角可以帮助我们更好的理解他们之间的联系。
依此类推,对于多级指针的学习,我们也可以借助存储空间图来帮助我们更好的分析程序,理解程序,对于一些复杂的问题给予简化,对于不同语言之间的关系我们也能进行更好的深入思考。
4 结束语
本文通过存储空间图深入浅出的探悉了两门语言在寻找数据方面的联系。可以说C语言的指针和汇编语言的寻址方式一直困扰着很多编程者,尤其对二级指针、二次间接寻址的理解及运用更加困难。文中的例题均以最简单的题型来说明这些深奥的道理,而且从存储空间图的视角分析了二者之间的联系。相信这篇文章,不仅能帮助我们运用存储空间图解释问题、分析问题,而且能帮助我们更好的思考不同语言之间的联系,更好的去思考程序设计。
参考文献:
[1] 裘宗燕. C++程序设计语言(特别版). 北京机械工业出版社, 2002.7.
[2] Standley B.lippman. C++ Primer中文版. 人民邮电出版社,20006.3.
[3] 谭浩强. C程序设计(第二版). 清华大学出版社出版,2005.6.
[4] 钱能. C++程序设计教程. 清华大学出版社, 2005.5.
[5] 沈美明. IBM PC汇编语言程序设计. 清华大学出版社,1993.9.
篇5
1.指针的定义
指针定义格式如下:
类型关键字 *指针变量名
2.用指针表示变量
例1:
int*p;
int a;
p=&a;
“*”是乘号,又可以定义指针,还可以取指针所指向的变量的内容。
#include
void main()
{
int *p,a;
int count=19;
p=&count;
a=*p;
printf("%d\n",a);
printf("%d\n",*p);
}
“*”放在可执行语句中的指针之前,表示取指针所指向的变量的内容。
“*”放在指针定义中时,称指针定义符。
该程序运行结果如下:
19
19
3.用指针表示数组元素
例2:
int*p,*q;
int a[10];
p=a;
q=a[2];
#include
void main()
{
int a[5]={1,2,3,4,5};
int *p=a;
for(p=a;p
{
printf("%d",*p);
}
printf(“\n”) ;
}
该程序运行结果如下:
12345
该例中输出的每个数组元素都是一个整型数。
#include
void main()
{
char a[]="ABCDE";
char *p=a;
for(p=a;p
{
printf("%c",*p);
}
printf("\n") ;
}
该程序运行结果如下:
ABCDE
该例中输出的每个数组元素都是一个字符。
4.用指针表示字符串
#include
void main()
{
char *p,s[]="abcdefgh";
p=s;
printf("%s\n",p);
p=s+1;
printf("%s\n",p);
printf("%c\n",*p);
}
该程序运行结果如下:
abcdefgh
bcdefgh
b
使用格式控制符%s,输出字符指针(即p)来输出字符串。
使用格式控制符%c,输出字符指针的间接(即*p)引用来输出字符。
同样的例子如下:
#include
void main()
{
char *p,s[]="abcdefgh";
p=s;
while(*p!='\0')
{
printf("%c",*p);
p++;
}
printf("\n");
p=s;
printf("%s\n",p);
p=s+1;
printf("%s\n",p);
}
该程序运行结果如下:
abcdefgh
abcdefgh
bcdefgh
#include
void main()
{
char a[]=”ABCDE”;
char *p=NULL;
for(p=a;p
{
printf(“%s\n”,p);
}
}
该程序运行结果如下:
ABCDE
BCDE
CDE
DE
E
#include
void main()
{
char a[]=”ABCDE”;
char *p=NULL;
for(p=a;p
{
printf(“%c”,*p);
}
}
该程序运行结果如下:
ABCDE
5.指针数组与指向数组的指针
指针数组就是数组元素为指针的数组。常用的指针数苏是一维一级指针数组,即数组是一维的,元素是一级指针。
指针数组定义的格式如下:
类型说明 *数组名[大小] 例如:int*ap[5];ap是一维一级指针,该数组有5个元素,每个元素是一个一级指针。
在实际应用中,常常使用一维一级指针数组来存放若干个字符串,这样操作起来比较方便。
例:编程实现输入星期几的数字后,输出该数字对应的英文全名。
#include
char *name[]={"","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
main()
{
int week;
while(1)
{
printf("Enter week No.:");
scanf("%d",&week);
if(week7) break;
printf("Week No. %d is %s\n",week,name[week]);
}
}
该程序中指针数组name经初始化后有8个元素,name[0]不用,name[1]指向Monday,name[2]指向Tuesday …… 。
指向数组的指针,定义格式为:
int(*p)[4] 定义了一个指针,该指针指向二维数组,此二维数组每行有4个元素。
#include
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
main()
{
int (*p)[4];
p=a+2;
printf("%3d %3d %3d\n",p[0][0],p[1][1],p[-1][2]);
}
该程序运行结果如下:
907
6.用指针表示结构体成员
#include
void main()
{
structperson{charname[9];intage;};
structpersonclass[10] = { "John",17,
"Paul",19,
"Mary",18,
"Adam",16,},*p;
p=class+2;
printf("%c\n",p->name[0]);
}
该程序运行结果如下:
M
#include
struct tt
{int x; struct tt*y;}*p;
struct tt a[4]={20,a+1,15,a+2,30,a+3,17,a};
main()
{int i;
p=a;
for(i=1;i
{ printf(“%d ”,p->x);
p=p->y;
}
}
该程序运行结果如下:
20 15
首先,指针p指向数组a的首地址,a[0]。在循环中,i=1时,因此时p指向a[0],因此p->x的值是20。a[0]的第二个成员表示为p->y,此值为a+1,即a[1]的地址,也就是把这个值更新了指针p,i=2时,p->x即为a[1]的成员x的值15。
本文主要归纳了C语言中指针的基本用法,熟练地掌握指针的基本用法,为指针在程序中的应用打下一个良好的基础。在以后的文章中将详细介绍指针在程序中的应用。
参考文献:
篇6
关键词:C语言;指针;数组
中图分类号:TP311文献标识码:A文章编号:1009-3044(2010)19-5228-01
Studying the Pointer and Array Problem of C Language
LIU Wen-feng
(Computer and Information Engineering Department, Heze University, Heze 274015, China)
Abstract: Using examples and pointing the two highlights,this paper sdudys the pointer and array in solving some issues ,there is some degree equivalence; This paper has some guidance to the different levels and types of the C language developer.
Key words: C language; pointer; array
C语言课程,是计算机科学与技术以及相关学科专业的一门专业基础课。该课程学习掌握的好坏对后继课程有着非常重要的影响,而C语言课程中有两天非常重要的部分,一个是数组,另一个是指针。数组有一维数组、二维数组等,学生理解相对容易,写程序也很容易上手。而指针则是C语言课程中最难学习和掌握的内容,虽然花费了大量的时间,但是也很难熟练运用。
1 结合实例剖析指针和数组的特点
下面我们给出实例来剖析指针和数组的特点,在主函数中间填写一部分语句或使用单独的函数以实现以下功能,求出1到1000之内能被7或11整除但不能同时被7和11整除的所有整数并存放在数组aa中,并把满足条件的值存入OUT.DAT中(我们事先已经在相应的目录建好了一个空的记事本文件,文件名为OUT,扩展名改为.DAT格式),同时输出到执行屏幕上,我们使用两种方式分别加以实现。
1.1 基于指针的实现方法
首先使用指针来实现该函数的功能。
#include
#include //使用到的头文件
void writeDAT();//声明写函数
void countValue(int *a,int *n);//声明编写函数,变量均使用指针
void main()
{ int aa[1000],n,k;//定义所需变量
system("CLS");//清楚屏幕内容
countValue(aa,&n);//转入countValue执行
for(k=0;k
if((k+1) %10 ==0)
{printf("%5d",aa[k]);
printf("\n"); }
else printf("%5d",aa[k]);/*以上for语句是实现结果的屏幕输出*/
writeDAT();/*执行输出语句的函数*/}
void writeDAT()//写函数的具体实现
{ int aa[1000],n,k;
FILE *fp;//使用文件指针
fp=fopen("out.dat","w");//以写方式打开文件out.dat
countValue(aa,&n);//再执行一次countValue函数
for(k=0;k
if((k+1)%10==0)
{ fprintf(fp,"%5d",aa[k]);
fprintf(fp,"\n"); }
else fprintf(fp,"%5d",aa[k]);/*以上for语句是实现aa中的数据写入文件out.dat中,每行显示10个 */
fclose(fp);//关闭所打开的文件
}
以下是使用指针对函数countValue的具体实现。
void countValue(int *a,int *n) /*定义传递指针变量a为数组指针和n统计满足条件的个数指针*/
{ int i;
*n=0; //对指针变量所指内容赋初值
for(i=1;i
{if((i%7==0 && i%11!=0)||(i%7!=0 && i%11==0))/*如果i的值满足能被7整除同时又不能被11整除;或者i的值满足不能被7整除同时必须能被11整除。满足这两个条件之一即符合条件*/
{*a++=i;*n=*n+1;}}}
语句*a++=i,可以分为两句来实现。即*a=i,a=a+1;语句*a=i是把变量i的值存入指针a所指地址的变量空间中;语句a=a+1指的是指针变量a指向下一个数据单元。
1.2 基于数组的实现方法
以下是数组的实现方法。
#include
#include //使用到的头文件
void main()
{ FILE *fp;//定义文件类型指针
int i,aa[1000],n=0,k; //定义所需变量
system("CLS");//清楚屏幕内容
for(i=1;i
{if((i%7==0 && i%11!=0)||(i%7!=0 && i%11==0))/*如果i的值满足能被7整除同时又不能被11整除;或者i的值满足不能被7整除同时必须能被11整除。满足这两个条件之一即符合条件*/
{aa[n]=i;n++;}}//把满足条件的数据存入数组aa中,个数n值增1
for(k=0;k
if((k+1) %10 ==0)
{printf("%5d",aa[k]);
printf("\n"); }
else printf("%5d",aa[k]); //以上for语句是实现把结果输出到屏幕上
fp=fopen("out.dat","w");//以写方式打开文件out.dat
for(k=0;k
if((k+1)%10==0)
{ fprintf(fp,"%5d",aa[k]);
fprintf(fp,"\n");
}else fprintf(fp,"%5d",aa[k]); /*以上for语句是实现aa中的数据写入文件out.dat中,每行显示10个 */
fclose(fp); //关闭所打开的文件
}
数组实现相对较简单,也很容易理解和掌握。这种方法没有使用单独的函数,由于该函数简单,直接放到主程序当中来实现,当然也没有用到参数传递。避免了在参数使用和参数传递中的不必要的错误。
这两种方法,前一种方法使用参数传递,在参数传递和地址传递中,指针有其非常优越的特性,利用指针我们实现了相应功能。但在具体使用中,虽然语句较少,指针在理解和学习过程中相对复杂。如在函数中的参数传递过程中,对整型变量n的传递使用的是变量n的地址&n,而不是n本身;对数组aa[1000]在函数传递中使用整型指针a,而不是*a或&a。
2 结束语
目前很多已经成型的编程专家,在很多情况下都不使用指针,特别是在大型软件程序的开发中。因为指针非常灵活和方便,在具体使用中很容易出现引用错误和指向错误的问题,与此同时这些错误在调试和测试中又是很难被发现的。数组虽然没有指针灵活,但我们可以实现与指针相同的效果,例如很多国外的编程专家都不使用指针,而使用数组来替代它。这样就避免了很多不必要的麻烦。也不是说大家都不要学习指针了,都来学数组。如果你是软件开发的新手,建议少使用指针,当然如果你是多年的编程专家并且对C语言掌握的非常透彻,指针当然是较好的选择。
参考文献:
[1] 李明辉,丁海艳,万克星,等.全国计算机等级考试上机考试题库――三级网络技术[M].成都:电子科技大学出版社,2008.
[2] 谭浩强.C语言程序设计教程[M].3版.北京:高等教育出版社,2006.
篇7
关键词:C++语言程序设计;函数指针;分析研究
中图分类号:TP311.11 文献标识码:A文章编号:1007-9599 (2011) 24-0000-01
Analysis and Research of Function Pointers for C++ Language Programming
Zhang Suxia
(Shandong Rural Credit Cooperatives,Qingdao266550,China)
Abstract:Pointer as C++ language programming is an important concept,its application is the C++ Programming Language is very important content.Pointer as a special type of data structure,which can effectively express complex data between the logical structure of the relationship.Flexible and correctly use the pointer to the design of the program with a lot of convenience,the application of which the most significant effect is a function pointer,by using the function pointer,you can call the function can get multiple return values,and to deal directly with memory addresses and so on.This article from the introduction of C++ language program design,function pointer to talk about,and then a detailed description of the use of C++ language program design function pointers need to pay attention to the,the final C++ language program design,function pointers application techniques carried out a systematic analysis.
Keywords:C++ Language Programming;Function pointer;Analysis
一、认识C++语言程序设计中的函数指针
(一)指针与函数。在C++语言程序设计中,将指针与函数结合在一起使用具有非常丰富的内涵。比如说,可以把指针作为函数的参数来使用,也可以把指针作为函数的返回值,另外,指针可以指向函数成为函数指针等。在C++语言程序设计中,用指针作函数的参数,从而实现地址传参的调用。而所谓的调用就是系统自动将实参地址的值赋给其所对应的形参指针,从而使形参指针指向实际参数变量。这样一来,形参在函数体内的变化,将会直接影响到调用函数中与之对应的实参的值。
(二)区别指针函数与函数指针的概念。由于函数的类型是按照函数返回值的类型来定义的,所以把返回值为指针类型的函数称为指针函数。其中需要说明的是如果使用某变量的地址来充当函数的返回值的话,还需要考虑地址所对应的变量空间是否还在被占用,若地址空间已经被释放掉,那么其中的数据就有可能发生了变化,这样的话就需要将相应的变量设置为静态变量,否则的话,就不能实现正确传递参数的效果。还有一点要说明的就是在使用指针函数时,必须把接收函数值的变量设置为指针,而且其数据类型必须与返回值的数据类型相同。
由于指针变量不仅可以指向不同的数据类型,同时还可以指向函数,其中把指向函数入口地址的指针称为函数指针。函数指针作为C++语言程序设计中函数与指针结合应用的一个重要概念,函数指针的作用就是用来在函数间进行函数参数的传递。
在C++语言程序设计中常常会把指针函数与函数指针两个概念混淆起来,实际上,明白二者的实质后,二者完全是两个不同的概念,其最为显著的区别就在于函数指针中的指针是指向函数入口的,而指针函数中的指针是指向函数出口的,所以在使用时一定要把握好二者的区别,正确使用。
二、使用C++语言程序设计函数指针需要注意的问题
尽管函数指针的使用可以为程序设计带来很多的方便,但是由于指针变量自身存在的缺陷,所以在使用中如果不小心的话就会出现错误,严重的话就可能导致系统的崩溃,所以这里有必要就C++语言程序设计函数指针应用中经常出现的问题进行说明。
第一、指针变量初始值的赋值问题。尽管指针变量是指向的是相应数据变量的存储地址,但是在使用该指针变量前必须对指针变量的初值进行赋值,如果不对其赋值的话,系统就会随机对其进行赋值,显然,这就会导致比较严重的错误。
第二、指针变量所指对象的存储单元单元分配问题。在对指针变量所指的对象进行赋值时需要为其所指的对象分配充足的存储单元,如果存储单元分配不足的话也将会发生一系列的错误。
第三、在操作前不对指针的值是否为空就进行操作的问题。对于一个值为空的,它的值为空的指针类型变量而言,它是不指向任何变量的,如果强制对它进行操作的话,就可能会出现如下的几种情况:一是禁止读写;二是只允许读而不允许写;三是既允许读又允许写的三种不合法的存储区域赋值问题,显然,这一问题所造成的错误势必会非常严重。
第四、函数按地址引用时参数的误用问题。函数参数的引用包括按值引用和按地址引用两种不同的引用方式,其中按值引用的是数值而按地址引用的是地址,二者是不一样的,一定要区分开来,不能混淆。
三、C++语言程序设计中函数指针的应用技巧分析
函数指针作为一种具有特殊用途的指针,它广泛的应用于C++语言程序设计中。其中C++语言程序设计中的函数指针主要用于调用函数以及充当函数的参数这两个方面。而C++语言程序设计中函数指针的应用是有技巧的,其使用技巧如下:
第一、多态机制的实现。在C++语言程序设计中使用函数指针来实现多态机制是比较复杂的,其中主要是通过虚函数表来实现的,其中虚函数表中存放的就是由函数指针组成的数组,由这些函数指针来指向实际所要调用的函数。
第二、回调函数。所谓的回调函数可以这样的来理解,如果把某个函数的指针作为参数将其传递给另一个函数时,当这个指针用来指向函数时,就是回调函数。在C++语言程序设计中回调函数应用的比较广泛,举个例子,譬如Win32程序设计中的WinProc其实就是一种回调函数,它主要是用来处理窗口的相关消息。
第三、取代分支语句。分支语句在程序维护上往往具有一定的限制,然而函数指针的应用可以很好的解决这一问题。
参考文献:
[1]张海平.C/C++语言中函数指针的深入分析与应用[J].软件开发与设计,2009(22)
篇8
下咽癌是一种恶性肿瘤,原发于喉部以外的喉咽或者下咽部,临床上的发病率不高,对其影响报道因而不多,我院对收治的38例下咽癌患者的临床资料进行回顾性分析,所有病例都经手术及其局部穿刺病理证实,对CT应用于下咽癌的鉴别与诊断进行探讨,具体报告如下。
1 资料与方法
1.1一般资料
本文资料选择我院自2003-2010年所收治的下咽癌患者共38例,其中男34例,女4例,年龄37-70岁,平均年龄55.4±2.3岁,临床上的症状表现为,咽部出现异物感患者18例,吞咽困难患者17例,声音嘶哑患者22例,咽喉部疼痛患者23例,颈部包块患者13例,4例患者伴随呼吸困难,以上所有病例均经过手术及局部穿刺病理证实,其中经手术患者20例,鳞状上皮细胞癌是其主要病理特征,其中有13例高分化的鳞状上皮细胞癌,11例中分化鳞状上皮细胞癌,7例低分化鳞状上皮细胞癌,5例中至高分化鳞状细胞癌,3例低至中分化鳞状细胞癌。
1.2方法
CT扫描仪选择Siemens Somatom Plus或者Somatom Plus4全身扫描仪,其扫描平面需要与硬腭平行,舌骨平面到环状软骨下缘,为扫描仪扫描范围,层厚度为5mm,视为连续扫描,若为螺旋扫描,层厚应为5mm,螺距应为1,其中28例需要行增强扫描。
1.3统计学方法
应用SPSS10.0软件包对其资料进行统计学处理分析。
2 结果
2.1下咽癌具体分型分析
依据病灶位置及其下咽解剖结构分析,本组病例分为,下咽上区癌(图1、2)其病灶主要位于会厌前间隙与会厌舌面,舌骨与会厌间,表现为软组织肿块,其中明显有4例肿块较大,占据会厌前间隙,同时侵犯口底、舌根部,另有5例伴随着颈部淋巴结转移,梨状窝癌(图3-6),发生于左侧14例,发生右侧12例,咽后壁癌或者环后癌(图7-9),共有5例,有3例患者为咽后壁癌,2例环后癌,混合型癌患者3例。
2.2下咽癌患者CT具体诊断
病变部位,位于会厌舌面的肿块有4例患者,梨状窝患者26例,下咽后壁患者3例,环后区2例,混合型3例,梨状窝,环后区及其咽后壁为肿块的广泛侵入部位,沿黏膜与病灶表现为浸润性生长,也随之会形成不规则肿块,同周围的结构组织界限不够明晰。病变的密度,通过平扫发现为等或者低密度,其密度同颈动脉鞘内的血管密度相一致,不过略低于双侧下颌下腺及其胸锁乳突肌的密度,同时其密度与口底舌肌区别明显,通过增强扫描发现肿块出现显著的不均匀强化,且梨状窝出现变窄或者消失现象,咽后组织明显增厚,喉邻近结构受累,肿瘤波及喉与喉旁结构,出现了声门裂变形,旋转或者转移,喉软骨也发生破坏,同时颈部淋巴结转移,食管与其他结构明显受累,食管壁增厚,出现软组织肿块。
3 讨论
所谓下咽即为喉咽,部位在4-6颈椎前,喉的两旁及其后方,上界与会厌平,下界环状软骨下缘平,下部与食管连接,其黏膜面包含会厌舌面与舌根下部,下咽侧壁与后壁。下咽可分为四区,其一为下咽上区,其包括会厌舌面,会厌溪与舌根,其二为梨状窝区,分别位于左右,上界是为舌会厌侧皱襞,舌甲膜为外侧上部,甲状软骨翼板[1]。其三为下咽后壁区,上部为会厌,下部为环咽肌间下咽后壁。其四为环后区,从上到下依次为环杓关节面,环状软骨下缘,前后壁依次为,环状软骨后黏膜与椎前黏膜。
下咽癌其属于喉癌,一般分为喉内喉外,喉内癌一般限于喉内,发展较为缓慢,扩散也较为晚,另喉外癌则则是起源于喉的下咽,生长快,转移较早,依据1961年的第七届国际耳鼻咽喉会议[2],其将下咽癌分出单列。
对于下咽癌来说,普遍较为少见,据国内统计,在全身恶性肿瘤中仅占据0.15%-2.2%,普遍来说分为梨状窝癌,其占75%-87%,下咽后壁癌则占5%-22%[3],下咽上区癌占9%,梨状窝癌普遍容易在黏膜下浸润性生长,甲状软骨板后部逐渐被其侵犯,向上侵犯舌根部,向内侵入喉部与喉旁间隙,出现了喉旁间隙增宽现象,密度明显升高,声带出现右侧移位,淋巴结转移,转移至颈内静脉淋巴结。
通过本文结果分析,下咽癌颈部淋巴结发生转移的可能性较高,据相关文献报道高达50%,本组为78.2%[4],其中声带发生转移的情况较少见,而声门上型癌与跨声门癌发生转移的情况较多,此为CT诊断的结果,更加清晰地显示了肿瘤的部位,显示了黏膜面的情况还有喉内侵犯的情况,特别是对肿瘤的侵犯范围,CT检查更加准确,其中包括对喉软骨、声门旁间隙与会厌前间隙,诊断鉴别都较高[5]。且通过CT诊断可以区分下咽癌与喉癌,两者虽病变部位较为接近,但在CT诊断下,下咽癌是发生于喉的两侧或者下方,而喉癌也不同,为发生于喉腔粘膜的恶性肿瘤。这是CT诊断的两者差别。
通过本文分析,下咽癌通过CT检查诊断,还是较为准确的,值得临床上的广泛推广使用。
参 考 文 献
[1]屠规益.现代头颈肿瘤外科学[M].北京:科学出版社,2004,594.
[2]黄选兆,汪吉宝.实用耳鼻眼科学[M].北京:人民卫生出版社,1998,398-402.
[3] 周蓉先,罗建天,李逸尘. 喉咽癌的咽-食道钡剂造影和CT扫描检查. 复旦学报,2009,30:269.
篇9
【关键词】 抗CCP抗体;RF因子;类风湿关节炎;应用价值
类风湿关节炎(RA)以慢性关节炎性反应为主要表现, 是一种结缔组织病。如果不及时给予恰当治疗, 将会引发不可逆转的骨关节破坏。因此早期确诊利于控制病情、改善预后具有重要意义。郑州市第九人民医院对118例RA及85例非RA患者的血清抗CCP抗体、RF进行检测, 探讨二者联合检测对RA诊断的价值, 现报告如下。
1 资料与方法
1. 1 一般资料 ①RA组:本组118例均为2009年7月~2013年7月于本院就诊的RA患者, 男45例, 女73例, 年龄21~83岁, 平均(42.2±12.5)岁, 均符合1987年美国风湿病协会修订的关于RA分类的诊断标准。②非RA组:本组85例均为同期于本院就诊的其他自身免疫性疾病患者, 男36例, 女49例, 年龄在18~79岁, 平均(39.7±12.1)岁, 其中系统性红斑狼疮(SLE)26例、骨性关节炎(OA)19例, 强直性脊柱炎(AS)13例、硬皮病9例、干燥综合征(SS)8例, 混合性结缔组织病(MCTD)5例, 皮肌炎3例, 血管炎2例。两组在性别、年龄、患病类型、临床表现等方面差异无统计学意义。
1. 2 实验方法 本组所有病例均于晨起空腹静脉采血3 ml, 经自然凝固后分离血清保存于-20℃待测。①抗CCP抗体检测:采用酶联免疫吸附法(ELISA), 试剂由欧洲诊断公司提供, 采用Stat fax-2100型酶标仪检测吸光度, 严格按照说明书操作, 结果以>25 U/ml判定为阳性。②RF检测:采用透射比浊法, 试剂仪器为全自动特种蛋白仪, 严格按照说明书操作, 结果以>25 U/ml判定为阳性。
1. 3 统计学方法 采用SPSS18.0统计软件进行数据处理, 采用四格表计算抗CCP抗体及RF的敏感性和特异性, 组间比较采用χ2检验, P
2 结果
RA、非RA患者抗CCP抗体、RF检测结果见表1, RA诊断结果显示:抗CCP抗体敏感性为78.8%, 特异性为89.4%;RF因子敏感性为89.0%, 特异性为65.9%;抗CCP抗体和RF联合检测对RA进行诊断敏感性为98.2%, 特异性为59.6%。抗CCP和RF因子联合检测诊断RA可明显提高敏感性, 但特异性下降, 差异具有统计学意义(P
3 讨论
类风湿关节炎(RA)是一种常见的自身免疫疾病, 具有高发性、高致残性等特点, 关节及周围组织呈对称性, 可引发多种并发症。临床治疗RA的目标是确保疾病无进展, 使之保持正常的生理功能, 以达到缓解病情的目的。因此对RA早期进行诊断确诊是治疗的关键。目前诊断RA多依赖症状、X线改变以及对RF的检测, 但临床表现多不典型, 易错失治疗时机, 而RF的检测具有局限性, 敏感但特异性低, 在其他的结缔组织疾病, 如系统性红斑狼疮以及部分健康老人的血清里都可以检测出, 因此给临床确诊带来困难。
抗环瓜氨酸肽抗体(CCP)是环状聚丝蛋白的多肽片段, 可在RA早期出现, 通常是RA患者还未出现关节损伤之前就能检出, 对类风湿性关节炎(RA)具有较高的特异性, 可克服RF存在的不足。本研究对118例RA患者和85例非RA患者血清抗CCP抗体、RF进行平行检测, 特异性差异具有统计学意义。抗CCP抗体较RF具有较高的特异性(89.4%)可避免临床误诊;联合检测可提高试验敏感性(98.2%)降低了RF对早期RA的漏诊率[1]。联合检测诊断RA可靠有效, 对于RA早期治疗与干预、阻断病情发展、提高患者生活质量具有重要意义。
篇10
【关键词】 脑CT检查;精神发育;诊断;治疗
doi:10.3969/j.issn.1004-7484(s).2013.11.801 文章编号:1004-7484(2013)-11-6783-01
精神发育迟滞(mental retardation,MR)是指个体在发育阶段(通常指18岁以前),由生物学因素、心理社会因素等原因所引起,以智力发育不全或受阻和社会适应困难为主要特征的一组综合征。主要有两大方面的原因引起精神发育迟滞:生物学因素和心理社会因素,目前对于精神发育迟滞的诊断,临床主要根据智力测评,生活能力测试,心理年龄评价等方面进行综合评估,根据智力水平的不同,精神发育迟滞共分为轻度、中度、重度和极重度四级。程度越重,患者预后及通过康复训练所获的个人能力改善程度也越差。因此,准确定级对患者的预后意义重大。本文收集100例精神发育迟滞患者的CT和临床资料,并结合文献进行初步探讨。
1 资料与方法
1.1 一般资料 从2009年4月至2010年4月100例门诊诊断为精神发育迟滞并登记鉴定的患者中,选取有头颅CT检查结果的病例100例,其中男55例,女40例,均自幼发生智障,无严重脑外伤史及癫痫史。年龄1-18岁,平均年龄11岁。
1.2 研究方法 影像学检查方法:采用Philips Brilliance 6螺旋CT机,以OM线为起始线进行头颅轴扫,扫描参数:管电压120kV,成人管电流150mA,年龄小于12岁管电流100mA,转速115s/圈,探测器宽度6×3mm,层厚9mm轴位扫描。滤过函数Brain Standard(UB),用Philips Brilliance 6自带工作站EBW作图像后处理,软件版本213。
2 结 果
100例患者中,CT检查结果能有效判定为92例,需其他检查共同判定有8例。CT检查能有效检查出的病理有:囊肿,包括蛛网膜囊肿、透明膈囊肿、枕大池囊肿,交通性脑积水;脑发育异常,包括大脑或小脑半球体积异常、小脑蚓部及胼胝体发育异常、平滑脑畸形、巨脑回畸形、脑裂畸形、灰质异位等;脑白质异常,包括髓鞘形成不良或髓鞘脱失。
3 讨 论
CT以其对组织解剖结构较高的密度分辨力及分层记录图像的优势而广泛应用于临床及研究,尤其是中枢神经系统。早在八十年代,就有关于CT应用于精神疾病的研究。根据相关文献报道,对于有脑部器质性病变的精神疾患,CT有较高的阳性检出率,并且病变范围大小与智力损害和精神症状的严重程度呈正相关。随着CT技术的飞速进步,其在有器质性病变的精神疾病中的应用也得了很大的发展。WHO(1985)资料报导精神发育迟滞症的轻度患病率为3%,重度(含中度)约为3‰-4‰,可以看出该病不容轻视。目前,精神病学有关精神发育迟滞诊断标准,仍然是以智力测评、社会适应能力和心理年龄综合评价作为诊断、分级的标准,而未将脑CT的异常列为分级的参考指标。
从本次的研究结果表明,CT检查结果有效率很高为92正常的比例明显增加,但异常病例中脑发育异常仍占一定比例,占8%。但异常病例中,仍然以脑发育异常为主。精神发育迟滞伴有脑部器质性损害的发生率较高,其原因主要有:①遗传异常,由基因或染色体异常所致的神经系统发育不良、畸形或先天性代谢Down综合征、Turner综合征;苯丙酮尿症、半乳糖血症、家族性黑朦性痴呆;神经纤维瘤病、结节性硬化及先天性脑积水、脑穿通畸形、小头畸形等。这些大都可有影像学表现。②环境因素:妊产期有害因素,主要是妊早期感染,如巨细胞病毒和单纯疱疹病毒感染,此类患儿生后约15%-20%有先天畸形,表现为小头、智力迟钝、癫痫等;另外,应该注意到妊娠期受到放射线照射也可能导致患儿出现小头、智力发育迟滞及器官发育畸形等。神经病理学有相关研究报道,极重度精神发育迟滞患者中90%肉眼和镜下脑组织异常改变,3/4可明确诊断,10%肉眼和镜下脑组织无改变。但是,精神发育迟滞患者中脑CT检查存在一定数量的阴性结果,部分脑CT异常者却与临床分级相矛盾,能否假设这种现象的发生可能与以下因素有关:脑CT检查为正常的精神发育迟滞患者中,部分患者脑解剖结构的确没有异常,只是神经递质浓度和受体的敏感度发生改变,普通CT无法显示,脑部存在较轻微解剖改变,但受CT分辨力及影像科医师识别能力的限制而未能检出;目前临床使用的评定方式并未将被鉴定者的年龄、生活环境、父母受教育程度、民族、地域、医患之间是否使用同一种语言进行交流等作为影响因子,不能排除由于语言文字等方面的差异,使受测者无法理解检测者的目的及要求,导致量分过低而给予不恰当的智障等级的可能;智障等级为轻-中度患者中,也有少数患者CT检查存在脑发育异常的结果,推测这可能与患者接受鉴定时的年龄偏大,或幼年时接受过良好的家庭教育和(或)系统的康复训练,患者的智商和依从度获得明显改善有关。
本组数据显示,智障程度越轻,脑器质性病变发生几率也越低,这与国内外同类文献相吻合。综上所述,对智障患者的相关测评,结合脑CT检查结果,对确定等级有积极的意义。
参考文献