电脑桌面
添加盘古文库-分享文档发现价值到电脑桌面
安装后可以在桌面快捷访问

C语言数据结构与指针

来源:文库作者:开心麻花2025-09-181

C语言数据结构与指针(精选12篇)

C语言数据结构与指针 第1篇

数据结构【第四次】实验报告

学院:

班级:

学号:

姓名:

实验四

(一)实验名称:C语言数据结构与指针

(二)实验目的:巩固复习前期所学C语言的函数参数传递、指针和结构体等知识点,加强学习数据结构语言基础。

(三)实验内容:

1)学生信息的显示,具体要求如下:

定义一个结构体描述学生信息(学号,姓名,性别,年龄,住址);

设计一个函数,用于显示单个学生信息,函数的参数为前面定义的结构体类型;

设计一个主函数,在主函数中输入学生的信息,并调用前面定义的函数进行显示(学生人数不少于5人)。

2)输入若干个整数作为数组元素值,然后按输入时顺序的就地逆置排序,最后打印出逆置后的元素值。要求用指针和动态内存分配方法实现。例如 输入:10 2 30 4 5,逆置后显示为:5 4 30 2 10。

(四)源代码:

#define MAXSIZE 100

#include #include typedef int ElemType;typedef struct {

ElemType data[MAXSIZE];int length;

} SqList;SqList l;

void InitList(SqList &L)

{

L.length = 0;} void CreatSqlist(SqList &L,int n)

{

printf(“请输入节点”);int i;for(i=0;i

} void Output(SqList &L)

{ int i;for(i=0;i

printf(“n”);} int chazhao(SqList &L,int x){ int i,k;printf(“n请输入你要查找的元素 x=?”);scanf(“%d”,&x);for(i=0;i<=(L.length+1);i++){

if(x==L.data[i])

{printf(“要查找的元素%d位于线性表第%d位上nn”,x,i+1);

k=0;

break;

} } if(k!=0)printf(“所要查找的元素%d不在线性表中”,x);return 0;} int GET(SqList &L,int i){ int m;if((i<0)||(i>L.length)){printf(“所查找范围超出线性表长度”);return 1;} else if((i>=1)(i<=L.length)){

m=L.data[i-1];}printf(“%d ”,m);return 0;} int DELETE(SqList &L,int i){ int j;if(i<1||i>L.length){printf(“删除错误”);return 0;} else {

for(j=i;j

L.data[j-1]=L.data[j];

L.length--;

} return 1;} int INSERT(SqList &L,int x,int i){ int j;if(L.length>=MAXSIZE-1){printf(“over flow”);return 1;} else if((i<1)||(i>L.length+1)){printf(“插入错误”);return 1;} else

{for(j=L.length;j>=i-1;j--)L.data[j+1]=L.data[j];L.data[i-1]=x;L.length=L.length+1;} return 0;} int main(){int n,i,k,x;InitList(l);printf(“请输入线性表的长度 ”);scanf(“%d”,&n);CreatSqlist(l,n);Output(l);

printf(“请输入你要查找的数所在的节点位置”);scanf(“%d”,&i);GET(l,i);chazhao(l,x);printf(“请输入你要删除元素的位置=?”);scanf(“%d”,&k);DELETE(l,k);Output(l);printf(“请输入你要插入的数和位置x,i=?”);scanf(“%d,%d”,&x,&i);INSERT(l,x,i);Output(l);return 0;}

(五)代码运行结果:

(六)需求分析

1、输入的形式和输出值的范围:1)输入10个整数。2)输出整个顺序线性表。

2、输出的形式:完成各种功能后的线性表。

3、程序所能达到的功能:1)所存储顺序线性表的显示、元素的查找、删除和插入。

(七)所用到的函数:

void CreatSqlist void Output Int chazhao int GET int INSERT int DELETE

(八)心得体会:

此次实验的过程中还是遇到了很多意想不到的问题,让我再一次深刻的体会到了理论和实践的差距。使我清楚的知道技术上的东西,细节更显得尤为重要和值得重视。困难虽有,但在我的努力下,最后还是成功完成了实验。总而言之,这次实验又增长了我不好知识。

C语言数据结构与指针 第2篇

在ANSI C标准中允许用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个传送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这时现金网96y.org由实参传向形参的只是地址,从而减少了时间和空间的开销。

计算一组学生的平均成绩和不及格人数。用结构指针变量作函数参数编程。

struct stu{

int num;

char *name;

char sex;

float score;

}boy[5]={

{101,Li ping,M,45},{102,Zhang ping,M,62.5},{103,He fang,F,92.5},{104,Cheng ling,F,87},{105,Wang ming,M,58}

};

main(){

struct stu *ps;

void ave(struct stu *ps);

ps=boy;

ave(ps);

}

