c语言指针变量

2024-10-13

c语言指针变量(精选14篇)

1.c语言指针变量 篇一

一、数组的指针、指针数组以及指向指针的指针

考虑数组的指针的时候我们要同时考虑类型和维数这两个属性,换一句话,就是说一个数组排除在其中存储的数值,那么可以用类型和维数来位置表示他的种类。

A)一维数组

在c和c++中数组的指针就是数组的起始地址(也就第一个元素的地址),而且标准文档规定数组名代表数组的地址(这是地址数值层面的数组表示)。例如:

int a[10]; int *p;

p=&a[0]//和p=a是等价的:

因为a是数组名,所以他是该数组的地址,同时因为第一个元素为a[0],那么&a[0]也代表了该数组的地址。但是我们是不是就说一个数组名和该数组的第一个元素的&运算是一回事呢?在一维的时候当时是的,但是在高维的时候,我们要考虑到维数给数组带来的影响。

a[10]是一个数组,a是数组名,它是一个包含10个int类型的数组类型,不是一般的指针变量噢!(虽然标准文档规定在c++中从int[]到int*直接转换是可以的,在使用的时候似乎在函数的参数为指针的时候,我们将该数组名赋值没有任何异样),a代表数组的首地址,在数字层面和a[10]的地址一样。这样我们就可以使用指针变量以及a来操作这个数组了。

所以我们要注意以下问题:

(1) p[i]和a[i]都是代表该数组的第i+1个元素;

(2) p+i和a+i代表了第i+1个元素的地址,所以我们也可以使用 *(p+I)和*(a+I)来引用对象元素;

(3)p+1不是对于指针数量上加一,而是表示从当前的位置跳过当前指针指向类型长度的空间,对于win32的int为4byte;

B)多维数组

对于二维数组a[4][6];由于数组名代表数组的起始地址,所以a(第一层)和第一个元素a[0][0]地址的数字是相同的,但是意义却是不同的。对于该数组我们可以理解为:a的一维数组(第一层),它有四个元素a[0]、a[1]、a[2]、a[3](第二层),而每个元素又含有6个元素a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5](第三层),…到此我们终于访问到了每个元素了,这个过程我们经历了:a->a[0]->a[0][0];

整体来讲:a是一个4行5列的二维数组,a表示它指向的数组的首地址(第一个元素地址&a[0]),同时a[0]指向一行,它是这个行的名字(和该行的第一个元素的首地址相同(第一个元素为地址&a[0][0]))。所以从数字角度说:a、a[0]、&a[0][0]是相同的,但是他们所处的层次是不同的。

既然a代表二维数组,那么a+i就表示它的第i+1个元素*(a+i)的地址,而在二维数组中

*(a+i)又指向一个数组,*(a+i)+j表示这个数组的第j+1个元素的地址,所以要访问这个元素可以使用 *(*(a+i)+j)(也就是a[i][j])。

他们的示意图为(虚线代表不是实际存在的):

对照这个图,如下的一些说法都是正确的(对于a[4][6]):

a是一个数组类型,*a指向一个数组;

a+i指向一个数组;

a、*a和&a[0][0]数值相同;

a[i]+j和*(a+i)+j是同一个概念;

总结一下就是:我们对于二维指针a,他指向数组a[0,1,2,3],使用*,可以使他降级到第二层次,这样*a就指向了第一个真正的数组。对于其他的情况我们也可以采用相同的方式,对于其他维数和类型的数组我们可以采用相类似的思想,

说到指向数组的指针,我们还可以声明一个指针变量让它指向一个数组。例如:

int (*p)[5];

这时p就是一个指针,要指向一个含有5个int类型元素的数组,指向其他的就会出现问题。

这个时候我们可以使用上面的什么东西来初始化呢?

我们可以使用*a,*(a+1),a[2]等。

原因很简单:我们在一个二维的数组中,那么表达方式有上面的相互类似的意义呢?只有 *a,*(a+1),a[2]等,

C)指针数组

一个指针数组是指一个数组中的每个元素都是一个指针,例如:

int *p[10];//而不能是int (*p)[10]

或者

char *p[10];

此时p是一个指针(数值上和&p[0]一样);

在前面有int t[10];

int * pt=t;//使用pt指向t

那么这里我们用什么指向int *t[10]中的t呢?我们要使用一个指针的指针:

int **pt=t;

这是因为:在int *t[10]中,每个元素是指针,那么同时t又指向这个数组,数组上和&t[0]相同,也就是指向t[0],指向一个指针变量,可以说是一个指针的指针了,所以自然要用

int **pt;

D)指针的指针

一个指针变量内部可以存储一个值,这个值是另外一个对象的地址,所以我们说一个指针变量可以指向一个普通变量,同样这个指针变量也有一个地址,也就是说有一个东西可以指向这个指针变量,然后再通过这个指针变量指向这个对象。那么如何来指向这个指针变量呢?由于指针变量本身已经是一个指针了(右值),那么我们这里就不能用一般的指针了,需要在指针上体现出来这些特点,我们需要定义指针的指针(二重指针)。

int *p1=&i; int**p2=&p1;

综合以上的所有点,下面是我们常常看到一些匹配(也是经常出错的地方):

int a[3],b[2][3],c,*d[3]; void fun1(int *p); void fun2(int (*p)[3]); void fun3(int **p); void fun4(int p[3]); void fun5(int p[]); void fun6(int p[2][3]); void fun7(int (&p)[3]);

函数 不会产生编译时刻的可能值(但逻辑上不一定都对)

函数

不会产生编译时刻的可能值(但逻辑上不一定都对)

fun1

a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]

fun2

b,b+i,

fun3

d

fun4

a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]

fun5

a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]

fun6

b

2.c语言指针变量 篇二

1 内存分配

计算机中的内存都是编址的,就象家的地址一样。在程序编译或者运行的时候,每遇到一次声明语句(包括函数的传入参数的声明),编译系统就为已定义的变量分配相应的内存单元,也就是说,每个变量在内存会有固定的位置,变量的数据类型不同,它所占的内存单元数也不相同。若我们在程序有如下定义:

如果将变量的地址保存在内存的特定区域,用变量来存放这些地址,这样的变量就是指针变量,通过指针对所指向变量的访问,也就是一种对变量的“间接访问”。

设有:

现在我们访问变量a、b、x、y、m、ch1、ch2对应的内存单元时,不仅可以通过变量名(直接访问),也可以通过指向这些变量的指针(间接访问)。

二者的关系如图2所示。

此时访问a变量对应的内存空间有:a、*pa二种方式。

2 指针就是一个整数

指针,是一个无符号整数(unsigned int),它是一个以当前系统寻址范围为取值范围的整数。32位系统下寻址能力(地址空间)是4G-byte(0~2^32-1)二进制表示长度为32bit(也就是4B)int类型也正好如此取值。

例如:程序1

程序1得到的答案和程序2的答案一致。(不同机器可能需要调整一下pt的取值。)

3 C的按值传递

C中函数调用是按值传递的,传入参数在子函数中只是一个初值相等的副本,无法对传入参数作任何改动。但实际编程中,经常要改动传入参数的值。这一点我们可以用传入参数的地址而不是原参数本身,当对传入参数(地址)取(*)运算时,就可以直接在内存中修改,从而改动原想作为传入参数的参数值。

