文档库 最新最全的文档下载
当前位置:文档库 › 指针的动态变量

指针的动态变量

指针的动态变量
指针的动态变量

指针的动态变量

1.定义指针类型

在Turbo Pascal中,指针变量中存放的某个存储单元的地址,即指针变量指向某个存储单元。一个指针变量仅能指向某一种类型的存储单元,这种数据类型是在指针类型的定义中确定的,称为指针类型的基类型。指针类型定义如下:

类型名=^基类型名;

例如:type q=^integer;

var a,b,c:q;

说明q是一指向整型存储单元的指针类型,其中"^"为指针符。a,b,c均定义为指针变量,分别可以指向一个整型存储单元。

上例也可定义为:

var a,b,c:^integer;

指针也可以指向有结构的存储单元。

例如:type person=record

name:string[10];

sex:(male,female);

age:20..70

end;

var pt:^person;

pt为指向记录类型person的指针变量。

2.动态变量

应用一个指针指向的动态存储单元即动态变量的形式如下:

指针变量名^

例如:p^、q^、r^

指针变量p和它所指向的动态变量^p之间有如下关系:

P->P'

以下语句把整数5存放到p所指向的动态变量p^ 中去:

p^:=5;

以下语句把p所指向的p^中的值赋给整型变量i:

i:=p^;

如果指针变量p并未指向任何存储单元,则可用下列赋值语句:

p:=nil;

其中nil是Turbo Pascal保留字,表示“空”,相当于C里面的null

10.2 对动态变量的操作

在Turob Pascal程序中,动态变量不能由var直接定义而是通过调用标准过程new建立的。过程形式为:

new(指针变量名);

如果有下列变量定义语句:

var p:^integer;

仅仅说明了p是一个指向整型变量单元的指针变量,但这个整型单元并不存在,在指针变量p中还没有具体的地址值。在程序中必须通过过程调用语句:new(p);才在内存中分配了一个整型变量单元,并把这个单元的地址放在变量p中,一个指针变量只能存放一个地址。在同一时间内一个指针只能指向一个变量单元。当程序再次执行new(p)时,又在内存中新建立了一个整型变量单元,并把新单元的地址存放在p中,从而丢失了旧的变量单元的地址。

为了节省内存空间,对于一些已经不使用的现有动态变量,应该使用标准过程dispose 予以释放。过程形式为:dispose(指针变量名);为new(指针变量名)的逆过程,其作用是释放由指针变量所指向的动态变量的存储单元。例如在用了new(p)后在调用dispose(p),则指针p所指向的动态变量被撤销,内存空间还给系统,这时p的值为nil。

例:输入两个数,要求先打印大数后打印小数的方式输出,用动态变量做。

program dongtai;

type intepter=^integer;

var p1,p2:intepter;

procedure swap(var,q1,q2:intepter);

var p:integer;

begin

p:=q1;q1:=q2;q2:=p;

end;

begin

new(p1);new(p2);

writeln('input 2 data: ');readln(p1^,p2^);

if p1^ writeln('output 2 data: ',p1^:4,p2^:$);

end.

1 建立链表

链表是动态数据结构的一种基本形式。如果我们把指针所指的一个存贮单元叫做结点,那么链表就是把若干个结点链成了一串。我们把链表叫做动态数据结构,是因为链表中的结点可增可减,可多可少,可在中间任意一个位置插入和删除。

下面就是一个链表:

(图T10.2)

每个链表有两个域,一个是数据域,一个是指向下一个结点的指针域。最后一个结点的

指针域为NIL,NIL表示空指针。

要定义一个链表,每个结点要定义成记录型,而且其中有一个域为指针。

TYPE

POINT=↑PP;

PP=RECORD

DATA:STRING[5];

LINK:POINT;

END;

VAR P1,P2:POINT;

在这个定义中,定义了两个指针变量P1,P2。每个结点有两个域,一个是数据域,一

个是指针域,数据域是字符串型。这种定义中,指针中有记录,记录中有指针,形成一种递归调用。

下面我们来看一下如何定义上图的链表:

有:P1,P2,P3,P4属于POINT类型。

(1)建立第一个结点

NEW(P1);

P1↑.DATA:=D1;

(2) 建立第二个结点,并把它接在P1的后面

NEW(P2);

P2↑.DATA:=D2;

P1↑.LINK:=P2;

(3) 建立第三个结点,并把它接在P2的后面.

NEW(P3);

P3↑.DATA:=D3;

P2↑.LINK:=P3;

(4) 建立最后一个结点,并把它接在P3的后面.

NEW(P4);

P4↑.DATA:=D4;

P4↑.LINK:=NIL;

P3↑.LINK:=P4;

例1 建立一个有10个结点的链表,最后输出该链表。

P2前一个结点,K一直指向第一个结点。

PROGRAM E1(INPUT,OUTPUT);

TYPE point=^pp;

pp=record

data:string[5];

link:point;

end;

VAR

p1,p2,k:point;

i:integer;

BEGIN

{产生新结点P1,作为链表的头}

new(p1);

writeln('input data');

readln(p1^.data);

{指针K指向链表头}

k:=p1;

{用循环产生9个新结点,每个结点都接在上一个结点之后}

for i:=1 to 9 do

begin

new(p2);

writeln('input data');

readln(p2^.data);

p1^.link:=p2;

p1:=p2;

end;

{给最后一个结点的LINK域赋空值NIL}

p2^.link:=nil;