void ave(struct stu *ps){

int c=0,i;

float ave,s=0;

for(i=0;i5;i++,ps++){

s+=ps-score;

if(ps-score60)c+=1;

}

printf(s=%fn,s);

ave=s/5;

printf(average=%fncount=%dn,ave,c);

}

本程序中定义了函数ave,其形参为结构指针变量ps。boy被定义为外部结构数组,因此在整个源程序中有效。在main函数中定义说明了结构指针变量ps,并把boy的首地址赋予它,使ps指向boy数组。然后博彩娱乐棋牌q07i5.org以ps作实参调用函数ave。在函数ave中完成计算平均成绩和统计不及格人数的工作并输出结果。

C语言指针在数据结构中的妙用 第3篇

多年来,C语言因其语言简洁紧凑、功能强大、使用方便灵活而受到广泛青睐。C语言作为一门高级语言,它又能直接对物理地址进行访问,兼有高级语言和低级语言的双重功能。C语言对物理地址进行访问的主要方式就是通过指针。指针是一种特殊的数据类型,指针变量存储目标变量的存储地址,通过指针变量可以直接访问对象存储空间。

指针既是C语言的特点,也是C语言的难点。用得好,可以简化、优化程序;用不好,不但程序出错,还可能影响整个系统的运行。下面从四个方面介绍C语言指针在数据结构中的巧妙使用。

1 通过指针带回在函数中改变了的数据

有些函数需要将在函数中改变了的数据带回主调函数,这时就必须通过指针实现这一功能。例如,删除顺序表中第i个数据元素的函数DelList()。

在函数DelList()中,指针L将主调函数中待处理的线性表带给DelList(),函数调用结束又将在函数中改变了的线性表带回主调函数。

2 通过指针克服一个函数只能带回一个值的限制

一个函数只一个返回值,可是,实际中常常碰到需要将两个或两个以上的值带回主调函数,解决这一问题的方法就是通过函数值带回一个值,使用指针作为参数带回其它值,从而克服这一限制,增强函数功能。例如,在上面的函数DelList()中,函数值表示删除成功与否,指针参数e将被删除的数据元素值带回主调函数。

3 通过使用指针变量作函数参数提高模块的时间性能和空间性能

下面的Locate1()函数是在顺序表中查找值等于e的元素并返回其序号,变量L所需的存储空间与原线性表所占空间大小相等,参数传递时所需时间与线性表的长度成正比。

若将此函数中的参数L改为指针变量,如Locate2()所示,则函数功能不变,而参数传递的时间复杂度和空间复杂度都由线性级降为常量级,与线性表的大小无关。

4 通过使用指针变量作函数参数提高模块的独立性

耦合性反映了模块之间的的相对独立性,耦合性越高,则模块的独立性就越弱。C语言中使用全局变量就会引起外部耦合,这种耦合严重影响模块的可靠性、适应性和可读性,是程序设计时应该尽量避免的。例如,统计二叉树中叶子结点数目的函数如下:

为了消除上面函数的外部耦合,将全局变量LeafCount改为指针类型的参数,如leaf2()所示,就可将外部耦合变为数据耦合,从而使程序界面简单、安全可靠、独立性强。

以上从四个方面介绍了在数据结构中巧妙地使用指针,从而增强函数功能、提高函数时间和空间性能、提高了函数的安全性、可靠性和独立性。

摘要:指针既是C语言的特点,也是C语言的重点和难点。用得好,可以简化、优化程序;用不好,不但程序出错,还可能影响整个计算机系统的运行。从四个方面提出了C语言指针在数据结构中的巧妙使用,从而增强模块功能、提高程序的时间和空间性能、提高了模块的安全性、可靠性和独立性。

关键词:指针,时间性能,空间性能,模块独立性

参考文献

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

[2]耿国华.数据结构——C语言描述[M].西安:西安电子科技大学出版社,2002.

[3]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:清华大学出版社,1997.

C语言数据结构与指针 第4篇

C语言数据结构与指针 第5篇

写一个函数,用于比较两个字符串的比较(string_compare).

程序分析:

(1)主要思想:传入两个字符串后,比较这两个字符串中的每个元素,如果第一次比较就不相等,就不要让它进入到下面的比较中,这样一来,将它返回一个相减的值(即:两数组中开始不相等的那两个元素相减,返回值(int类型),是ASCII码值相减)。进入比较的过程中时,相等就返回0;其他情况都返回那个相减的值。

(2)主要方式:定义指针数组,并对其初始化。然后照上面的思想,进行代码的实现。

代码如下:

深度理解C语言的指针与数组 第6篇

Section 1 左值与右值