在调用函数语句inc(&a)执行时,a的地址传给了函数inc的形参(*val)并在函数体内执行了(*val)++;就等于改变了变量a的值。执行完inc函数后返回到main函数输出a的值为4,操作*val,即是在操作a了。

4 双重指针(指向指针的指针)

设有如下程序:

5 指针数组、数组指针和指向函数的指针

指针数组是一组有序的指针集合,它所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。

设有:int a,b,c;int*p[3]={&a,&b,&c};

上述语句定义了一个名称为p的指针数组,其中有三个元素p[0]、p[1]、p[2]分别指向三个整型变量a、b、c。此时可以通过*p[0]、*p[1]、*p[2]这三种方式来访问a、b、c。

数组指针是指向数组的指针。数组在计算机内存中占据一片连续的存储空间。数组名存放着这一连续空间的首地址(注意这是一个常数)。数组指针指向这一片连续空间的起始地址。

设有:

int a[10]{1,2,3,4,5,6,7,8,9,10},*p=a;/*p指向了起始地址*/

此时访问数组a中第三个元素有三种方法:a[2]、*(a+2)、*(p+2)

设有:

int b[3][3]={{1,2,3},{4,5,6},{7,8,9}},*p=&[0][0];/*此时p这是一个列指针*/

此时访问数组b中第一行的第2个元素有:a[0][1]、*(p+1)、*(*a+1)(注:a是一个行指针)三种方法。

指向函数的指针,从二进制角度考虑,数组名是该数组数据段首地址,函数名就是该代码段的首地址。

设有如下程序:

程序运行的结果与上面第4个问题完全相同。丰富了访问函数的方法。

6 结束语

指针可以指向任何类型的变量用,有效地表示出复杂的数据结构;指针可以指向函数;用于函数参数传递,达到更加灵活使用函数的目的,有了指针在编程时丰富了访问内存单元的手段和方法,使C语言程序的设计更加灵活、实用、高效。

参考文献

[1]陈强.C语言核心开发技术从入门到精通[M].北京:电子工业出版社,2009.

[2]匡松.C语言程序设计[M].北京:中国铁道出版社,2008.

[3]李俊杰.C语言复习指南与题解[M].北京:清华大学出版社,2003.

3.C语言中指针链表的学习探讨 篇三

关键词:动态;链表

中图分类号:TP311.12

C语言中存储数据的结构用的最普遍的是数组,包括简单类型的数组,指针数据和结构体数组等,但是他们在实际应用中,会因为实现定义过大的数组容量而造成内存的浪费,或者因为保守的预测分配而满足不了实际使用的要求,这时就需要另一种方法来解决这个问题,这就是动态数据结构和动态分配内存技术。链表就是这样一种最简单的动态数据结构。那么如何让学生能够很好的学习并掌握它,本人就近几年的教学过程中经过探讨,采用了图示法进行教学,效果很好。

1 基本概念的理解

1.1 指针的理解

(1)指针与简单变量。通过图1所示理解指针与简单变量的关系,当把变量i的地址存入指针变量p1后,就可以说这个指针指向了该变量。

如需要指向下一个元素,只需要指针往后移动即可!

1.2 结构体的理解

(1)结构体类型。结构体类型是一种专门组织和处理复杂关系的数据结构,是一种自定义类型。同一个数据对象由于应用不同定义的类型也有所不同。比如处理学生的信息,可以有很多种方式:

结构体中的成员名可增,可减,形成新的结构体类型。

(2)结构体变量与数组。以上是结构体类型的定义,变量定义方式有三种,这里不一一举例,可根据自己的个人习惯选择不同的定义方式。比如上面两个类型,分别定义简单变量,可这样定义:

struct student s1,s2; struct stu s3,s4;

如定义数组,结合前面所学数组的知识,可这样定义:

struct student s[10]; struct stu s1[20];

2 指针链表

掌握了前面指针和结构体的知识内容,对于指针链表的理解和掌握是非常重要的。

2.1 指针链表的定义

这里主要讲解单项链表结点的结构体类型的定义,对于初学者掌握了这种定义,对于以后学习更为复杂的链表知识的理解是很有帮助的。

单项链表结点的定义:

struct node

{

int data; //存放的数据,可以定义其他更为复杂的数据结构

struct node *next; //指向struct node类型数据,用此建立链表

};

2.2 指针链表的建立

定义好类型后,再定义变量,并将链表建立起来,形成整数数据按升序建立的数据链,下面通过函数create来实现链表的建立。

struct node *create()