{从链表头开始依次输出链表中的DATA域}

while k^.link<>nil do

begin

write(k^.data,'->');

k:=k^.link;

END.

在本程序里,输出链表的过程就是一个链表的遍历。给出一个链表的头结点,依次输出后面每一个结点的内容,指针依次向后走的语句用K:=K↑.LINK 来实现。

例2 读入一批数据,遇负数时停止,将读入的正数组成先进先出的链表并

输出。

分析:首先应定义指针类型,结点类型和指针变量,读入第一个值,建立首结点,读入第二个值,判断它是否大于零,若是,建立新结点。

PROGRAM fifo(input,output);

{建立先进先出链表}

TYPE

Point=^node;

Node=RECORD

Data:real;

Link:point

END;

VAR

head,last,next:point;

x:real;

BEGIN

{读入第一个值,建立首结点}

read(x);

new(head);

head^.data:=x;

last:=head;

{读入第二个值}

read(x);

write(x:6:1);

WHILE x>=0 DO

BEGIN

{建立新结点}

new(next);

next^.data:=x; {链接到表尾}

last^.link:=next; {指针下移}

last:=next; {读入下一个值}

read(x);

write(x:6:1)

END;

Writeln; {表尾指针域置NIL}

Last^.link:=NIL; {输出链表}

Next:=head;

WHILE next<>NIL DO

BEGIN

Write(next^.data:6:1);

Next:=next^.link

END;

Writeln

END.

例3 读入一批数据,遇负数时停止,将读入的正数组成先进后出的链表并输出。

PROGRAM fifo(input,output);

{建立先进后出链表}

TYPE

point=^node;

node=RECORD

data:real;

link:point

END;

VAR

head,last,next:point;

x:real;

BEGIN

{初始准备}

next:=NIL;

read(x); {读入第一个数}

write(x:6:1);

WHILE x>=0 DO

BEGIN {建立一个新结点}

new(head);

head^.data:=x; {链接到表首}

head^.link:=next;{指针前移}

next:=head; {读入下一个数}

read(x);

write(x:6:1)

END;

writeln; {输出链表}

WHILE next<>NIL DO

BEGIN

write(next^.data:6:1);

next:=next^.link

END;

writeln

END.

2 在链表中插入结点

在一个已建好的链表中插入一个结点,这是一种常见算法。当我们找到插入点后,就断开原先的链接,将新结点插入进来。

(图T10.3)

如图所求示:要把P3的结点插入到P2之前,应该这样操作:(1) P1,P2之间的链断开,改为P1指向P3。

P1↑.LINK:=P3;

(2)将P2,P3连接起来:

P3↑.LINK:=P2;

于是,P3所指向的结点便插入进来了。

例4 插入一结点的过程

PROCEDURE insert(x:real;VAR head:point);

{插入一结点的过程}

VAR

q,last,next:point;

BEGIN

{建立新结点}

new(q);

q^.data:=x;

IF X<=head^.ata

THEN {插入前表}

BEGIN

q^.link:=head;

head:=q;

EDN

ELSE BEGIN {找出表中合适的位置}

Next:=head;

WHILE (x>next^.data) AND (next^.link<>NIL) DO

BEGIN

Last:=next;

Next:=next^.link

END;

IF x<=next^.data

THEN {插入中间表}

BEGIN

last^.link:=q;

q^.link:=next

END

ELSE {插入表尾}

BEGIN

next^.link:=q;

q^.link:=NIL

END

END

END;

例5 建立一个有序的整数链表,再将一任意整数插入进链表,使链表仍然有序。

PROGRAM e1(input,output);

TYPE point=^pp;

pp=record

data:integer;

link:point;

end;

VAR

p1,p2,p3,k:point;

BEGIN

{建立一个整数的链表,要求输入的整数依次是有序的,以数9999结束}

new(p1);

writeln('input data');

readln(p1^.data);

k:=p1;

repeat

new(p2);

writeln('input data');

readln(p2^.data);

p1^.link:=p2;

p1:=p2;

until p2^.data=9999;

p2^.link:=nil;{有序链表建立完毕}

writeln('input p3');

readln(p3^.data);

p1:=k;p2:=k;{P1,P2都指向表头}

{P2找到插入点后一个结点}

while p2^.data

p2:=p2^.link;

{P1找到插入点以前的结点}

while p1^.link<>p2 do

p1:=p1^.link;

{将P3接入P1,P2之间}

p1^.link:=p3;

p3^.link:=p2;

{将整个插入后的链表依次打印出来}

repeat

write(k^.data,'->');

k:=k^.link;

until k^.data=9999;

write(k^.data);

END.

3 删除一个结点

要在一个链表中删去一个结点,首先在链表中找到该结点,将其前面的指针与该点断开,直接接到后面的结点,再用DISPOSE 命令将P3结点空间释放。如图,删除P3结点:

(图T10.4)

删除语句如下:

P1↑.LINK:=P3↑.LINK

DISPOSE(P3);

例6 删除结点的过程

PROCEDURE delete(x:real;VAR head;point;VAR deleted:Boolean); {删除结点的过程}

VAR

Last,next:point;

BEGIN

{遍历表直到找到目标或到达表末}

next:=head;

WHILE(next^.data<>x)AND(next^.link<>DIL) DO

BEGIN

Last:=next;

Next:next^.link

END;

{如果目标文件找到,删除包含它的结点,设置deleted}

IF next^.data=x