编译器为每个变量分配一个地址(左值),该地址在编译时可知,且变量在运行时一直存于该地址。存于该地址的变量的值(右值)只有在运行时可知。因此,编译器如果需要一个地址来执行某种操作,它可以直接进行操作,如果需要一个变量的值,它需要发出指令从指定地址中读入变量值并存于寄存器中。到这里,可以理解作为一个指针变量,它本身的地址是左值,它变量的值(即指向的地址值)为右值。所以指针首先需要在运行时取得它的当前值,然后才能对它进行解除引用操作。

数组名是一个左值,即内存中的位置。但数组名是一个不可修改的左值,即不可被赋值。

int main()

{

int a[3] = {0};

int b = 1;

a = &b; //ERROR: “=” : 左操作数必须为 l 值。

return 0;

}

Section 2 数组与指针的不同

一个例子:

int main()

{

char arr[4] = “abc”; // Note 1

//char arr[4] = {'a', 'b', 'c', '�'}; // Note 2

char *ptr = “ABC”; // Note 3

//ptr+1 = &arr[2]; // Note 4

printf(“arr: %x, %x, %x %x ”, &arr, &arr[0], &arr[1]); //Note 5

printf(“ptr: %x, %x, %x %x ”, &ptr, &ptr[0], &ptr[1]);

return 0;

}

Note 1&2等价定义,其结构如下:

a b c �

[__] [__] [__] [__]

12fed4 +1 +2 +3

Note 3结构如下

42703c A B C �

[__] [__] [__] [__] [__]

12fec8 42703c +1 +2 +3

Note 4复习一下Section 1.显然的错误,因为p+1首先需要知道p的值(右值),只有在运行时刻才能得到,编译时刻就希望对其所在的地址进行赋值显然错误,

Note 5验证Note1和3,运行结果如下:

arr: 12fed4, 12fed4, 12fed5

ptr: 12fec8, 42703c, 42703d

可以发现,arr的地址(左值)的结果与数组中首元素的地址一致,而ptr的变量值(右值)与数组的首元素地址一致。

因此对一个数组中的元素进行引用,c=arr[i]和c=ptr[i]都能够取出相应数组中的第i个元素。但要注意这两个操作的过程完全不同:

c = arr[i]; c = ptr[i];

1:取地址12fec8的内容,即42703c

1 取出i的值与12fed4相加 2:取出i的值与42703c相加

2 取地址(12fed4+ i)的内容 3:取地址(42703c+i)的内容

得到结论:尽管c=arr[i]和c=ptr[i]用同样的形式完成了同样的功能,但绝不可以混用。注意数组原始的声明方式,如果原始声明为数组式的,那么对其元素的引用要使用数组形式,反之亦然。

文件1中:

C语言数据结构与指针 第7篇

用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的。在使用时应注意以下几个问题:

1)字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以作为串的结束。字符数组现金网96y.org是由于若干个数组元素组成的,它可用来存放整个字符串。

2)对字符串指针方式

char *ps=C Language;

可以写为:

char *ps;

ps=C Language;

而对数组方式:

static char st[]={C Language};

不能写为:

char st[20];

st={C Language};

而只能对字符数组的各元素逐个赋值。

从以上几点可以看出字符串指针变量与字符数组在使用时的区别,同时也可看出使用指针变量更加方便。

前面说过,当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。但是博彩娱乐棋牌q07i5.org对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。

因此,char *ps=C Langage;

或者

char *ps;

ps=C Language;

浅析C语言数组与指针 第8篇

关键词:C语言,指针,数组,自增自减

在C语言中数组表示一组数据类型都一样的有序数据的集合, 在内存中, 它们占有连续的存储单元, 数组分一维数组和多维数组, 一维数组是数组中最简单的, 比较容易理解, 用一个数组名和一个下标就能唯一地确定一个元素。多维数组理解相对抽象些, 以二维数组举例, 二维数组在内存中虽然是占一个连续的存储单元, 但是习惯上把它写成矩阵的形式, 更有助于理解其逻辑结构, 二维数组每一行都可以看成一个一维数组。任何数组它们的数组名代表数组的首地址。而指针是C语言的另一个重要概念, 指针代表地址, 并且指针是可以移动的, 对于数组和指针的使用, 初学者往往感到无所适从, 笔者根据多年经验, 利用等级考试中的典型实例来进行描述和分析, 所有实例如都在VC6.0环境下通过, 希望初学者能快速理解和掌握。

1指向一维数组指针的定义及数组元素的引用

定义指向数组元素的指针变量的方法, 与定义指向变量的指针变量相同, 假设定义了一个一维数组int a[5]和一个指针变量int *p, 如何让指针变量指向数组呢?对于一维数组来说, 只要让指针变量指向它的数组元素就可以, 因为数组名a代表数组的首地址, 所以p=&a[0] 或p=a都表示指针指向数组的第一个元素, 直接定义可以写成int *p=a。而p+1表示指向下一个元素, p-1表示指向数组上一个元素, 这样, 其后面第i个元素它的地址就可以表示成p+i, 也可以表示成a+i。