{

struct node *head,*p,*q,num;

head=NULL;

scanf("%d",#);

while(num!=0)

{

p=(struct node *)malloc(sizeof(struct node ));

if(p==NULL)

{

printf("Allocation failure\n");

exit(0);

}

p->data=num;

p->next=NULL;

if(head==NULL)

head=p;

else

q->next=p;

q=p;

}

return head;

}

2.3 指针链表的插入

链表建立完成后,最常用的操作之一就是对链表的数据进行增加,也就是插入操作,具体程序通过insert函数实现。

struct node*insert(struct node*head,sturct node*r,int*x)

{

struct nod *p,*q;

if(head==NULL)

{

head=r;

r->next=NULL;

}

else

{

p=head;

while(*x>p->data&&p-;>next!=NULL)

{

q=p;

p=p->next;

}

if(*xdata)

{

if(p==head)

head=r;

else

q->next=r;

p->next=p;

}

else

if(p==NULL)

{

p->next=r;

r->next=NULL;

}

return head;

}

2.4 指针链表的删除

对于链表中数据的删除也是链表数据中操作的重点,具体实现过程通过函数deletenode实现。

struct node*deletenode(struct node*head,int*x)

{

struct nod*p,*q;

if(head==NULL)

{

printf("This is a empty list.");

return head;

}

p=head;

while(*x!=p->data&&p-;>next!=NULL)

{

q=p;

p=p->next;

}

if(*x==p->data)

{

if(p==head)

head=p->next;

else

q->next=p->next;

free(p);

}

else

printf("NOT FOUND");

return head;

}

3总结

单向结点链表的主要操作就是建立,插入和删除数据,而且是链表当中最简单的一种形式,只有理解和掌握单向结点链表的基本操作,才有可能处理更为复杂的数据对象,在课堂上通过以上三个函数的编写与引导,学生对于链表有了初步的认识,并起到了良好的效果。

参考文献

[1]杜友福.C语言程序设计[M].北京:科学出版社,2012.

[2]龚民,朱秀兰.C语言程序设计教学探讨[J].电脑知识与技术,2009.

作者简介:刘山根(1976.8-),男,籍贯:河南新乡,职务:广东省华侨职业技术学校教务科副科长。

4.C语言程序设计实验十指针 篇四

【实验1】

实验题目:

1、下列代码片段哪里有错误?

char var1,ptr1;

var1 = „x‟;

ptr1 = &var1;

2、设有如下定义:

Double var1, *ptr1, *ptr2;

Float* ptr3;

Int var2, *var4;

那么,var1, *ptr1, ptr2,*ptr2,ptr3,* ptr3,var2, var4,*var4个属于哪种数据类型?

3、下列代码片段在哪里有错误?

Char c = ‟ A ‟;

Char * p;

p = c;或*p=‟A‟;

4、下列代码片段的输出结果是什么?

charvar1 = „ S „;

charvar2 = „ X ‟;

char*ptr1, *ptr2;

ptr1 = &var1;

ptr2 = &var2;

*ptr2 = *ptr1;

printf(“%ct%cn”, *ptr1, var2);

【实验2】

实验题目:输入3个整数,按由小到大的顺序输出。

【实验3】

实验题目:输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。

实验要求:写3个函数:(1)输入10个数;(2)进行处理;(3)输出10个数。

【实验4】输入年和天数,输出对应的年、月、日。

例如:输入2000和61,输出2000-3-1。

5.c语言指针变量 篇五

B.-

C.=

D.== 2.when0<=i<10, for the following statements, which reference is wrong to reference array elements.int a[]={1,2,3,4,5,6,7,8,9,0}, *p, i;p=a;A.*(a+i)

B.a[p-a]

C.p+i

D.*(&a[i])3.when0<=i<10, for the following statements, which reference is wrong to reference the address of array elements.int a[]={1,2,3,4,5,6,7,8,9,0}, *p,i;

p=a;

A.&(a+1)

B.a++

C.&p

D.&p[i] 4.What is the result for the following program? #include main(){ int a[]={1,2,3,4,5,6},*p;

p=a;

*(p+3)+=2;printf(“%d,%dn”,*p,*(p+3));}

A.0,5

B.1,5

C.0,6

D.1,6 5.what is the result for the following program? #include main(){ int a[12]={1,2,3,4,5,6,7,8,9,10,11,12}, *p[4],i;for(i=0;i<4;i++)p[i]=&a[i*3];printf(“%dn”,p[3][2]);}

A.输出项不合法

B.6

C.8

D.12 6.For the following statements, what’s the value of(p1-p2)? int a[10], *p1, *p2;p1=a;p2=&a[5];

A.5

B.6

C.10

D.没有指针与指针的减法

7.for this function prototype: void adder(int *ptr,int b);if there are two integers: int op1=2;int op2=4;which statement of function call is right?

A:adder(*op1,op2);B:adder(op1,op2);C:adder(&op1,op2);D:adder(&op1,&op2);8.What does the following program outputs to screen_____ voidToSrn(int *);main(){ int a=8;int *ptr=&a;ToSrn(ptr);} voidToSrn(int *ptr){ printf(“%p”,&a);} A:compile error,can not be run B:8 C:16 D:address of a 9.Assuming int *p,a=4;p=&a;which of the following statements is all means address A:a,p+1 B:&a,*p C:&a,p D:*a,p 10.Assuming inta[10],*p;which one is right A:*p=&a[0];B:*p=a;C:p=a[0];D:p=&a[0];11.Assuming :int a[10],*p=a;which one is the address of a[9] A:a[0]+9 B:&(p+9)C:*(p+9)D:a+9 12.Assuming:

char s1[]=“Hello”,s2[10],*s3=“HelloWorld”,*s4;which one of the following statements is correct? A:strcpy(s1[0],“Morning”);B:s2=“Morning”;C:strcpy(s3,“Morning”);D:strcpy(s4,“Morning”);13.For the following statements,after execution the statement a=p+2;what’s the value of a[0]? float a[3]={1.2,45.6,-23.0};float *p=a;

A.1.2

B.45.6

C.-23.0

D.语句有错

14.What format specifiers(in order)should be used in the printf()statement in thefollowing program? Note that in the program the correct format specifiers have beenreplaced by Z.#include int main(void){ int x = 5;int *x_ptr = &x;printf(“%Z, %Z, %Z, %Zn”, x, *x_ptr, &x, x_ptr);}(a)%f, %p, %d, %p(b)%d, %d, %p, %p(c)%d, %p, %d, %p(d)%p, %d, %d, %p

二、Fill the blank.1.the result of printf(“%sd”,“abcd”);is __【1】___。2.A pointer is a special type of variable which stores the

【1】

of a memory location.3.assuming:int a[]={1,3,5,7,9,11},*p=a;and the value of *p is _【1】__.the value of *(a+5)is __【2】

4.For the following statement, int a[]={8,1,2,5,0,4,7,6,3,9};What’s the value of a[*(a+a[3])]?._____________

二、read the following programs.1.On a machine in which addresses are 4 bytes, what is printed by the following program: #include int main(void){ char fun[] = “Programming is fun.”;char favorite[] = “My favorite class is programming.”;char *x = fun;printf(“%dn”, sizeof(fun));printf(“%dn”, sizeof(favorite));printf(“%dn”, sizeof(x));}

2.What does the following program print? #include int main(void){ int data[] = {1, 2, 3, 4, 5, 6, 7};int *ptr = data;int i;printf(“ i *ptrn--------n”);for(i = 2;i >-4;i--){ printf(“%2d, %2dn”, i, *ptr);ptr+=i;} }

三、write the following program.1.Rewrite the following program such that the function has a return type of void andthe variable y gets its value using pointers.#include intdbl(intnum);int main(void){ int x = 13;x = dbl(x);printf(“x doubled is %dn”, x);} intdbl(intnum){ return 2*num;}

2.Write a program that has a function that when passed a string will print every fourthcharacter of the string.In main()you should create the string ”This is an examplestring.” and pass this to your function to be printed.3.Change the program below to print I love programming.You should do this byusing the values in lovetext to change hatetext.Hint: think about the relationshipbetween the index values of the letters in love and the index values for the word hate.This can be done without creating any new variables.#include int main(void){ int i;charhatetext[] = “I hate programming.”;charlovetext[] = “love”;/* Your code goes here.*/ printf(“%sn”, hatetext);}

4.Write a program that has a function that when passed a string will print every fourthcharacter of the string.In main()you should create the string ”This is an examplestring.” and pass this to your function to be printed./*Void printString(char *p);*/ Void printString(char *p){ Int i=0,len=0,length=strlen(p);While(*p!=NULL&&len

{ Printf(“%c”,*p);P+=4;Len+=4;} } main(){ Char str[]=”This is an examplestring.”;printString(str);} 5./* Write a program.In main(), declare an integer array,and initialize the array through keyboard.Create a multiply()function that when given the array and the number of array elements,in which can double the value of the array elements(that is a[i]*2).Also create another print()function for printing the array elements.Call the two functions in main function.Tip: when running the program, input n with 14.*/

#include

#define N 14

void multiply(int a[],int n);void print(int *p);

main(void){ int a[N],i;

for(i=0;i

{ printf(“n No.%d: ”,i+1);scanf(“%d”,&a[i]);

}

/*(1)call the multiply()function*/

/**********Program**********/ multiply(a,N);

/********** End **********/

/*(2)call the print()function*/

/**********Program**********/ Print(a);

/********** End **********/

}

void multiply(int a[],int n){ int I;

/*(3)double the value of the array elements*/

/**********Program**********/

/********** End ***********/

} void print(int *p){ int i;

printf(“nThe output values after multiply are:n”);

/*(4)output the value of the array elements*/

/**********Program**********/

/********** End **********/

}

1.Write a program that has a function that when passed a string will print every fourthcharacter of the string.In main()you should create the string ”This is an examplestring.” and pass this to your function to be printed./*Void printString(char *p);*/ Void printString(char *p){ Int i=0,len=0,length=strlen(p);While(*p!=NULL&&len

{ Printf(“%c”,*p);P+=4;Len+=4;} } main(){ Char str[]=”This is an examplestring.”;printString(str);} 2./* Write a program.In main(), declare an integer array,and the array

initialize through keyboard.Create a multiply()function that when given the array and the number of array elements, in which can double the value of the array elements(that is a[i]*2).Also create another print()function for printing the array elements.Call the two functions in main function.Tip: when running the program, input n with 14.*/

#include

#define N 14

void multiply(int a[],int n);void print(int *p);main(void){

for(i=0;i

{ printf(“n No.%d: ”,i+1);scanf(“%d”,&a[i]);int a[N],i;

}

/*(1)call the multiply()function*/

/**********Program**********/ multiply(a,N);

/********** End **********/

/*(2)call the print()function*/

/**********Program**********/ Print(a);

/********** End **********/

}

void multiply(int a[],int n){

int I;

/*(3)double the value of the array elements*/

/**********Program**********/

/********** End ***********/

} void print(int *p){

printf(“nThe output values after multiply are:n”);

int i;

/*(4)output the value of the array elements*/

/**********Program**********/

6.c语言指针变量 篇六

先看下面的代码,注意看代码中的注解!

#include

#include

usingnamespacestd;

voidprint_char(char* array[],intlen);//函数原形声明

voidmain(void)

{

//-----------------------------段1-----------------------------------------

char*a[]={“abc”,“cde”,“fgh”};//字符指针数组

char* *b=a;//定义一个指向指针的指针,并赋予指针数组首地址所指向的第一个字符串的地址也就是abc�字符串的首地址

cout<<*b<<“|”<<*(b+1)<<“|”<<*(b+2)

//-----------------------------段2-----------------------------------------

char* test[]={“abc”,“cde”,“fgh”};//注意这里是引号,表示是字符串,以后的地址每加1就是加4位(在32位系统上)

intnum=sizeof(test)/sizeof(char*);//计算字符串个数

print_char(test,num);

cin.get;

//-------------------------------------------------------------------------

}

voidprint_char(char* array[],intlen)//当调用的时候传递进来的不是数组,而是字符指针他每加1也就是加上sizeof(char*)的长度

{

for(inti=0;i{

cout<<*array++<}

}

下面我们来仔细说明一下字符指针数组和指向指针的指针,段1中的程序是下面的样子:

char*a[]={“abc”,“cde”,“fgh”};

char* *b=a;

cout<<*b<<“|”<<*(b+1)<<“|”<<*(b+2)<

char *a[]定义了一个指针数组,注意不是char[], char[]是不能同时初始化为三个字符的,定义以后的a[]其实内部有三个内存位置,分别存储了abc�,cde�,fgh�,三个字符串的起始地址,而这三个位置的内存地址却不是这三个字符串的起始地址,在这个例子中a[]是存储在栈空间内的,而三个字符串却是存储在静态内存空间内的const区域中的,接下去我们看到了char* *b=a;这里是定义了一个指向指针的指针,如果你写成char *b=a;那么是错误的,因为编译器会返回一个无法将char* *[3]转换给char *的错误,b=a的赋值,实际上是把a的首地址赋给了b,由于b是一个指向指针的指针,程序的输出cout<<*b<<“|”<<*(b+1)<<“|”<<*(b+2)<结果是>

abc

cde

fgh

可以看出每一次内存地址的+1操作事实上是一次加sizeof(char*)的操作,我们在32位的系统中sizeof(char*)的长度是4,所以每加1也就是+4,实际上是*a[]内部三个位置的+1,所以*(b+1)的结果自然就是cde了,我们这时候可能会问,为什么输出是cde而不是c一个呢?答案是这样的,在c++中,输出字符指针就是输出字符串,程序会自动在遇到�后停止.

我们最后分析一下段2中的代码,段2中我们调用了print_array()这个函数,这个函数中形式参数是char *array[]和代码中的char *test[]一样,同为字符指针,当你把参数传递过来的时候,事实上不是把数组内容传递过来,test的首地址传递了进来,由于array是指针,所以在内存中它在栈区,具有变量一样的性质,可以为左值,所以我们输出写成了,cout<<*array++<

到这里这两个非常重要的知识点我们都说完了,说归说,要想透彻理解希望读者多动手,多观察,熟能生巧!

420){this.width=420}“ alt=”“ />

内存结构示意图!

//程序作者:管宁

//站点:www.cndev-lab.com

7.C语言指针简化教学思考 篇七

关键词:C语言,数组,教学,指针

在C语言的教学中, “指针”这一部分内容一直是C语言的教学重点和难点, 直接影响学生对后续课程的学习和把握[1,2,3]。作为软件开发入门课程, 绝大多数时间是在讲条件、循环、数组、函数, 而指针内容却是省、国家计算机二级、程序员等考试的必考内容。为了在最短的时间内达到较好的教学效果。笔者从多年的教学经验认为C语言的指针教学应该注意以下几点:

一、输入函数scanf () 和数组中地址的应用

所有的书本上都有介绍scanf (格式控制字符串, 输入项列表) , 此函数的输入项列表要用“&”加变量名, 要将所输入的内容放入变量的地址中, 其中格式控制串中如果有普通字符也要输入普通字符, 且有很多输入后不能正确读取的情况, 初学者往往感到非常困惑难以理解。其实, 连续定义的多个变量在内存中也是占用连续的内存单元, 只是不同的数据类型所占的字节不同, 程序在运行过程中遇到第一个scanf () 函数时, 将要求用户从键盘上按要求输入内容, 所有输入的内容都将先放入缓冲区且你可以输入很多内容, 输入完成后再按scanf的格式控制字符串的格式来存入到变量的地址中, 一旦输入不合法, 则认为输入结束, 后面的变量将取不到值。如:scanf (“%d:%d”, &a, &b) ;若输入时你输入3, 4↙其中a的值为3, 输入格式串中本来要求你输入的是“:”而你输入的是“, ”, 明显不合法, 则scanf函数输入结束, 后面的变量b将取不到值。同时这也很好解释了若程序中有多个scanf函数时, 为了保证每次输入都有效, 则应该在输入函数前加一个清空缓存函数fflush (stdin) 。

数组名代表的是数组的首地址, 所以在scanf () 函数中以”%s”为格式串所对应输入项列表不需要加“&”。如:char str[20];

scanf (“%s”, str) ;/*将输入的内容存储到从数组首地址开始的地址中*/

printf (“%s”, str) ;/*从数组的首地址开始输出字符数组的内容*/。

这些内容都与计算机的实际存储有关 (即和地址有关) 。

二、指针

指针就是地址。其实前面我们在讲解输入输出函数和数组时, 我们就介绍了一些有关地址的应用。一听自己已经用过且有所接触了, 学生也就不会感到太畏惧了。再加上时间有限, 我们要言简意赅地说明指针的用法。

1. 指针的概念。

指针就是内存地址。这里首先要区分三个比较接近的概念:名称、地址和内容 (值) 。名称是给内存空间取的一个容易记忆的名字;内存中每个字节都有一个编号, 就是“地址”;在地址所对应的内存单元中存放的数值即为内容或值。

为了帮助读者理解三者之间的联系与区别, 我们不妨打个比方, 有一座教师办公楼, 各房间都有一个编号, 如101, 102, …, 201, 202, …。一旦各房间被分配给相应的职能部门后, 各房间就挂起了部门名称:如电子系、计算机系、环境工程系等, 假如电子系被分配在101房间, 我们要找到电子系的教师 (内容) , 可以去找电子系 (按名称找) , 也可以去找101房间 (按地址找) 。类似地, 对一个存储空间的访问既可以指出它的名称, 也可以指出它的地址。

在C语言中, 如果变量p中的内容是另一个变量i的地址, 则称变量p指向变量i, 或称p是指向变量i的指针变量, 形象地用图1所示的箭头表示。

由此可以得出结论:变量的指针即为变量的地址, 而存放其他变量地址的变量是指针变量。

指针变量是一种变量, 因而也具有变量的三个要素, 但它是一种特殊的变量, 其特殊性表现在它的类型取值上。具体而言: (1) 变量名:与一般的变量命名规则相同。 (2) 变量的值:是某个变量的内存地址。 (3) 变量的类型:主要是其指向的变量的类型。

2. 指针指向简单变量。

如:int a=100, *p;/*指针变量的定义*/

p=&a;/*指针变量的赋值*/

*p=200;/*指针变量的应用*/

printf (“%d”, a) ;则输出值为200。

在此我们要理解指针一旦定义且指向了一简单变量, 除定义和初始化时的*p, 其他的*p等价于它所指向的简单变量 (即这里的*p<=>a) , p (指针) 等价于简单变量的地址 (即这里的p<=>&a) 。上面的输出语句可以变为:printf (“%d”, *p) 。

3. 指针指向数组。

(1) 指针指向一维数组。

如:int a[5]={10, 20, 30, 40, 50}, *p=a;p++;

printf (“%d, %d, %d”, *p, * (p+2) , *p++) ;则输出结果为:30, 50, 20

以上是指针指向一维数组的基本应用, 首先我们要理解有关指针的运算。

&:取地址运算符[5]。

*:指针运算符 (间址访问运算符) , 取指针所指向的值, 若所指向二维数组则表示离取值进了一步。

++:算术运算符, 表示指针往下或右移一个单位 (其中这个单位和具体的数据类型有关, 如果是整型数一个单位就指2个字节, 实型指4个字节) 。

--:算术运算符, 表示指针往上或左移一个单位。

若定义了一个指针指向了一个一维数组, 则p<=>a的使用 (原来的a[i], 也可以用p[i]表示, *p<=>*a) , 即* (p+i) <=>a[i]<=>p[i]<=>* (a+i) 。但要注意p和a同为地址它们是有区别的, p为变量地址, 而a是常量地址。有p++而不能用a++。

(2) 指针指向二维数组。对于指针指向二维数组, 要理解行地址和列地址的含义 (*运算符能实现行地址向列地址的转换) 再加上一维数组中的等价关系, 能理解下面的二维数组的指针表示形式表即可。

(3) 数组指针与指针数组的含义。前者是指针, 后者是数组。定义格式:仅差一对圆括号。 (1) 指向一维数组的指针。假设有定义语句:int (*p) [4]; (2) 指针数组。假设有定义语句:int*p[4];

(4) 应用场合:前者是一个指针, 后者是多个指针。 (1) 指向一维数组的指针。一般将一个二维数组名赋值给一个指向一维数组的指针, 来访问二维数组中的某一行。 (2) 指针数组。适合存放若干个字符串, 使字符串的处理更加方便灵活。例如:

用字符指针数组处理字符串不仅可以节省内存, 还可以提高运行效率。

4. 指针指向函数。

(1) 指针作为函数的参数。

其中左边交换完后, 能传递给实参, 因为它是指针所指向的值发生交换, 而右边只是指针的指向发生改变原本值未发生交换。

(2) 指针函数与函数指针。这是两个完全不同的概念, 前者是函数, 后者是指针。

a定义格式:仅差一对圆括号。

(1) 指针函数。假设有定义语句:

int*fp (int x, int y) ;

(2) 指向函数的指针 (函数指针) 。假设有定义语句:

int (*fp) (int x, int y) ;

b应用场合:前者是一个函数, 只是函数的返回值是指针;后者是一个指向函数的指针, 通过这个指针可以间接地调用所指向的函数。

三、总结

本文探讨了指针教学中, 通过截取最基本且最重要的知识来解析其应用问题, 目的在于使学生在较短的时间内掌握其基本知识, 预计可作为指针教学的有效方案之一。

参考文献

[1]管银枝.C语言程序设计实例教程[M].北京:人民邮电出版社, 2011.

[2]谭浩强.C程序设计 (第二版) [M].北京:清华大学出版社, 2001.

8.C指针与malloc,free 篇八

1、如何初始化一个指针

int *pbuff1; 和 int *pbuff2 = NULL;的区别是什么呢

首先,*pbuff1没有初始化指向NULL,也没指向合法的内存。所以*pbuuf1是个野指针。它会胡乱指向一个地址,这是很危险的。当你对野指针进行写操作的时候,没人会知道结果怎样,可能会修改掉程序中其它值。

*pbuff2初始化为NULL指针,表示*pbuff2不指向任何内容,将指针悬空。指针就不会乱指一气了。

2、如何使用一个指针

建议使用前给指针分配空间。一般使用指针的时候就知道需要多大的空间了。

这就用到malloc:

void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)

pBuff = malloc(lenAll*sizeof(char));

if(pBuff!=NULL)

{

memcpy(pBuff,buff,8*sizeof(char));

}

这里是先分配一个空间,然后把内存地址指向了pBuff,如果分配成功了,就把接收到buff里的值存放到pBuff指针,

同样初始化unsigned char *pBuff = NULL;

3、如何防止内存泄漏

malloc对应着free:

void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。

注意free到底释放了什么:

free释放的是指针指向的内存。指针变量依然存在,只有程序结束时才被销毁。不过现在指针指向的内容是未定义的垃圾,所以现在指针又成为了野指针。

因此,释放内存后把指针指向NULL,悬空。防止指针在后面不小心又被解引用了。

同时,确认不用这块内存了在free,不要free完了接着使用。

4、补充:

malloc和free是一一对应的,如果你只malloc一次,相应的就要free一次,重复释放是错误的。

malloc()函数的工作机制:

9.c语言指针变量 篇九

结构化程序设计的优点是便于分工合作,便于调试、维护和扩充。这种程序设计方法是将一个大程序分成若千个模块,每个模块完成一个功能,由一个总控模块来控制和协调各个模块来实现总的功能;因此,这种程序设计方法又称为模块化程序设计方法。在C语言中,函数是构成C谙言程序的最小模块。实际上,C语言的程序是由一个或者多个文件组成的,每个文件叉是由一个或多个函数组成的。因此,一个程序是由一个或多个函数组成的,其中,须有且仅有一个主函数,生函数的名字规定为rnaino这样,组成一个程序的者干个文件中,仅有一个是主文件,只有主艾件中才含有main()函数。另外,函数是由若干条语句组成的,语句是由若干个单词组成的‘单词是由若干个字符组成的。字符是构成程序的最小单元。e语言程序的构成如下所示:

程序~文件~函数~语句~单词、字符。

C语言是结构化程序设计语言,它具有构成三种基本结构模式的语句,这种结构化程序设计应具有的三种基本结构模式如下:

顺序结构棋式

它将由若干条顺序执行的语句构成,这是程序设计的最基本形式。

分支结构模式

C语言中具有条件语句和开关语句,它将会构成各种需要的分支结构模式。

循环结构模式

C语言中提供了三种循环语句(for循环,whil。循环和do-while循环),用它们可以构成

各种循环结构模式

在讲述C语言是一种结构化程序设计语言的同时,还必须指出它与其他结构化程序设计语言(如PASCAL语言)相比较,还有一些不完全之处,因此,C语言是一种不完全的结构化程序设计语言。其表现如下:

第一,完全的结构化程序设计语言不允许使用goto语句,因为goto语句会破坏结构化。

但是。got。语句在某些时候会使得程序简练,因此,在C语言中原则上允许使用goto语句,为了减少它对结构化的影响,采取了限制使用的办法,即规定got。语句的转向范围只能在一个函数体内。不得使用gates语句从一个函数体内转向到另一个函数体中,这种限制性地使用goto语句会给编程带来一些方便,又不会影响棋块之间的结构化。但是,建议在G语言的程序中尽量少使用goto语句。

第二,完全的结构化程序设计语言要求一个模块只有一个入口和一个出口,这样便于结构化的管理。但是,C语言程序中允许函数使用多个返回语句(return语句),即允许函数有多个出口,返回到调用函数。这样做也是为了编程中的方便。在C语言程序中,可以使用条件语句来返回不同的函数值。

由此可见,C语言虽然是一个不够严格的结构化程序设计语言,但它是一个使用起来十分灵活的高级语言。

1.计算机二级C语言程序设计考点解析:C语言程序实例

2.计算机二级C语言程序设计考点:指针

3.计算机二级C语言程序设计考点:函数

4.计算机二级C语言程序设计考点:数组

5.计算机二级C语言考点:字符型数据

6.计算机二级c语言试题

7.计算机二级C语言程序设计考点解析:常用的输人函数

8.计算机二级C语言程序设计考点解析:常用的输出函数

9.计算机二级C语言程序设计考点:单词及词法规则

10.C语言指针教学方法探讨 篇十

1 指针的概念理解

理解指针变量和普通变量的区别, 如:int a=1, b=2, *p=&a, *q;q=&b;前一条语句含义是定义变量a、b和指针变量p、q, 同时将变量a的值赋值为1和变量b的值赋值为2, 再将变量a的地址赋值给指针变量p;后面一条语句是将变量b的地址赋值给指针变量p, 这样就可以通过指针变量p和q间接访问变量a和b。如果通过这样枯燥的语言来表述, 对于一部分同学理解起来就有一定的难度。但是可以通过图示的方法来阐述。

如图1所示, 采用图示方法展示出普通变量a、b和指针变量p、q之间的关系, 指针其实是内存地址, 而内存中的单元是按字节编址 (每个地址编码对应一个字节空间) , 从图中也可以看出整型变量a和b分别占用二个字节的内存空间。同时也能看出每个指针变量也是占用二个字节的空间, 因为每个指针变量都是存储一个地址码。

2 指针的应用

在实际教学过程中, 特别是在实验教学过程中经常发现学生在指针的运用上很容易出现错误, 特别是在和数组的结合使用中。

2.1指针的初始化

指针的运用中必须先对指针初始化, 然后再使用。没有初始化的指针所指向的地址空间是一个不确定的内存空间, 对于一个不确定的内存空间进行操作, 会造成非法内存空间的访问, 甚至造成系统崩溃。

如例一中所示, 其中的指针变量p没有赋初始值, 在执行语句*p=i;时。因为指针p没有初始化, p所指向内存中的一个任意地址, 如果这个任意值恰好是一个空间的内存单元, 那么这个程序的执行就没有问题, 但是如果p所指向内存地址恰好是一个系统内存地址, 这样就会造成系统内存地址的非法访问而造成系统崩溃。

例1:

采用图示方法分析, 如图2中所示, 指针P没有一个确定的值, 它可能是其他任意的一个值。如果这个随机值恰好是3002, 那么在执行完语句*P=i:后。是将一个与例1程序无关的内存空间的值改变为i的值。

不同数据类型的变量, 占用的字节数不同, 系统把变量占据存储单元的第一个字节的地址作为该变量的地址。

a.间接访问运算

用变量名对其所对应的存储单元的内容进行读写称为直接访问, 而通过存储单元的地址对其内容进行读写的则称为间接访问。尽管指针变量中保存的是存储单元的地址, 而引入指针的目的主要是为了更方便快捷地访问存储单元的内容。间接访问是在引用的指针变量前面加一个“*”号, 用来表示指针所指向的存储单元的值或内容。

需要说明的是:在定义指针变量和在引用时“*”的含义是不同的。【int a=5, *p】中的“*”表示所定义的p是一个指针变量, 而在语句printf (“%d”, *p) 中的*p则是间接访问, 表示指针变量p所指向的存储单元的内容。由于指针的间接访问是访问存储单元的内容, 所以语句*p=&a在编译时也将出现警告错误。

b.指针变量加或减一个整型量, 从而得到另一个地址, 当然自增自减运算也是合法的。例如当指针变量p指向一个一维数组的首地址, 则p+n表示的是下标为n的元素地址。指针变量乘除一个整型量无意义, C语言也不允许此类语句出现。

c.由于指针变量中的地址也是一数值, 所以指针变量间也可以进行关系运算。

d.两个类型相同的指针变量可以相减, 例如指向同一数组的指针变量相减可以得到两个指针间元素的个数。相加或相乘则无意义。

由于++与*优先级相同, 且均为自右至左结合, 所以当用间接访问形式使得所指变量自加或自减时, 应使用括号。例如:指针变量p已指向变量a, 用间接访问形式使得变量a自加1, 应写为 (*p) ++, 即等价于a++, 但不能写成*p++, *p++是后面要介绍的一种指针运算, 所以必须要分开。

由于数组占据一块连续的存储单元, 且数组中的各元素的相对位置总是固定的, 所以对数组元素的引用除了使用下标外, 还可以使用指针运算来实现。

由于C语言中的一维数组名代表数组的首地址, 即数组的第一个元素所在存储单元的地址, 所以&a[0]与a是等价的, p=&a[0]也可写为p=a。

按照C语言的规定, 当指针变量p指向数组中的某一元素时, p+1则指向下一个元素, p+n指向后面第n个元素;同样, p-1指向前一个元素, 而p-n则指向前面第n个元素。当指针移动1, 系统内部移动的字节数, 取决于指针变量p的基类型。若为字符型则指针移动1个字节, 若为整型, 则指针移动两个字节, 依此类推。

当p指向数组a的首地址时, 表示数组元素a[i]有四种形式:a[i]* (a+i) * (p+i) p[i]。需要说明的是:指针变量与数组名相比, 可以进行自加自减或赋值运算。例如p++或p=p+n, 它们分别表示指针变量p指向下一个元素和指向后面第n个元素。而数组名一旦定义, 则所代表的地址是不能改变的。虽然* (a+i) 也能访问数组中每个元素, 但它是通过i的变化来实现的。

由于a[i]可以看作是一维数组名, 所以它代表该行的首地址, 因此, 二维数组a中的任一元素的地址既可以通过&a[i][j]求得, 也可以通过a[i]+j求得, 即&a[i][j]与a[i]+j等价。在一维数组的讨论中, a[i]与* (a+i) 等价。因此, 若将a[i]+j中的a[i]用* (a+i) 代换, 则二维数组元素的地址可用* (a+i) +j表示, 相应的数组元素表示为* (* (a+i) +j) 。

3 加强实验教学环节

实验教学也是课堂理论教学的重要辅助教学部分, 而C语言又是一门实践性比较强的课程。C语言中的指针运用非常灵活, 尤其是指针部分的内容对于多数同学难以掌握, 在实际编写程序的时候容易出现错误, 所以要进行实际的上机调试程序, 从中不断摸索和积累, 才能把指针内容掌握, 并加以灵活的应用。

结束语

C语言是一门计算机专业和相关专业的重要基础课程, 具有很强的灵活性。在进行C语言课程教学过程中, 针对整个课程的重点和难点的指针部分内容教学, 可以通过图示表示方法更加直观、形象的展示给学生, 方便于教师讲解, 另一方面通过上机实验教学加强理解和运用、使学生能够灵活掌握和运用指针进行编程。

摘要:C语言功能丰富、表达能力强、使用灵活方便、应用面广、目标程序效率高、移植性好, 既具有高级语言的优点, 又具有低级语言的许多特点。C语言指针部分的内容是教学的难点, 本文通过图示方法来阐述指针的概念、指针的应用和指针与数组之间的联系。

关键词:C语言,指针,数组,图示方法

参考文献

[1]康莉.零基础学C语言[M].北京:机械工业出版社, 2009, 4.

[2]谭浩强.C语言程序设计[M].北京:清华大学出版社, 2000.

[3]王柏盛.C语言程序设计[M].北京:高等教育出版社, 2004.

11.c语言感想 篇十一

在科技快速发展的今天,计算机在人们生活中的作用越来越突出,而C语言作为一种计算机的语言,我们学习它有助于我们更好地了解计算机。通过学习,我们可以了解到计算机是如何执行程序命令的。不仅如此,我们还可以根据自己的需要编写程序,来解决生活当中的实际问题。因此C语言的学习对于当代大学生来说尤为重要。

在这学期我们学完了《C语言程序设计教程》,并对它有了深入的了解。在这之前,我也对C语言有一个初步的了解,但仅仅是停留在了解层面,对它的实际运作方式和一些细节的东西还是很陌生。在学完之后,就对它有了更为深入的了解,比如C语言的发展历史,如何编写程序,编写程序时的注意事项和方法。C语言有它自己严格的语法规定,符号绝对要按要求使用,不能乱加、错加,但同时它也是很灵活泼的程序设计语言,同一种程序可以有不同的编写方法,但均可以保证最终的结果是一样的,我们要在学习中找到编写程序简单、快捷的方法,尽量舍弃那些复杂的步骤,让我们编写的程序更加容易读。这体现了C语言的灵活性,同一个结果可以有不同的途径到达。但在学习过程中还是遇到了不少困难,有时一个小小的错误就导致整个程序不能运行,需要花大量时间找出错误并修改。可能是因为初次接触C语言这门课程,有时还是会跟不上老师讲课的步伐,好在老师仍然耐心的给我们讲解,无论是什么问题都耐心回答,渐渐的我们知道了C语言的学习方法。

其次就是上机课,我们可以有大量的时间进行上机操作,上机是学习C语言必不可少的部分。一些简单快捷的程序设计方法需要上机进行检查其正确性。如果嫌上机时间短的话,还可以将上机的软件拷贝回去,这样在寝室也可以找时间练习。上机会遇到一些问题,有时一个程序会出现七八个错误,好在计算机可以自己找到错误的位置,并提醒我怎么改正,慢慢的,一个一个的错误被纠正过来,看到程序能运行时,心里就觉得很有成就感。也就越来越对它产生兴趣。我可以学着编一些程序来解决实际中的问题,上次物理实验有很多实验数据需要处理,老师就建议我们用C语言编写一个程序来处理那些数据。由此可以看出C语言的用处是非常大的。

12.c语言指针变量 篇十二

在C/C++程序中,对象(变量)存储在程序的内存空间中,并对应着惟一的地址。确切地讲,这个地址还跟对象(变量)的类型(auto,static,global,etc)有关。

同样,函数与对象(变量)相似,它也有自己惟一的地址与之对应。那么,就可以定义一个指针指向该地址(函数),这个指向函数的指针就叫做函数指针。与函数指针相似的一个术语是指针函数,表示其返回值是指针类型的函数。

2 定义

所有的C/C++中的对象(变量)必须经过定义才能够使用,函数指针也不例外。函数指针的定义与对象(变量)类似,略有不同。函数指针定义的一般形式为:

Return_Type(*Function_Fointer)(Argulist)。

示例(一):pointer to object pointer to function

注意函数指针定义中括号的使用保证了*和func_ptr的优先结合,否则func_ptr将变成一个返回值为指针的普通函数。函数指针中一个非常重要的问题是要保证函数指针的类型与它所指向的函数的一致性,比如示例一中func_ptr与f的返回类型和参数列表都是一致的,这样才不会报错。

函数指针的初始化和赋值有二种方式,第一种方式如示例一所示,对函数名使用取址运算符&。由于函数名本身就代表着入口地址,所以也可以直接把函数名赋给函数指针,那么示例一中可改为:int(*func_ptr)(int arg)=f。

示例(二)

运用typedef可以使函数指针的定义和使用更加方便和简洁。在示例二中,typedef的使用是程序更加明朗和可读。

示例(二)

typedef的功能是定义新的类型。示例二中第一句就是定义了一种PTRFUN的类型,并定义这种类型为指向某种函数的指针,这种函数以一个int为参数并返回char类型。后面就可以像使用int,char一样使用PTRFUN了。

3 使用

通过函数指针去调用函数有两种方法,包括隐性(explicit)和显性(implicit)调用。显性调用如示例三所示。隐性调用只需要将(*funcptr)(3,2)改为funcptr(3,2)即可。这两种方法完全是等同的,具体由个人爱好所决定。

4 应用

4.1 应用技巧

函数指针(function pointer)是一类特殊的指针,它在C/C++编程中有着广泛的应用。函数指针主要有两个方面的用途:调用函数和做函数的参数。利用函数指针作为参数和调用函数,就开创了许多程序设计中的可能和技巧,主要体现在以下3个方面:

(1)多态(polymorphism)。多态实现的机制十分复杂,其中虚函数表起着重要的作用。一般来讲,编译器会为数据结构加入一项成员,是一个指向虚函数表的指针(经常被称为vptr),而虚函数表中存放的是由函数指针组成的数组,函数指针指向实际所调用的函数。

(2)回调函数(call-back)。实现回调函数的关键是函数指针作为函数的参数。回调函数应用的非常广泛,例如Win32的Win Proc其实就是一种回调,用来处理窗口的信息。

(3)取代switch–case语句。switch-case语句在选择项数上和程序维护上有一定的限制,使用函数指针可以解决这一问题。

4.2 应用实例

4.2.1 消息映射雏形

Windows程序是以消息为基础的,其消息映射极其复杂,函数指针发挥着重要的作用。下面用一个简单的消息映射雏形来说明函数指针的使用方法和技巧。

定义一个MSGMAP结构和一个cou宏:

MSGMAP结构中第二个元素pfn是一个函数指针,以此指针所指的函数处理n Message消息。

设计一个数组_message Eneries[]把程序中预处理的消息以及消息处理函数的关联性建立起来。

可以看出,Wnd Proc函数永远不必改变,每当有新的要处理的消息时,只需在_message Entries[]数组中加入新的元素即可。而函数指针在整个消息映射中扮演十分关键的角色。

4.2.2 回调函数

回调函数是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来用它所指向的函数时,就说这是回调函数。回调函数使用的场合很多,下面就通过一个简单回调函数实例来阐述函数指针在回调函数中的应用。

假设Barrel Volume是库函数中用来计算柱体体积的一个函数,定义如下:

由于不同类型柱体底面积的计算方法不一样,用户可以根据需要编写自己的面积计算函数,通过函数指针传递进去,增加了程序的维护性和简洁性。

如果用户计算圆柱的体积,可以这样编写:

其中Area0(),Area1()为回调函数。

5 结语

函数指针由于定义复杂,抽象难懂,使用技巧性强,是C/C++程序设计学习中的难点。,在程序设计的过程中,要认真思考,巧妙应用,克服函数指针的致命缺点(函数指针无法对参数和返回值的类型进行检查),利用函数指针设计出优秀的程序代码

参考文献

[1]汪明光.C++语言中函数指针的分析与应用.巢湖学院学报,2006,(3):30-33.

[2]李永祥,陈意云.基于函数指针数组的代码迷惑技术.计算机学报,2004,(12):1707-1708.

[3]侯俊杰.深入浅出MFC.武汉:华中科技大学出版社,2001.

13.c语言教案 篇十三

一、教学目标:要求学生对C语言及C语言程序有一概括的的了解,并掌握C语言环境的功能及使用方法,为以后熟练地使用它进行上机练习做准备。

二、教学重点:掌握简单C语言程序的结构,及C语言的上机步骤。

三、教学难点:C语言编程环境的熟悉。

四、课程:讲授新课。

五、学时:两学时。

六、教学过程:

第一节 C语言概述

一、C语言简史

二、C语言的特点(优点、缺点)

(1)语言简洁紧凑,使用方便、灵活。(2)运算符丰富。(3)数据结构丰富。

(4)具有结构化的控制语句。

(5)语法限制不太严格,程序设计自由度大。

(6)C语言能进行位操作,可以直接对硬件进行操作。(7)生成目标代码质量高,程序执行效率高。

第二节 C语言程序

举例如下所示: main(){ int a,b,c;scanf(“%d,%dn”,&a,&b);c=max(a,b);printf(“max=%dn”,c);} int max(int x,int y){ int z;if(x>y)z=x;else z=y;return(z);}

一、源程序的书写格式

(1)C程序是由函数构成的。一个C源程序至少仅包含一个main函数,也可包含一个main函数和若干其他函数。

(2)函数名后必须有一对圆括号“(”和“)”,这是函数的标志。(3)函数必须由左大括号“{”和“}”结束。(4)程序中的每个语句必须有一个分号“;”。

(5)C程序书写格式自由,一行内可写多个语句,一个语句可以写在多行上。

(6)C语言本身没有输入输出语句。输入输出函数由库函数scanf和printf等函数来完成。

(7)可以用/*„*/对C程序中的任何部分作诠释。

举例:举出例子,由学生说出所举例子程序书写格式的错误。学时:两课时

二、函数的定义形式

C语言函数由两部分组成。

(1)函数的首部,即函数的第一行,包括函数名,函数类型,参数名,参数类型。(2)函数体:即大括号弧内{„}的部分。如果一函数有多个大括号弧,最外层的一对{ }号函数体的范围。

举出例子:int max(int x,int y)由学生说出函数的组成。{ }

第三节 上机操作

一、上机步骤安排如下:

1、打开Turboc2环境;

2、输入程序;

3、保存文件“Alt+F”选择,F2进行保存;

4、选择compile菜单下的“compile to OBJ”,然后再选择“compile/Link EXE file”,得到EXE文件。

5、执行程序,选择Run或“Alt+F9”按“Alt+F5”得到执行结果。

布置几个程序,由学生输入,运行,检查其结果。

七、小结:通过本章的学习,要求学生必掌握C语言的书写格式及其结构介绍,并能输入程序在Turboc环境下调试运行。

14.C指针原理GLIB 篇十四

GLib是一个跨平台的、用C语言编写的库,起初是GTK+的一部分,但到了GTK+第二版,开发者决定把跟图形界面无关的代码分开,这些代码于是就组装成了GLib,因为GLib具有跨平台特性,所以用它编写的程序可以无需进行大幅度修改就可以在其他程序上编译和运行。

glib库是Linux平台下最常用的C语言函数库,它具有很好的可移植性和实用性。

glib是Gtk +库和Gnome的基础。glib可以在多个平台下使用,比如Linux、Unix、Windows等。glib为许多标准的、常用的C语言结构提供了相应的替代物。

麦好的AI乐园博客所有内容是原创,如果请注明来源

blog.csdn.net/myhaspl/

如果在程序中要使用到glib库中的函数,则应该包含glib.h头文件(在gtk.h和gnome.h头文件中已经包含了glib.h了)

1、Freebsd中安装glib

cd /usr/ports/devel/glib20

portsnap fetch extract

Looking up portsnap.FreeBSD.org mirrors... 7 mirrors found.

Fetching snapshot tag from isc.portsnap.freebsd.org... done.

Fetching snapshot metadata... done.

Updating from Fri Dec 6 11:20:31 CST to Mon Dec 23 21:23:19 CST 2013.

Fetching 4 metadata patches... done.

Applying metadata patches... done.

Fetching 4 metadata files... gunzip: (stdin): unexpected end of file

metadata is corrupt.

root@dp:/usr/ports/devel/glib20 # ls

Makefile distinfo files pkg-descr pkg-plist

root@dp:/usr/ports/devel/glib20 # make install clean

===> License LGPL20 accepted by the user

===> Found saved configuration for glib-2.36.3

===> Fetching all distfiles required by glib-2.36.3 for building

===> Extracting for glib-2.36.3

=> SHA256 Checksum OK for gnome2/glib-2.36.3.tar.xz.

===> Patching for glib-2.36.3

===> glib-2.36.3 depends on package: libtool>=2.4 - found

===> Applying FreeBSD patches for glib-2.36.3

..........................

..........................

2、windows下配置与安装

3、测试:

Linux/unix下测试,以freebsd为例

首先看一下下面这个程序,在编辑器中输入下面程序,程序首先创建20个1-100以内的随机数,并显示在屏幕,然后计算30000000次累加,并输出计算用的时间,

#include

int main(int argc, char *argv[])

{

GRand *rand;

GTimer *timer;

gint n;

gint i, j;

gint x = 0;

rand = g_rand_new; //创建随机数对象

for(n=0; n<20; n++)

{ //产生随机数并显示出来

g_print(“%dt”,g_rand_int_range(rand,1,100));

}

g_print(“n”);

g_rand_free(rand); //释放随机数对象

//创建计时器

timer = g_timer_new();

g_timer_start(timer);//开始计时

for(i=0; i<10000; i++)

for(j=0; j<3000; j++)

x++;//累计

g_timer_stop(timer);//计时结束

//输出计时结果

g_print(“%ldtall:%.2f seconds was used!n”,x,g_timer_elapsed(timer,NULL));

}

编译

dp@dp:~/gliblearn % gcc `pkg-config --cflags --libs glib-2.0 gthread-2.0` a.c -o mytest

最后执行:

dp@dp:~/gliblearn % ./mytest

96 24 52 87 52 16 62 17 78 62 76 6 33 53 87 3 40 69 20 33

30000000 all:0.08 seconds was used!

上一篇:乡镇长近三年工作总结下一篇:考核纪律评语