THEN BEGIN

Deleted:=true;

IF next=head

THEN head:=head^.link

ELSE last^.link:=next^.link

END

ELSE deleted:=false

END;

例7 在一个有序链表中装有1到100共100个整数。要求任意输入100以内的一个整数,把它从链表中删除。

PROGRAM e1(input,output);

TYPE point=^pp;

pp=record

data:integer;

link:point;

end;

VAR

p1,p2,p3,k:point;

i:integer;

BEGIN

{建立一个1――100的整数的有序链表}

new(p1);

k:=p1;

p1^.data:=1;

for i:=2 to 100 do

begin

new(p2);

p2^.data:=i;

p1^.link:=p2;

p1:=p2;

end;

p2^.link:=nil;

{输入要删除的结点的DATA值}

new(p3);

writeln('input p3');

readln(p3^.data);

P1:=k;p2:=k;

{P2指针查找P3结点}

while p2^.data

p2:=p2^.link;

{P1指针定位于P3之前}

while p1^.link<>p2 do

p1:=p1^.link;

p1^.link:=p2^.link;

dispose(p3);{将P3结点的空间释放} {输出修改后的链表}

repeat

write(k^.data,'->');

k:=k^.link;

until k^.data=100;

write(k^.data);

END.

C指针函数习题

C++指针函数习题 一、选择题 1.以下程序的运行结果是()。 sub(int x, int y, int *z) { *z=y-x; } void main() { int a,b; sub(10,5,&a); sub(7,a,&b); cout< #include<>

指向指针的指针——彻底搞定C指针

彻底搞定C指针---指向指针的指针 彻底搞定C指针---指向指针的指针一.回顾指针概念: 今天我们又要学习一个叫做指向另一指针地址的指针。让我们先回顾一下指针的概念吧! 当我们程序如下申明变量: short int i; char a; short int * pi; 程序会在内存某地址空间上为各变量开辟空间,如下图所示。 内存地址→6 7 8 9 10 11 12 13 14 15 ------------------------------------------------------------------------------------- … | | | | | | | | | | ------------------------------------------------------------------------------------- |short int i |char a| |short int * pi| 图中所示中可看出: i 变量在内存地址5的位置,占两个字节。 a变量在内存地址7的位置,占一个字节。 pi变量在内存地址9的位置,占两个字节。(注:pi 是指针,我这里指针的宽度只有两个字节,32位系统是四个字节) 接下来如下赋值: i=50; pi=&i; 经过上在两句的赋值,变量的内存映象如下: 内存地址→6 7 8 9 10 11 12 13 14 15 -------------------------------------------------------------------------------------- … | 50 | | | 6 | | | | -------------------------------------------------------------------------------------- |short int i |char a| |short int * pi| 看到没有:短整型指针变量pi的值为6,它就是I变量的内存起始地址。所以,这时当我们对*pi进行读写操作时,其实就是对i变量的读写操作。如:*pi=5; //就是等价于I=5; 你可以回看本系列的第二篇,那里有更加详细的解说。 二.指针的地址与指向另一指针地址的指针 在上一节中,我们看到,指针变量本身与其它变量一样也是在某个内存地址中的,如pi的内存起始地址是10。同样的,我们也可能让某个指针指向这个

指针变量作为函数参数

用名作为其他变量名地别名. ; 等价于; ()声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名地一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元.故:对引用求地址,就是对目标变量求地址.与相等. ()不能建立数组地引用.因为数组是一个由若干个元素所组成地集合,所以无法建立一个数组地别名. 引用应用 、引用作为参数 引用地一个重要作用就是作为函数地参数.以前地语言中函数参数传递是值传递,如果有大块数据作为参数传递地时候,采用地方案往往是指针,因为这样可以避免将整块数据全部压栈,可以提高程序地效率.但是现在(中)又增加了一种同样有效率地选择(在某些特殊情况下又是必须地选择),就是引用. 【例】: ( , ) 此处函数地形参, 都是引用 { ; ; ; ; } 为在程序中调用该函数,则相应地主调函数地调用点处,直接以变量作为实参进行调用即可,而不需要实参变量有任何地特殊要求.如:对应上面定义地函数,相应地主调函数可写为: ( ) { ; >>>>; 输入两变量地值 (); 直接以变量和作为实参调用函数 <<<< ' ' <<; 输出结果 }

上述程序运行时,如果输入数据并回车后,则输出结果为. 由【例】可看出: ()传递引用给函数与传递指针地效果是一样地.这时,被调函数地形参就成为原来主调函数中地实参变量或对象地一个别名来使用,所以在被调函数中对形参变量地操作就是对其相应地目标对象(在主调函数中)地操作. ()使用引用传递函数地参数,在内存中并没有产生实参地副本,它是直接对实参操作;而使用一般变量传递函数地参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量地副本;如果传递地是对象,还将调用拷贝构造函数.因此,当参数传递地数据较大时,用引用比用一般变量传递参数地效率和所占空间都好. ()使用指针作为函数地参数虽然也能达到与使用引用地效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"地形式进行运算,这很容易产生错误且程序地阅读性较差;另一方面,在主调函数地调用点处,必须用变量地地址作为实参.而引用更容易使用,更清晰. 如果既要利用引用提高程序地效率,又要保护传递给函数地数据不在函数中被改变,就应使用常引用. 、常引用 常引用声明方式:类型标识符引用名目标变量名; 用这种方式声明地引用,不能通过引用对目标变量地值进行修改,从而使引用地目标成为,达到了引用地安全性. 【例】: ; ; ; 错误 ; 正确 这不光是让代码更健壮,也有些其它方面地需要. 【例】:假设有如下函数声明:

指针练习题

. 编程题 1用指向数组的指针变量输出数组的全部元素 2 使用函数调用,形参为指针,实参为数组,把一个数组逆序存放在输出 练习题: 一判断题 1.指针是变量,它具有的值是某个变量或对象的地址值,它还具有一个地址值,这两个地址值是相等的。 2.指针的类型是它所指向的变量或对象的类型。 3.定义指针时不可以赋初值。 4.指针可以赋值,给指针赋值时一定要类型相同,级别一致。5.指针可以加上或减去一个int型数,也可以加上一个指针。6.两个指针在任何情况下相减都是有意义的。 7.数组元素可以用下标表示,也可以用指针表示。 8.指向数组元素的指针只可指向数组的首元素。 9.字符指针是指向字符串的指针,可以用字符串常量给字符指针赋值。 10.引用是一种变量,它也有值和地址值。 11.引用是某个变量的别名,引用是被绑定在被引用的变量上。

12.创建引用时要用一个同类型的变量进行初始化。 13.指针是变量,它可以有引用,而引用不能有引用。 ;. . 二单选题 1.下列关于定义一个指向double型变量的指针,正确的是()。A.int a(5);double *pd=a; B.double d(2.5),*pd=&d;C.double d(2.5),*pd=d; D.double a(2.5),pd=d;。).下列关于创建一个int型变量的引用,正确的是(2A.int a(3),&ra=a; B int . a(3),&ra=&a;ra=a;D.int a(3), C.double d(3.1);int &rd=d;.下列关于指针概念的描述中,错误的是()。3 A.指针中存放的 是某变量或对象的地址值.指针的类型是它所存放的数值的类型 B .指针是变量,它也具有一个内存地址值 C .指针的值是可以改 变的D 。.下列关于引用概念的描述中,错误的是()4 A.引 用是变量,它具有值和地址值 B.引用不可以作数组元素 C.引用是变量的别名 D.创建引用时必须进行初始化。++*p相同的是()*p=a5.已知:int a[5],;则与a[0] . B.*++p A++a[0] .C*p++ D.;. . 6.已知:int a[ ]={1,2,3,4,5},*p=a;在下列数组元素地址的表

指针练习题

编程题 1用指向数组的指针变量输出数组的全部元素 2 使用函数调用,形参为指针,实参为数组,把一个数组逆序存放在输出 练习题: 一判断题 1.指针是变量,它具有的值是某个变量或对象的地址值,它还具有一个地址值,这两个地址值是相等的。 2.指针的类型是它所指向的变量或对象的类型。 3.定义指针时不可以赋初值。 4.指针可以赋值,给指针赋值时一定要类型相同,级别一致。 5.指针可以加上或减去一个int型数,也可以加上一个指针。 6.两个指针在任何情况下相减都是有意义的。 7.数组元素可以用下标表示,也可以用指针表示。 8.指向数组元素的指针只可指向数组的首元素。 9.字符指针是指向字符串的指针,可以用字符串常量给字符指针赋值。 10.引用是一种变量,它也有值和地址值。 11.引用是某个变量的别名,引用是被绑定在被引用的变量上。 12.创建引用时要用一个同类型的变量进行初始化。 13.指针是变量,它可以有引用,而引用不能有引用。

二单选题 1.下列关于定义一个指向double型变量的指针,正确的是()。 A.int a(5);double *pd=a;B.double d(2.5),*pd=&d;C.double d(2.5),*pd=d;D.double a(2.5),pd=d; 2.下列关于创建一个int型变量的引用,正确的是()。 A.int a(3),&ra=a;B.int a(3),&ra=&a; C.double d(3.1);int &rd=d;D.int a(3),ra=a; 3.下列关于指针概念的描述中,错误的是()。 A.指针中存放的是某变量或对象的地址值 B.指针的类型是它所存放的数值的类型 C.指针是变量,它也具有一个内存地址值 D.指针的值是可以改变的 4.下列关于引用概念的描述中,错误的是()。 A.引用是变量,它具有值和地址值 B.引用不可以作数组元素 C.引用是变量的别名 D.创建引用时必须进行初始化 5.已知:int a[5],*p=a;则与++*p相同的是()。 A.*++p B.a[0] C.*p++ D.++a[0]

变量的指针和指针变量的区别是什么

2变量的指针和指针变量的区别是什么。 答;一个变量的地址指出了变量的存储单元在内存中的具体位置,能对变量进行存取操作。这个变量的地址就是变量的指针。指针是一种具有特殊意义的整型数,指针不能存放在一般的整型变量中,必须存放在专门指针的变量中,这类变量就是指针变量。 3 一维数组元素的引用有哪些方式。 答;下标法、地址法、指针法 4 2维数组列地址有哪些计算方法。 答;1 根据数组元素所在的行计算出行地址,然后把行地址转换成行中首元素的地址,再根据数组元素所在的列计算数组元素的地址。 2 根据2维数组的数组元素在存储空间上按行连续存放的特点,每个数组元素的地址等于2维数组元素的首元素地址加上该数组元素相对于首元素位置的偏移量。 3把2维数组的每一行当作一个一维数组,用一维数组元素地址的计算方法计算相应的2维数组元素的地址。 第9章结构体与共用体 1 什么是链表。其中单向链表具有哪些特点。 答;链表是若干个同样类型的结构通过依次串接方式构成的一种动态数据结构。链表中的每一个结构体数据成为结点,链表可以分成单向链表和双向链表 单向链表的特点;1 链表中的结点数据可以改变的 2 结点占用的内存是动态分配内存和动态释放内存函数。 2 对单向链表的常用操作有哪些。 答;对单向链表的常用操作有建立、显示、插入,删除和查找。 3 什么是共用体。 答;共用体是一个集合体。它的各个成员的数据类型可以是不相同的,所有成员共享同一段存储空间,存储空间的大小取决存储单元最大的成员的数据类型。 4 指向结构体类型变量的指针变量引用形式有哪些。 答;有两种形式;【星号指针变量名】。成员名和指针变量名-大于号成员名。 第10章位运算及编译预处理 1 C提供的编译预处理功能有哪些。如何实现。 答;功能有三种;宏定义、文件包含和条件编译,分别用宏定义命令、文件包含命令、条件编译命令实现。 2 文件包含的基本功能是什么。 答;文件包含处理是一个源文件可以将另一个源文件的全部内容包含到本文件中来,作为本文件的一部分,这可以节省程序设计人员的重复劳动。 【3【在C语言中提供了几种什么样的位运算符。 答;-、小于小于、大于大于、 4 文件包含需要注意哪些问题 答;一个井include命令只能指定一个被包含文件,包含多个文件侧需多个井include命令;文件包含可以嵌套,即一个被包含文件中可以包含另一个被包含的文件;在井include命令中,文件名可以用双引号或尖括号括起来。 第11章文件 1 文件的结束标志有哪些。 答;每个文件都有一个结束标志。当文件的位置指针移到文件的结束标志处时,表示文件结束。如何测试文件是否结束,常有2种方法 1 ASCII码文件的结束标志用【-1】表示。

指向函数的指针

指向函数的指针 c/c++ 2010-11-20 13:17:02 阅读41 评论0 字号:大中小订阅首先看这个程序: #include using namespace std; void max(int a, int b) { cout<<"now call max("<b?a:b; cout<

我曾经写过一个命令行程序,有很多命令,于是构着了一个结构的数组,大概是这样 struct{ char *cmd_name; bool (*cmd_fun)(); }cmd_info_list[MAX_CMD_NUM]; 程序中得到一个用户输入的命令字符串后,就匹配这个数组,找到对应的处理函数。 以后每次添加一个命令,只需要加个函数,然后在这个数组中加一个记录就可以了,不需要修改太多的代码。 这可以算是一种用法吧。呵呵。 Windows 中,窗口的回调函数就用到了函数指针。 用VC向导 New Projects ----> Win32 Application ----> A typical "Hello World!" application 其中的WndProc 是WNDPROC 类型的函数typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM); WndProc 作为窗口的回调函数,用来填充WNDCLASSEX 结构。 WNDCLASSEX wcex; wcex.lpfnWndProc = (WNDPROC)WndProc; void ListTraverse(LinkList L,void (*visit)(int)) { Link p; p=L->next; while(p) { visit(p->data); p=p->next; } return OK; } void print(int c) { printf("%d",c); } ListTraverse(L,print); 这算是个例子吧??? #include #include #include double Add (double x, double y) { return x+y; } double Sub (double x, double y) { return x-y; } double Mul (double x, double y)