若p指向a[0], 而a[i]的地址可以用p+i或a+i表示, 所以, 引用数组元素的时候, 既可以用普通的下标法如a[i]形式, 也可以用指针法, 这时* (p+i) 和* (a+i) 都可以表示a[i]元素。

实例分析:此实例中, 定义了一个指针指向a[1], i的值为3, 输出a[3]和p[3]的值, 很多初学者以为p[i]的写法是错误的, 有的初学者则认为a[3]和p[3]等价, 输出结果是40, 40, 但实际上, 在C语言中, 指针变量可以带下标, 程序在编译时, 会把下标的处理转换为地址的, p[i]处理成* (p+i) , 因为一开始的时候p指向a[1], 那么p+i则表示往后数第三个元素, 也就是a[4], 故此程序输p出结果为40, 50。若一开始p=a, 也就是说指针指向第一个元素, 那么a[i]和p[i] 的值就是相等的。

2指针与自增自减运算符的结合

指针若与自增自减运算符结合起来使用, 初学者最容易出错, 以自增运算符为例, 若程序中出现*p++、* (p++) 、* (++p) 、++ (*p) 等算式, 看起来差不多, 很多初学者搞不懂它们之间的区别, 殊不知“失之毫厘, 谬以千里”, 因为不懂它们的区别, 分析程序时往往得到错误的结果。

首先, 大家要知道“*”和“++”都是单目运算符, 它们同一个优先级, 其结合方向是自右向左的, 所以*p++和* (p++) 等价, 根据自增运算符的“名前先取”原则, 要先取*p的值, 再使p自增1, 即指向下一个数组元素, * (++p) 则是先使p指向下一个元素, 再取*p的值, 这几个算式都是对所指的地址加1。 ++ (*p) 表示先取*p, 再在这个值的基础上加1, 也就是对所指的元素的值加1。

实例分析:此实例中, 自先定义了数组a, 指针p和指向指针的指针k, 通过p=a和k=&p语句, 使指针p指向数组a的首地址, k指向指针p, 接下来printf (“%d ”, * (p++) ) 语句, 是先输出*p的值为2, 再使指针往后指, 再输出**k的指也就是*p的值, 此时, p指向4, 输出4, 程序的输出结果为“2 4”。

3指向二维数组指针的定义及数组元素的引用

在使用指针指向二维数组时首先要了解多维数组元素的地址表示方式, 假设有二维数组a[3][3], 那么在逻辑上可以把这个二维数组看作是一个3行3列的表格, 也可以看成是一个有3个元素的一维数组, 该数组的每个元素也是一个一维数组, 序号为0的行的首地址可以用a[0]、&a[0]或a表示, 序号为1的行的首地址可表示为a[1]、&a[1]或a+1, 如图1所示。根据一维数组指针的定义, a[0]的值可以又表示成为*a, a[1]可以表示为* (a+1) , a[i]即为* (a+i) 。序号为0的行的首地址也就是元素a[0][0]的地址, 即&a[0][0], 它后面几个元素的地址可以表示为a[0]+1, a[0]+2 , 若用指针法表示为* (a+0) 、* (a+0) +1和* (a+0) +2, 以此类推, 第i行第j列元素的地址&a [i][j]可以表示成为a[i]+j, 指针法表示为* (a+i) +j, 也就是说&a[i][j]、 a[i]+j、* (a+i) +j是等价的。这样, 对于一个二维数组来说, 元素a[i] [j]可用指针法表示为* (a[i]+j) 或* (* (a+i) +j) 。

指针变量指向二维数组中的元素, 可以有两种定义指针方法, 一种是直接定义成指向数组元素的指针变量, 如int *p, 再让p指向数组中某个具体元素;还有一种是定义成指向二维数组某一行的指针变量, 假设一行有M个数据, 则可以定义成int (*p) [M]=a, 这样就可以让指针指向第一行。

程序分析:此实例中, 指针p指向二维数组a的首地址, 然后执行循环, 首先i=0, j=0, 累加* (* (p+0) +0) , 即a[0][0], 接着i=0, j=1, 累加* (* (p+0) +1) , 即a[0][1], 然后j=2时跳出内循环, 以此类推, 执行下一次外循环i=1时, 累加a[1][0]和a[1][1], 执行外循环i=2时累加a[2][0]和a[2][1]……最后i=3时跳出整个循环, 由此看出, 语句在这里其实就是累加二维数组第一列和第二列的元素。最后结果为1+3+9+11+17+19=60, 输出“k=60”。

总之, 指针和数组结合起来使用非常灵活, 同一地址有多种表示方法, 而指针根据地址表示的不同可定义成指向数组元素的指针和指向某行数据的指针, 初学者很难理解, 大家一定要从C语言的数组和指针的概念出发, 仔细琢磨, 反复思考, 多比较, 多应用, 如果能很好地应用指针访问数组, 对C语言后面的知识学习有很大帮助, 如C语言的结构体、共用体、链表等, 都是跟指针和数组相关的, 正确灵活地运用指针, 可以使程序更加简洁、紧凑、高效。

参考文献

[1]谭浩强.C程序设计[M].4版.北京:清华大学出版社, 2010.

[2]未来教育.全国计算机等级考试模拟考场二级C[M].成都:电子科技大学出版社, 2015.

C语言数据结构与指针 第9篇

关键词:C语言指针;创新思维;探究发现;学以致用

中图分类号:G712 文献标识码:A 文章编号:1671-0568(2013)32-0075-02

指针是一个重要的数据类型,指针的应用可以使代码高效、简洁,但也最容易出错。指针在函数传值、内存使用、数组遍历等使用上的灵活性及其类型的多样性,使得指针教学成为C语言教学的重点,也是难点,是教师与学生花精力和时间最多,而效果相对较差的知识点。在C语言教学中,指针的讲授往往处于非常尴尬的地位,教师与学生都感到心有余而力不足。

一、教学现状

指针的类型很多,这是学生正确使用指针的一大障碍。指针变量的值是一个整数(内存字节编号),但与int不同,它代表内存的一个地址,需符合系统的地址编码规则。使用时可以指向不同的数据类型,学生很容易犯错。

C语言规定,指针变量只能进行加减法运算:指针变量-指针变量,参与运算的指针变量必须是同类型的指针变量并指向同一块有效的内存区域才有意义,其结果是一个整数;指针变量的值±整数其结果为指向同一块有效的内存区域,且该内存区域保存的数据类型与指针变量类型相同才有意义,对比较运算也有相同的限制。这也是学生很难理解的知识点,使用时容易出错。

讲授指针赋值操作时,只是告诉学生有两种方式:一种是把某个同类型变量的地址或同类型指针变量的值赋给一个指针变量;另一种是把申请内存库函数的返回值赋给一个指针变量。学生难以理解直接赋一个地址给指针变量为什么经常出错。

二、基于创新思维的教学

1.创新思维内涵

创新思维就是把已有的思维材料进行整理抽象,以适应新的环境,进而求解新的问题。在教学中,采用何种方法能启发学生获得知识呢?美国教育家布鲁纳主张教学采用“探究发现”法,引导学生像科学家那样探求知识,而不是被动接受教师的灌输。不论是在校学生的发现,还是科学家致力于日趋尖端的研究领域的发现,按实质来说,都是把现象重新组织和转换,使人能超越现象再进行组合,从而获得新的领悟。

对教学而言的创新思维,一般是指对引导学生利用已有的知识,发现新问题、引入新方法、解决新问题,使学生了解创新的过程与方法,理解理论源于实际的本质,进而培养学生的创新思维和科学素养。

2.基于创新思维的指针教学

C语言规定,指针变量只能保存地址,其实在学习指针之前,学生已经使用过地址。如代码int x;scanf(“%d”,&x);&x就是变量x的地址,代码的含义就是声明一个int型变量x,并把x的地址传给scanf()函数。学习指针之前,只告诉学生记住变量前的&;学习指针之后,教师就应根据内存模型,告诉学生在计算机中每个内存空间(字节)对应的地址是唯一的,scanf函数功能就是把从键盘上输入的数据保存在内存中,供主调函数使用。所以,主调函数只要把变量地址(内存地址)传递给scanf函数即可。这个地址是对scanf函数,主调函数都是可见,因而都可以操作其中的数据,这样就实现了scanf函数的功能。

为了引导学生利用创新思维,学习新知识指针。可以帮助学生回顾,当计算机执行类似int x;这样的声明语句时,系统的行为,来建立新旧知识的联系。①系统给x分配了与int类型相符的连续空间(vc是4字节);②系统记录了这个空间第一个字节的编号,即x的地址;③系统标识了这个空间中保存的数据是int类型的数据。

在程序开发中,经常需要把多个具有相同属性的数据保存在连续区域,而数据的个数需要到运行时才能确定。只要能记住这块内存开始的位置(即内存地址,也就是第一个字节的编号),通过简单的加减整数操作访问到全部的数据。

首先,教师需要引导学生思考,C语言程序要实现这种场景就必须引入新的数据类型:这个数据类型的变量可以保存数据空间地址,可以与一个整数相加减,还需要标识保存在数据空间中的数据的数据类型。指出这种新数据类型就是C语言中的指针类型,它具有两种属性(地址及保存在该内存空间数据的数据类型),给出新的数据类型——指针变量的声明格式。例如,int * x;其中*标识x是一个指针变量,int标识这个x中只能保存int类型数据空间的地址。