C语言——指向函数的指针

1函数类型(* 函数指针变量)();//指向函数的入口地址 一个函数是若干语句的集合,经编译后存储在函数代码存储区,并占有一片连续的存储空间,对函数指针只能用函数名赋值而无其他运算 1#include 2 3int max(int x ,int y); 4 5int main() 6{ 7int(* p)() ;//定义p是指向函数的指针变量 8int a , b , c ; 9 10p= max ;//将函数max的入口地址赋给指针变量p 11scanf("%d %d",&a ,&b) ; 12c= (* p)(a , b) ;//用指向函数的指针变量p调用函数 13printf("a = %d , b = %d , max = %d", a , b , c); 14 15return0; 16} 17 18int max(int x ,int y) 19{ 20int k ; 21k= (x> y)? x : y ; 22 23return k ; 24} 函数名作为实际参数: 1 #include 2 3int fun1(int a , int b) 4 { 5return a+b ; 6 } 7 8int fun2(int (*q)() , int x , int y) 9 { 10return (*q)(x , y) ; 11 } 12 13int main() 14 { 15int (*p)() , k ; 16 p = fun1 ;

17 k = fun2( p , 8 , 5 ) ; 18 19printf("k = %d \n" , k); //输出 13 20 21return0 ; 22 } 设置一个函数proc ,每次调用它会实现不同的功能,输入 a , b 两个数,第一次调用proc时,找出两者中最大者,第二次找出最小者,第三次调用求两数之差: 1 #include 2 3int max(int *x , int *y); 4int min(int *x , int *y); 5int a_b(int *x , int *y); 6int proc(int *x , int *y , int(*p)()); 7 8int main() 9 { 10int a , b ; 11 12printf("Enter a and b :"); 13scanf("%d %d" , &a , &b); 14 15printf("a = %d \t b = %d \n" , a , b); 16 17printf("max(%d,%d) = " , a , b); 18 proc(&a , &b , max); 19 20printf("min(%d,%d) = " , a , b); 21 proc(&a , &b , min); 22 23printf("%d - %d = " , a , b); 24 proc(&a , &b , a_b); 25 26return0 ; 27 } 28 29int max(int *x , int *y) 30 { 31int k ; 32 33 k = (*x > *y) ? *x : *y ; 34 35return k ; 36 } 37 38int min(int *x , int *y)