其次,教师引导学生分析这种新的数据类型,如int *x;根据学过的变量声明格式可知,x是一个int *类型的变量(int类型的指针变量),*x是一个int类型的变量。通过例子,利用数据的有效性,使学生明白x中的值必须是系统分配给程序的有效内存的地址才有意义,从而理解指针运算的本质。此时,学生经历一个完整的发明过程,从应用中发现现有知识不能解决或不完美,进而引入一个能解决问题的新数据类型来圆满解决问题。这就是创新思维。学生在学习新知识的同时,建立了新旧知识的联系及使用场景。

最后,教师指导学生进行总结,声明指针变量时(int *x;),系统的行为:①系统给x分配了与地址值相符的连续空间(vc是4字节);②系统记录了这个空间第一个字节的编号,即x本身的地址;③系统标识了x中只能指向保存int类型数据的内存空间;④x中的值必须是系统分配给程序的有效内存空间的地址才有意义。

引导学生总结指针变量的运算规律,计算机的内存有很多,但只有系统分配给程序的内存才能被使用。在程序中对指针变量进行操作,其本质是为了对指针变量所指向的内存地址中的数据进行操作。要使指针变量指向有效的内存空间,那么指针变量与指针变量之间只是减法运算,而且参与运算的指针变量是指向同一块连续的内存空间才有意义。指针变量与整数运算的结果一定是与指针变量所指向地址属于同一块连续的有效内存空间才有意义。

对于比较运算来说,其本质是由地址的特点决定的:地址值是内存空间编号,只是序号而已。因此,指针变量的比较运算只是为了确定内存空间的位置关系,而内存空间的位置关系只有指向同一块连续的有效内存空间才有意义。加法、乘法、除法等运算,都不能保证运算结果,是一个系统分配给程序的有效内存地址,因而C语言规定指针变量进行这些运算是不合法的。

基于创新思维的教学,引导学生按照知识获取的规律学习,理论源于实践,当原有的知识不能解决问题时就需引入新的理论,并利用新知识解决问题,达到学以致用的目标。

参考文献:

[1]李俊萩等.C语言指针教学中的知识点分析与总结[J].计算机教育,2011,(08).

[2]于福生等.C语言课程中指针内容体系设置的改革尝试[J].计算机教育,2013,(04).

[3](美)杰罗姆.S.布鲁纳.布鲁纳教育论著选[M].邵瑞珍,张渭城译.北京:人民教育出版社,1989.

C语言指针 第10篇

1、指针的定义和简单使用

定义一个指针变量和定义一般的变量类似,只需在变量名前面加一个“*”。对一个指针变量赋值可以用取地址符&来获取到一个变量的地址,如果要获得指针指向的内存区域的数据,用解参考运算符*(也称为间接运算符,它返回其操作数指向的对象的值)。指针的值为NULL(NULL是stdio.h中定义的符号变量,实际上是0)说明其不指向任何的内存单元,0是唯一直接可以赋值给指针变量的整数值。实际上,*和&是互补的,当两个运算符连续应用于一个指针变量时,无论顺序如何,运算结果相同。同时可以用printf中的格式化字符串%p来输出指针变量的值,下面是一个简单的程序。

[cpp]

#include

int main

{

int a;

a=9;

//定义并初始化一个指针,命名就可以看出

int *aPtr=NULL;

//将指针指向变量a

aPtr=&a;

printf(“The address of a is %p”

“nThe value of aPtr is %p”,&a,aPtr);

printf(“nnThe value of a is %d”

“nThe value of *aPtr is %d”,a,*aPtr);

printf(“nnShowing that * and & are complements of ”

“each othern&*aPtr = %p”

“n*&aPtr = %pn”,&*aPtr,*&aPtr);

return 0;

}

2、用指针做函数的参数

2.1 通过指针实现的引用传递

程序设计语言的参数传递方式,大致分两种:值传递和引用传递。C语言中没有引用传递,但是C语言通过指针间接实现了引用传递。通过用指针变量作为函数的参数,可以传递变量的地址(只需要在变量前面加上&运算符就可以),这样,用该地址就可以访问到主调函数中的该变量的内存地址,并可以进行相应的修改。这样,在函数执行完毕之后,修改仍然可以得到保留。

2.2 const

const限定符可以告诉编译器特定的变量的值是不能被修改的。如果想确保函数不会修改传递进来的参数值,应该将参数声明为const。这样对于C语言中用指针实现的引用传递,有四种情况:指向非常量数据的非常量指针(int *aPtr),指向非常量数据的常量指针(int *const aPtr),指向常量数据的非常量指针(const int *aPtr)和指向常量数据的常量指针(const int * const aPtr)。简单的说,就是指针变量自身和指针指向的变量都有可能是const,这样就产生了四种情况,这四种情况提供了四种不同的访问权限,下面分别解释。

指向非常量数据的非常量指针(int *aPtr):指针的值本身和指针指向变量的值都可以在函数中被修改。

指向非常量数据的常量指针(int *const aPtr):指针的值不能被修改,但是指针指向的变量的值可以被修改。

指向常量数据的非常量指针(const int *aPtr):指针指向的值不能被修改,但是指针本身的值可以被修改。

指向常量数据的常量指针(const int * const aPtr):指针本身和指针指向变量的值都不能被修改。

3、sizeof和指针运算

3.1 sizeof

sizeof是C语言中特殊的一元运算符,可以应用在变量名称、数据类型和常量之前,它在程序编译期间以字节为单位来确定数组或其他数据类型的大小。当应用于数组时,sizeof返回数组中的字节总数。如float a[20],sizeof(a)的值应该是4*20,80。当然,如果想获得数组的大小可以采用sizeof(a)/sizeof(float)。

3.2 指针运算

实际上,指针变量可以进行的算术操作是有限的:递增,递减,将指针和整数相加,从指针中减去一个整数或者一个指针减去另一个指针,

需要注意的是,对于指针的算术运算,其单位长度并不是一般意义上的1,而是sizeof(TYPE)。这样,如果float a[14]; float *aPtr=a;(或者int *aPtr=&a[0]); aPtr++;这样aPtr应该指向的是数组a的第二个元素,也就是a[1],这里的单位长度就是sizeof(float)。同样地,如果aPtr=aPtr+5;,这样aPtr又指向了数组a的第6个元素。如果aPtr-a,这样可以得到两个指针之间的元素间隔个数。应该是6。

进行指针运算要注意:

(1)如果将一个指针的值赋给另外一个指针,那么这两个指针的类型必须相同,否则应该用类型转换运算符进行类型转换。但是,有一个例外就是指向void类型的指针,它是通用指针,可以代表任何指针类型。因此,所有指针类型都可以赋值给void指针,而void指针也可以赋值给任何类型的指针,而不需要任何类型转换运算符。但是,void指针不能解参考,编译器知道指向int类型的指针引用的是32位计算机上的4个字节内存,但指向void的指针仅包含未知数据类型的内存位置,也就是说,编译器不知道指针所引用的字节数。编译器必须知道数据类型,才能确定所引用的字节数。

(2)除非两个指针变量都指向的是一个数组中的元素,否则对它们相减的结果没有任何意义,因为我们不能假设两个变量在内存中是连续的。

4、指针和数组

4.1 数组和指针的共性

实际上,数组名称的本质是一个常量指针。因此,int a[6]; int *aPtr;定义一个数组和指针之后,通过a[3],*(a+3)和*(aPtr+3)都可以访问到数组的第四个元素的值。但是区别在于,aPtr=aPtr+3;这样aPtr就指向了a数组的第四个元素,但是,不能a=a+3;,因为a是一个数组名,它是一个常量指针它的值不能被修改,更加具体地说,它应该是一个指向非常量数据的常量指针。

4.2 指针数组

数组元素也可以是指针类型,指针数组常见的用途就是构成由字符串组成的数组,简单地说就是字符串数组,数组中的每一个元素都是字符串。下面是一个例子,const限定符说明不能修改每个元素指针所指向的字符串。

[cpp]

#include

int main()

{

const char *suit[4]={“Hearts”,“Diamonds”,“Clubs”,“Spades”};

int i;

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

printf(“sizeof pointer to ”%s“ :%dn”,suit[i],sizeof(suit[i]));

printf(“nsizeof suit:%dn”,sizeof(suit));

return 0;

}

运行结果如下:

从这个例子中,可以看出const char *suit[4]={“Hearts”,“Diamonds”,“Clubs”,“Spades”};定义了一个指针数组,但是,其中的每个元素只是一个指针,而不是数组名(如果是数组名的话,sizeof的结果不应该都是4)。这样定义字符串数组可以节省空间。

5、函数指针

和数组名实际上就是数组第一个元素在内存中的地址类似,函数迷你实际上就是执行函数任务的代码在内存中的起始地址。函数指针包含函数在内存中的地址,可以传递给函数、从函数返回、存储在数组中或者是赋值给其它的函数指针,下面是两个函数指针的例子。

(1) 用函数指针实现升序/降序排序

[cpp]

#include

#define SIZE 10

int ascending(int a,int b)

{

return a>b;

}

int descending(int a,int b)

{

return a

}

void swap(int *aPtr,int *bPtr)