C语言程序设计 指针变量的定义

6.1.3指针变量的定义 前面提到的存放地址的变量是一种特殊的变量,它只能用来存放地址而不能用来存放其他类型(例如整型、实型、字符型等)的数据,需专门定义。“指针”表示指向关系,所谓指针就是地址。一个变量的指针就是这个变量的地址,存放地址的变量称为指针变量。例如:pa 是一个指针变量,pa 中存放的是整型变量a 的地址,也就是说pa 指向变量a。变量a 的地址就是变量a 的指针,一个指针变量的内容一定是另一个变量在内存中的地址。 定义形式为: 数据类型说明符 *标识符; 例如: int *p; 表示定义了一个指针变量p,它指向一个整型变量,即p 存放一个整型变量的地址。 说明: (1)“数据类型说明符”是指该指针变量所指向变量的类型;(2)“标识符”就是所定义的指针变量的名字; (3)定义一个指针变量必须用符号“*”,它表明其后的变量是指针变量,但不要认为“*p”是指针变量,指针变量是p 而不是*p; (4)指针可以指向任何类型的对象。 在定义了一个指针变量p 以后,系统为这个指针变量分配一个存储单元(一般为2个字节),用来存放地址。要使一个指针变量指向某个变量,必须将该变量的地址赋给该指针变量。 例如: int a,b;int *p1,*p2; p1=&a;p2=&b; 上述语句表示定义了两个整型变量a,b 和两个指针变量p1,p2,然后将a 的地址赋给p1,b 的地址赋给p2,这样p1指向变量a, p2指向变量b。 6.1.4指针变量的引用 定义了一个指针变量后,可以对该指针变量进行各种操作,操作时用到两个有关指针的运算符: (1)&:取地址运算符。(2)*:指向运算符。 例如:&a 为变量a 的地址,*p 为指针变量p 所指向的变量。【例6-1】定义指向整型变量的指针 /*程序名:6_1.c*/#include &a &b p1 a p2b 图6-3指针的指向