{

int temp=*aPtr;

*aPtr=*bPtr;

*bPtr=temp;

C语言指针实习 第11篇

一、实习目的

姓名:尹思智

学号:2012014413

完成日期:2013年4月

1.由键盘输入10个整数,将它们从小到大排序 2.将10个字符串(设其长度小于30)排序。

3.找出二维数组(设4行5列)中的最大数及其位置。

4.从键盘输入一串字符,从下标为m的字符开始,取出n个字符(m和n从键盘输入),形成一个新字符串 5.实现字符串的拷贝

6.编写一程序,将一个字符串反序存放。

二、实习步骤

1.由键盘输入10个整数,将它们从小到大排序 #include void main(){ int a[10],t,i;int *p;printf(“输入十个数:n”);for(p=a;p

scanf(“%d”,p);for(i=0;i<10;i++)for(p=a;p

if(*p>*(p+1))

{

t=*p;

*p=*(p+1);

*(p+1)=t;}

for(p=a;p

printf(“%d ”,*p);}

2、将10个字符串(设其长度小于30)排序 #include #include void main(){ char cty[10][30],*str[10],*temp;int i,j,k;for(i=0;i<10;i++)

str[i]=cty[i];printf(“输入十个字符串:n”);for(i=0;i<10;i++)

gets(cty[i]);for(i=0;i<9;i++){

k=i;

for(j=i+1;j<10;j++)

if(strcmp(str[k],str[j])>0)

k=j;

temp=str[k];

str[k]=str[i];

str[i]=temp;} printf(“排序后:n”);for(i=0;i<10;i++)

printf(“%sn”,str[i]);}

2.将10个字符串(设其长度小于30)排序。

3.找出二维数组(设4行5列)中的最大数及其位置。

4.从键盘输入一串字符,从下标为m的字符开始,取出n个字符(m和n从键盘输入),形成一个新字符串 5.实现字符串的拷贝

6.编写一程序,将一个字符串反序存放。

学通C语言:函数型指针 第12篇

int func(const int a, const int b);

那么,此时声明的函数变量add的地址即为这个函数的地址,同时,add的值保存为这个函数的地址,这个特性与数组相似:数组变量与数组变量的地址均为数组的起始地址。而在这个函数声明中,函数类型为int (const int a, const int b)。使用该函数类型来定义一个函数型指针,其方式如下:

int (* fp)(const int a, const int b);   /* 其中,参数列表的参数名a和b可省 */

上述语句将变量func定义为指向类型为int (const int a, const int b)的指针操作符和变量名两侧的小括号不可省,否则其含义大不相同。例如:

int * fp(const int a, const int b);

此时,指针操作符与数据类型int结合为int型指针类型,该语句只是声明了一个fp函数,而非定义一个函数指针。为该函数型指针赋值的方式如下:

fp = func;

被赋值的函数变量的类型必须与fp的类型完全一致,包括其返回类型和每一个形参的类型。否则程序将报错。

注意:函数型指针变量赋值时,左值与右值的类型必须完全一致。

使用函数型指针变量调用函数的方法与使用函数变量类似,得到函数地址后再带上参数列表即可。可以使用下面两种方式来调用函数:

fp(5, 6);

(*fp)(5, 6);

由于fp被赋值为函数变量func的地址,而func的值又等于其地址,所以*fp可以得到func函数的地址。因此,在调用方式上,可以粗略地将两者视为一致(实际上其后台的处理略有不同)。范例14-7演示了如何使用函数型指针来调用函数。

【范例14-7】使用函数型指针来调用函数,实现方法如示例代码14-7所示。

示例代码14-7

01   #include

02

03   int add(const int a, const int b) {         /* 定义add函数 */

04      return a + b;

05   }

06

07   int main(void) {

08      int (*fp) (const int a, const int b);      /* 定义函数指针 */

09

10      fp = add;                        /* 将其赋值为add */

11      printf(“3 + 4 = %d”, fp(3, 4));         /* 使用fp计算+ 4的值 */

12      printf(“3 + 4 = %d”, (*fp)(3, 4));      /* 使用*fp计算+ 4的值 */

13

14      printf(“%p”, add);                  /* 输出add的值 */

15      printf(“%p”, &add);                  /* 输出add的地址 */

16      printf(“%p”, fp);                  /* 输出fp的值 */

17      printf(“%p”, *fp);                  /* 输出fp指向的值 */

18

19      return 0;

20   }

【运行结果】程序运行后,

【代码解析】本程序定义了一个函数指针,并将其赋值为相应类型的函数变量add。

   第11~12行分别使用fp和*fp的方式调用函数,从图14-12的第1~2行中可以看到它们的调用结果是一样的。

   第14~17行输出了add的值和地址、fp的值和指向的值,从图14-12的第3~6行中可以看到它们的调用结果都是一样的。

C语言数据结构与指针

C语言数据结构与指针(精选12篇)C语言数据结构与指针 第1篇数据结构【第四次】实验报告学院:班级:学号:姓名:实验四(一)实验名称:C...
点击下载文档文档内容为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

确认删除?
回到顶部