指向对象的指针变量

指向对象的指针变量 定义的一般形式: 类名*指针变量名; p-> (*p). 指向对象的成员变量的指针变量: 1.该指针变量可出现在成员函数中,通过获取该成员变量的地址,然后通过(*指针变量名)访问该成员变量 class aa { int a; public: aa() { a=0; } aa(int a) { this->a=a; } void get_a() { int *p; p=&a; cout<<*p<a=a; } void get_a() { int *p; p=&a; cout<<*p<

} }; int main() { aa b(3); b.get_a(); aa *p; p=new aa[2]; (p+1)->get_a(); p[1].get_a(); int *q; q=&b.a; return 0; } 指向成员函数的指针变量: 定义的一般形式: 函数类型名(类名::*指针变量名)(参数); 赋值的一般形式: 指针变量名=对象名.成员函数名 指针变量名=&类名.成员函数名或指针变量名=类名.成员函数名通过指针变量引用对象的成员函数 一般形式:(对象名.*指针变量名)(参数) this指针 #include using namespace std; class aa { int a; public: aa() { a=0; } aa(int a) { this->a=a; } void get_a() { cout<a<

指向函数的指针变量

1.一般定义形式: 返回值的数据类型(*指针变量名)(); for example: int function(int a, int b){...;} int (*pointer_of_function)(); pointer_of_function = function; //相关联的语句就是这么简单。 2.函数的调用可以通过函数名调用,也可以通过函数指针调用(即用指向函数的指针变量调用)。 3.(*p)() 表示定义一个指向函数的指针变量,它不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,它是专门用来存放函数的入口地址的。在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。在一个程序中,一个指针变量可以先后指向返回类型相同的不同的函数。 4.在给函数指针变量赋值时,只需给出函数名而不必给出参数,如:pointer_of_function = function ,因为是将函数入口地址赋给pointer_of_function, 而不牵涉到实参与形参结合的问题。不能写成pointer_of_function = function(a,b)。 5.用函数指针变量调用函数时,只需将(*P)代替函数名即可,在(*p)之后的括弧中根据需要写上实参。 6.对指向函数的指针变量,像p++ 等类似运算是没有意义的。 7.区别int (*p)() 与int *p():由于()的优先级高于*,它就成了声明一个函数了,这个函数的返回值是指向整形变量的指针。 1 定义和调用 程序在编译后,每个函数都有一个首地址(也就是函数第一条指令的地址),这个地址称为函数的指针。可以定义指向函数的指针变量,使用指针变量间接调用函数。下面通过一个简单的例子来说明: float max(float x,float y) { return x>y?x:y; } float min(float x,float y) { return x

函数指针和指针函数

在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。 1.函数指针定义 函数类型(*指针变量名)(形参列表); “函数类型”说明函数的返回类型,由于“()”的优先级高于“*”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。 例如: int (*f)(int x); double (*ptr)(double x); 在定义函数指针时请注意: 函数指针和它指向的函数的参数个数和类型都应该是—致的; 函数指针的类型和函数的返回值类型也必须是一致的。 2.函数指针的赋值 函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。 例如, int func(int x); /* 声明一个函数*/ int (*f) (int x); /* 声明一个函数指针*/ f=func; /* 将func函数的首地址赋给指针f */ 赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,

因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。

3.通过函数指针调用函数 函数指针是通过函数名及有关参数进行调用的。 与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则*p等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则*pf 就等价于它所指的变量f。同样地,*f是指向函数func(x)的指针,则*f 就代表它所指向的函数func。所以在执行了f=func;之后,(*f)和func代表同一函数。 由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步: 首先,要说明函数指针变量。 例如:int (*f)(int x); 其次,要对函数指针变量赋值。 例如:f=func; (func(x)必须先要有定义) 最后,要用(*指针变量)(参数表);调用函数。 例如:(*f)(x);(x必须先赋值) 【例】任意输入n个数,找出其中最大数,并且输出最大数值。 main() { int f(); int i,a,b; int (*p)(); /* 定义函数指针*/ scanf('%d',&a);

指针总结

让你不再害怕指针 前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍 一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一 个类型里会出现很多运算符,他们也像普通的表达式一样,有优先 级,其优先级和运算优先级一样,所以我总结了一下其原则: 从变量名处起,根据运算符优先级结合,一步一步分析. 下面让我们先从简单的类型开始慢慢分析吧: int p; //这是一个普通的整型变量 int *p; //首先从P处开始,先与*结合,所以说明P是一 //个指针,然后再与int结合,说明指针所指向 //的内容的类型为int型.所以P是一个返回整 //型数据的指针 int p[3]; //首先从P处开始,先与[]结合,说明P是一个数 //组,然后与int结合,说明数组里的元素是整 //型的,所以P是一个由整型数据组成的数组 int *p[3]; //首先从P处开始,先与[]结合,因为其优先级

//比*高,所以P是一个数组,然后再与*结合,说明 //数组里的元素是指针类型,然后再与int结合, //说明指针所指向的内容的类型是整型的,所以 //P是一个由返回整型数据的指针所组成的数组 int (*p)[3]; //首先从P处开始,先与*结合,说明P是一个指针 //然后再与[]结合(与"()"这步可以忽略,只是为 //了改变优先级),说明指针所指向的内容是一个 //数组,然后再与int结合,说明数组里的元素是 //整型的.所以P是一个指向由整型数据组成的数 //组的指针 int **p; //首先从P开始,先与*结合,说是P是一个指针,然 //后再与*结合,说明指针所指向的元素是指针,然 //后再与int结合,说明该指针所指向的元素是整 //型数据.由于二级指针以及更高级的指针极少用 //在复杂的类型中,所以后面更复杂的类型我们就 //不考虑多级指针了,最多只考虑一级指针. int p(int); //从P处起,先与()结合,说明P是一个函数,然后进入 //()里分析,说明该函数有一个整型变量的参数 //然后再与外面的int结合,说明函数的返回值是 //一个整型数据

指向函数的指针变量

指向函数的指针变量 函数的指针是指函数的入口地址,和数组名代表数组的首地址一样,函数名代表函数的入口地址。 若有一个指针变量,存放某一个函数的入口地址,我们可以通过指向这个函数的指针变量来调用函数。 1.定义指向函数的指针变量 形式如下: 类型标识符(*变量标识符)(); 类型标识符是指针变量所指向的函数类型,变量标识符是指向函数的指针变量名。 例如: int(*p)(); 定义了一个指向函数的指针变量p,它可以存放一类整型函数的入口地址,程序中把哪一个函数的入口地址赋给它,它就指向哪一个函数。 说明: (1)定义指向函数的指针变量,可以指向一类函数。 (2)定义指向函数的指针变量时,括号不能省略。 形式int*p()定义的是指针函数头,返回值是指向整型数据的指针值,而不是指向函数的指针变量。 (3)对指向函数的指针变量p,p+i、p++、p--等运算无意义。 2.让指针变量指向函数 定义了指向函数的指针变量,就可以在指针变量与特定函数之间建立关联,让指针变量指向特定函数。 建立关联的方法为: 指针变量一函数名; 说明: (1)指针变量只能指向定义时所指定的一类函数。 (2)一个指针变量可以先后指向多个不同的函数。

3.利用指针实现函数调用 指针变量一旦指向某函数,利用指针所指向的变量可以实现函数调用。一般形式: (* 指针变量)(实参表);

1、快速锁屏 现代人的电脑充满了各种商业机密与隐私,上班时间喝个茶水都害怕电脑被“偷窥”。电脑它自己也会保护自己哦,只要你离开之前按下快捷键:Windows+L,就能快速锁住电脑屏幕哦,妈妈再也不用担心我的机密泄露了 2、误删恢复 字打多了就容易手抖,尤其做文案的,有时候忙得眼花缭乱却一不小心把文字为误删了。只要你未清空回收站,就能按快捷键:Ctrl+Z,进行撤回恢复。

指向函数的指针

1 定义和调用 程序在编译后,每个函数都有一个首地址(也就是函数第一条指令的地址),这个地址称为函数的指针。可以定义指向函数的指针变量,使用指针变量间接调用函数。下面通过一个简单的例子来说明: float max(float x,float y) { return x>y?x:y; } float min(float x,float y) { return x

指针变量及基本使用

第十章指针变量及基本使用 [内容提要] 1.了解pascal 语言中静态存储、动态存储的概念以及它们在存储过程中的不同点; 2.掌握指针类型及指针变量的定义和使用方法; 3.掌握指针变量的基本操作; 4.掌握线性表、线性链表的基本概念以及线性链表建立方法; 5.掌握线性链表、循环链表、双向链表的基本操作; 6.能够应用线性链表解决一些综合实际问题; 7.为学习数据结构知识打下基础。 [重点难点] 1.重点:指针概念和基本操作 线性链表的基本概念和对线性链表的操作 能够用线性链表操作的算法思想解决实际问题。 2.难点:指针变量与静态变量的区别、使用方法 灵活运用线性链接表的思想解决实际问题,线性链表的存储与访问。 3.关键:理解指针变量的意义及基本操作,线性链表的概念及基本操作 [内容讲授] 一、静态存贮和动态存贮 1、静态存储:变量一经说明,计算机管理系统就在内存中分配相应的存贮单元,其中变量名是存贮单元的地址,而变量的值是存贮单元的内容,该存贮单元自始至终都被该变量所占用,直到程序结束。如果变量是局部变量,那么在它的作用域内,一经说明也占有一定的存贮单元,直到退出其作用域为止。这样的变量,在程序的执行过程中,不能随时使用随时分配存贮空间,也不能在程序执行的过程中,释放这些空间。也就是说,一旦给这些变量分配存贮空间,无论程序是否需要,它们都要占用一定的存贮空间,以便给用户存贮数据。我们称具有这样特点的存贮为静态存贮,它所对应的变量称为静态变量。如字符类型、数组类型、记录类型等,这类变量的特点是存贮方便,查找容易。 2、动态存贮:在程序执行过程中,通过向计算机申请存贮空间或释放存贮空间的命令,以达到动态管理计算机的存贮空间,保证存贮空间的充分利用。存贮空间可以随时申请、随时释放,这样的存贮方式称为动态存贮,其变量称为动态变量。指针变量即为动态变量。 二、指针类型与指针变量 1、指针类型定义 type 指针类型标识符=^基类型名; 其中基类型名是前面我们所学过的数据类型,但不能是文件类型。

指针函数与函数指针的区别

指针函数与函数指针的区别 1、int(*p)[4];------ptr为指向含4个元素的一维整形数组的指针变量(是指针) 2、int *p[4];-------定义指针数组p,它由4个指向整型数据的指针元素组成(是数组) 3、int(*)[4];--------实际上可以看作是一种数据类型。也就是第一个(int(*p)[4];)中定义的p的数据类型 其实你要看这种到底是什么,就是要看他最先和谁结合。比如1中p先与*结合,那就说明p本质是一个指针;而2中p先与后面的[4]结合,说明他本质是一个数组。 一、 在学习arm过程中发现这“指针函数”与“函数指针”容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1、指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针 类型标识符 *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。 表示: float *fun(); float *p; p = fun(a); 注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。 来讲详细一些吧!请看下面 指针函数: 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。 格式: 类型说明符* 函数名(参数) 当然了,由于返回的是一个地址,所以类型说明符一般都是int。 例如:int *GetDate(); int * aaa(int,int); 函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。 int * GetDate(int wk,int dy); main()

指向指针的指针变量

一个指针变量可以指向整型变量、实型变量、字符类型变量,当然也可以指向指针类型变量。当这种指针变量用于指向指针类型变量时,我们称之为指向指针的指针变量,这话可能会感到有些绕口,但你想到一个指针变量的地址就是指向该变量的指针时;这种双重指针的含义就容易理解了。下面用一些图来描述这种双重指针,见图6-13。 在图中,整型变量i的地址是&i,将其传递给指针变量p,则p指向i;实型变量j的地址是&j,将其传递给指针变量p,则p指向j;字符型变量ch的地址是&ch,将其传递给指针变量p,则p指向ch;整型变量x的地址是&x,将其传递给指针变量p2,则p2指向x,p2是指针变量,同 时,将p2的地址&p2传递给p1,则p1指向p2。这里的p1就是我们谈到的指向指针变量的指针变量,即指针的指针。 指向指针的指针变量定义如下: 类型标识符**指针变量名 例如:f l o a t**p t r; 其含义为定义一个指针变量ptr,它指向另一个指针变量(该指针变量又指向一个实型变量)。由于指针运算符“*”是自右至左结合,所以上述定义相当于: f l o a t*(*p t r); 下面看一下指向指针变量的指针变量怎样正确引用。 [例6-27]用指向指针的指针变量访问一维和二维数组。 #i n c l u d e #i n c l u d e m a i n()

{ i n t a[10],b[3][4],*p1,*p2,**p3,i,j;/是*p指3向指针的指针变量*/ f o r(i=0;i<10;i++) s c a n f("%d",&a[i]);/*一维数组的输入*/ f o r(i=0;i<3;i++) f o r(j=0;j<4;j++) s c a n f("%d",&b[i][j]);/*二维数组输入*/ f o r(p1=a,p3=&p1,i=0;i<10;i++) p r i n t f("M",*(*p3+i));/*用指向指针的指针变量输出一维数组*/ p r i n t f("\n"); f o r(p1=a;p1-a<10;p1++)/*用指向指针的指针变量输出一维数组*/ { p3=&p1; p r i n t f("M",**p3); } p r i n t f("\n"); f o r(i=0;i<3;i++)/*用指向指针的指针变量输出二维数组*/ { p2=b[i]; p3=&p2; f o r(j=0;j<4;j++) p r i n t f("M",*(*p3+j));

相关文档
相关文档 最新文档