C和指针 (pointers on C)――第十二章:使用结构和指针

时间:2022-05-23 01:43:03 其他范文 收藏本文 下载本文

C和指针 (pointers on C)――第十二章:使用结构和指针(共8篇)由网友“Rhykcha”投稿提供,以下是小编收集整理的C和指针 (pointers on C)――第十二章:使用结构和指针,仅供参考,希望对大家有所帮助。

C和指针 (pointers on C)――第十二章:使用结构和指针

篇1:C和指针 (pointers on C)――第十二章:使用结构和指针

这章就是链表,先单链表,后双向链表。

总结:

单链表是一种使用指针来存储值的数据结构。链表中的每个节点包含一个字段,用于指向链表的下一个节点。

有一个独立的根指针指向链表的第1个节点。单链表只能从一个方向遍历。

如何insert单链表:1、新节点的link字段必须设置为指向它的后面节点。2、前一个节点的link字段必须指向这个新节点。

为了防止可能会插入链表的起始位置这种情况,在C中,可以保存一个指向必须进行修改的link字段的指针,而不是保存一个指向前一个节点的指针。

双链表中的每个节点包含两个link字段:其中一个指向链表的下一个node,另一个指向前一个node。

双链表有两个根指针,一个指向第一个node,另一个指向最后一个node。因此遍历的过程中可以从任何一端开始,而且在遍历过程中够可以改变方向。

为了把一个新节点插入到双链表中,我们必须修改4个指针。新节点的前向和后向link字段必需被设置,前一个节点的fwd和后一个节点的bwd也要修改,指向新节点。

警告:

1、落到链表尾部的后面。

2、使用指针时应该格外小心,因为C并没有对他们的使用提供安全网。

3、从if语句中提炼语句可能会改变测试结果。

编程提示:

1、消除特殊情况使代码更易于维护。

2、不要轻易的进行提炼语句,这样会使你的语句更难维护。

编程实例:(本章就不再弄习题了,关于数据结构这块会有大量代码进行训练)

1、提炼后的单链表插入操作

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#include “stdlib.h”

typedef struct NODE

{

struct NODE *link;

int        value;

} Node;

int sll_int(register Node **linkp, int new_value)

{

register Node *current;    //指向当前节点

register Node *new_node;   //指向插入节点

/*

** 寻找正确插入位置,按顺序访问链表,直到有个值大于或等于新值

*/

while ((current = current->link) != NULL && current->value < new_value)

{

linkp = ¤t->link; //移动linkp指向下一个Node的link

}

/* 分配新的内存,并存到新节点去 */

new_node = (NODE *) malloc (sizeof(NODE));

if (new_node == NULL)

{

return 0;

}

new_node->value = new_value;

/* 插入新节点 */

new_node->link = current;

*linkp = new_node;

return 1;

}

2、双链表插入操作

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

#include “stdlib.h”

typedef struct NODE

{

struct NODE *fwd;

struct NODE *bwd;

int value;

}Node;

int dll_insert(Node *rootp, int value)

{

/* 把一个值插入到一个双向链表中,rootp是一个指向根节点的指针

value 是插入的新值

返回值:如果已经存在链表中,返回0

如果内存不足导致无法插入,返回-1,成功返回1;

*/

Node *this_node;

Node *next_node;

Node *new_node;

for (this_node = rootp; next_node != NULL; this_node = next_node )

{

if (next_node->value == value)

return 0;

if (next_node->value < value)

break;

next_node = next_node->fwd;

}

/* 为新节点申请内存空间*/

new_node = (Node *) malloc (sizeof(Node));

if (new_node == NULL)

return -1;

new_node->value = value;

/*

插入节点

if 不在链表尾部 then 不在链表起始位置 or 位于链表起始位置

else 在链表尾部 then 不在链表起始位置 or 位于链表起始位置(空链表)

*/

if (next_node->fwd != NULL)

{

/*不在链表尾部*/

if (this_node != rootp)

{

/* 不在链表的头部 */

this_node->fwd = new_node;

next_node->bwd = new_node;

new_node->bwd = this_node;

new_node->fwd = next_node;

}

else

{

/* 在链表的头部*/

rootp->fwd = new_node;

next_node->bwd = new_node;

new_node->bwd = rootp;

new_node->fwd = next_node;

}

}

else

{

/*在链表尾部*/

if (this_node->bwd != rootp)

{

/* 不在链表的头部 */

new_node->fwd = NULL;

new_node->bwd = this_node;

this_node->fwd = new_node;

rootp->bwd = new_node;

}

else

{

/* 在链表的头部*/

new_node->fwd = NULL;

new_node->bwd = NULL;

rootp->bwd = new_node;

rootp->fwd = new_node;

}

}

}

篇2: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

篇3:C语言指针

指针变量是包含内存地址的变量,它指向内存中的一块区域,通过指针的值,可以间接访问到相应的内存单元的数据,并做相应的修改,

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;

}

篇4:指针、结构、联合和枚举(C语言)

Turbo C新的数据类型:

结构、联合和枚举, 其中结构和联合是以前讲过的五种基本数据类型(整型、浮

点型、字符型、指针 型和无值型)的组合, 枚举是一个被命名为整型常数的集合。

最后对类型说明(typedef)和预处理指令作一阐述。

1、 指        针(point)

学习Turbo C语言, 如果你不能用指针编写有效、正确和灵活的程序, 可以

认为你没有学好C语言。指针、地址、数组及其 相互关系是C语言中最有特色的部

分。规范地使用指针, 可以使程序达到简单明了, 因此, 我们不但要学会如何正

确地使用指针, 而且要学会在各种情况下正确地使用指针变量。

1. 指针和地址

1.1 指针基本概念及其指针变量的定义

1.1.1 指针变量的定义

我们知道变量在计算机内是占有一块存贮区域的, 变量的值就存放在这块区

域之中, 在计算机内部, 通过访问或修改这块区域的内容来访问或修改相应的变

量。Turbo C语言中, 对于变量的访问形式之一, 就是先求出变量的地址, 然后

再 通过地址对它进行访问, 这就是这里所要论述的指针及其指针变量。

所谓变量的指针, 实际上指变量的地址。变量的地址虽然在形式上好象类似

于整数, 但在概念上不同于以前介绍过的整数, 它属于一种新的数据类型, 即指

针 类型。Turbo C中, 一般用“指针”来指明这样一个表达式&x的类型, 而用 “地

址”作为它的值, 也就是说, 若x为一整型变量, 则表达式&x的类型是指向整数的

指针, 而它的值是变量x的地址。同样, 若

double d;

则&d的类型是指向以精度数d的指针, 而&d的值是双精度变量d的地址。所以, 指

针和地址是用来叙述一个对 象的两个方面。虽然&x、&d的值分别是整型变量x 和

双精度变量d的地址, 但&x、&d的类型是不同的, 一个是指向整型变量x的指针,

而另一个则是指向双精度变量d的指针。在习惯上, 很多情况下指针和地址这两

个术语混用了。

我们可以用下述方法来定义一个指针类型的变量。

int *ip;

首先说明了它是一指针类型的变量, 注意在定义中不要漏写符号“*”, 否则它为

一般的整型变量了。另外, 在定义中的int 表示该指针变量为指向整型数的指针

类型 的变量, 有时也可称ip为指向整数的指针。ip是一个变量, 它专门存放整型

变量的地址。

指针变量的一般定义为:

类型标识符 *标识符;

其中标识符是指针变量的名字, 标识符前加了“*”号, 表示该变量是指针变

量, 而最前面的“类型标识符”表示该指针变量所指向的变量的类型,

一个指针变

量只能指向同一种类型的变量, 也就是讲, 我们不能定义一个指针变量, 既能指

向一整型变量又能指向双精度变量。

指针变量在定义中允许带初始化项。如:

int i, *ip=&i;

注意, 这里是用&i对ip初始化, 而不是对*ip初始化。和一般变量一样, 对于外

部 或静态指针变量在定义中若不带初始化项, 指针变量被初始化为NULL, 它的值

为0。Turbo C中规定, 当指针值为零时, 指针不指向任何有效数据, 有时也称指

针为空指针。因此, 当调用一个要返回指针的函数(第五节中介绍)时, 常使用返

回值为 NULL来指示函数调用中某些错误情况的发生。

1.1.2 指针变量的引用

既然在指针变量中只能存放地址, 因此, 在使用中不要将一个整数赋给一指

针变量。下面的赋值 是不合法的:

int *ip;

ip=100;

假设

int i=200, x;

int *ip;

我们定义了两个整型变量i, x, 还定义了一个指向整型数的指针变量ip。i, x中

可存放整数, 而ip中只能存放整型变量的地址。我们可以把i的地址赋给ip:

ip=&i;

此时指针变量ip指向整型变量i, 假设变量i的地址为1800, 这个赋值可形象理解

为下图所示的联系。

ip              i

┏━━━┓      ┏━━━┓

┃ 1800 ╂──→ ┃ 200 ┃

┗━━━┛      ┗━━━┛

图1. 给指针变量赋值

以后我们便可以通过指针变量ip间接访问变量 i, 例如:

x=*ip;

运算符*访问以ip为地址的存贮区域, 而ip中存放的是变量i的地址, 因此, *ip

访 问的是地址为1800的存贮区域(因为是整数, 实际上是从1800开始的两个字节),

它就是i所占用的存贮区域, 所以上面的赋值表达式等价于

x=i;

另外, 指针变量和一般变量一样, 存放在它们之中的值是可以改变的, 也就

是说可以改变它们的指向, 假设

int i, j, *p1, *p2;

i='a';

篇5:c指针笔试题

1. 变量的指针,其含义是指该变量的_________.

a)值 b)地址

c)名 d)一个标志

2.若有语句int *point,a=4;和point=&a;下面均代表地址的一组选项是_____. a)a,point,*&a b)&*a,&a,*point

c)*&point,*point,&a d)&a,&*point ,point

3.若有说明;int *p,m=5,n;以下正确的程序段的是________.

a)p=&n; b)p=&n;

scanf(“%d”,&p); scanf(“%d”,*p);

c)scanf(“%d”,&n); d)p=&n;

*p=n; *p=m;

4. 以下程序中调用scanf函数给变量a输入数值的方法是错误的,其错误原因是________.

main

{

int *p,*q,a,b;

p=&a;

printf(“input a:”);

scanf(“%d”,*p);

……

}

a)*p表示的是指针变量p的地址

b)*p表示的是变量a的值,而不是变量a的地址

c)*p表示的是指针变量p的值

d)*p只能用来说明p是一个指针变量

5. 已有变量定义和函数调用语句:int a=25; print_value(&a); 下面函数的正确输出结果是________.

void print_value(int )

{ printf(“%dn”,++);}

a)23 b)24 c)25 d)26

6.若有说明:long *p,a;则不能通过scanf语句正确给输入项读入数据的程序段是

A) *p=&a; scanf(“%ld”,p);

B) p=(long *)malloc(8); scanf(“%ld”,p);

C) scanf(“%ld”,p=&a);

D) scanf(“%ld”,&a);

7.有以下程序

#include

main

{ int m=1,n=2,*p=&m,*q=&n,*r;

r=p;p=q;q=r;

printf(“%d,%d,%d,%dn”,m,n,*p,*q); }

程序运行后的输出结果是

A)1,2,1,2

C)2,1,2,1

篇6:c指针笔试题

1. 有以下程序

main { int a=1, b=3, c=5; int *p1=&a, *p2=&b, *p=&c; *p =*p1*(*p2); printf(“%dn”,c); }

执行后的输出结果是

A)1

2. 有以下程序

main

{ int a,k=4,m=4,*p1=&k,*p2=&m;

a=p1==&m;

printf(“%dn”,a);

}

程序运行后的输出结果是

A)4

B)1 C)0 D)运行时出错,无定值 B)2 C)3 D)4 B)1,2,2,1 D)2,1,1,2

3. 在16位编译系统上,若有定义int a={10,20,30}, *p=a;,当执行p++;后,下列说法错误的是

A)p向高地址移了一个字节

C)p向高地址移了两个字节

4.有以下程序段

int a[10]={1,2,3,4,5,6,7,8,9,10},*p=&a[3],b;

b=p[5];

b中的值是

A)5 B)6 C)8 D)9

5.若有以下定义,则对a数组元素的正确引用是_________.

int a[5],*p=a;

a)*&a[5] b)a+2 c)*(p+5) d)*(a+2)

6.若有以下定义,则p+5表示_______.

int a[10],*p=a;

a)元素a[5]的地址 b)元素a[5]的值

c)元素a[6]的地址 d)元素a[6]的值

7.设已有定义: int a[10]={15,12,7,31,47,20,16,28,13,19},*p; 下列语句中正确的是

A) for(p=a;a<(p+10);a++);

B) for(p=a;p<(a+10);p++);

C) for(p=a,a=a+10;p

D) for(p=a;a

篇7:c指针笔试题

1.有以下程序段

#include

int main

{ int x = {10, 20, 30};

int *px = x;

printf(“%d,”, ++*px); printf(“%d,”, *px);

px = x;

printf(“%d,”, (*px)++); printf(“%d,”, *px);

px = x;

printf(“%d,”, *px++); printf(“%d,”, *px);

px = x;

printf(“%d,”, *++px); printf(“%dn”, *px);

return 0; B)p向高地址移了一个存储单元 D)p与a+1等价

}

程序运行后的输出结果是( )

A)11,11,11,12,12,20,20,20 B)20,10,11,10,11,10,11,10

C)11,11,11,12,12,13,20,20 D)20,10,11,20,11,12,20,20

2.设有如下定义:

int arr={6,7,8,9,10};

int *ptr;

ptr=arr;

*(ptr+2)+=2;

printf (“%d,%dn”,*ptr,*(ptr+2));

则程序段的输出结果为

A)8,10 B)6,8 C)7,9 D)6,10

3.若有定义:int a={2,4,6,8,10,12},*p=a;则*(p+1)的值是______. *(a+5)的值是_________.

4.若有以下说明和语句,int c[4][5],(*p)[5];p=c;能正确引用c数组元素的是______.

A) p+1 B) *(p+3) C) *(p+1)+3 D) *(p[0]+2)

5.若有定义:int a[2][3],则对a数组的第i行j列元素地址的正确引用为______. a)*(a[i]+j) b)(a+i) c)*(a+j) d)a[i]+j

6.若有以下定义:int a[2][3]={2,4,6,8,10,12};则a[1][0]的值是_____. *(*(a+1)+0)的值是________.

7.有以下定义

char a[10],*b=a;

不能给数组a输入字符串的语句是

A)gets(a) B)gets(a[0]) C)gets(&a[0]); D)gets(b);

8.下面程序段的运行结果是_________.

char *s=“abcde”;

s+=2;printf(“%d”,s);

a)cde b)字符'c' c)字符'c'的地址 d)无确定的输出结果

9.以下程序段中,不能正确赋字符串(编译时系统会提示错误)的是

A) char s[10]=“abcdefg”; B) char t=“abcdefg”,*s=t;

C) char s[10];s=“abcdefg”; D) char s[10];strcpy(s,“abcdefg”);

10.设已有定义: char *st=“how are you”; 下列程序段中正确的是

A) char a[11], *p; strcpy(p=a+1,&st[4]);

B) char a[11]; strcpy(++a, st);

C) char a[11]; strcpy(a, st);

D) char a, *p; strcpy(p=&a[1],st+2);

篇8:C语言指针讲解

指针是C语言的一种数据类型,类似于C中的其他类型,例如int ,char 等,既然指针是一种类型,当我们定义该类型变量,该类型变量就称为指针变量。

C中有了指针就有了指向。指向:指针变量指向本身保存的内容(地址或指针)所表示的内存单元。

C语言指针是一个特殊的变量,其里面储存的数值被解释成为内存里的一个地址。

在计算机中,所有对数据的操作,都是通过其地址进行的,指针让程序的效率更高,代码更少。

在学习指针的时间,一定要理解并区分指针的四个感念:指针的类型,指针所指向的类型,指针的值,指针本身所占据的内存区。

指针变量定义的一般形式:类型说明符* 变量名。 类型说明符:表示该指针变量指向的变量的数据类型,并且该指针变量只能指向该数据类型的变量。这是指针变量的特征。

*:表示该变量的指针变量。这也是指针变量的特征。

变量名:表示指针变量的名称。

例如:char *pstu; *表示pstu是一个指针变量,char是指针变量pstu指向的变量的数据类型。整个语句表示定义了一个指向char类型变量的指针变量。但具体pstu指向哪个char类型的变量,这就要看在使用pstu时,给pstu赋予的值,值是什么就指向哪。

讲指针不得不说的两个运算符。取地址运算符&和取值运算符*.通过取地址运算符&可以获得某个变量的地址,用取值运算符可以获得某个地址中存放的数据。

指针变量使用前,先定义,给指针初始化以后,也就是赋值以后才能使用。在赋值时只能赋兼容类型的值。

例如:

#include

#include

void main()

{

int name,stuName=1;

int *pStu;

int *pNew;

pStu = &stuName;

pNew = pStu;

name = *pNew;

printf(“%dn%dn%dn%dnn”,stuName,*pStu,name,*pNew);

printf(“%dn%dn%dn%dnn”,&stuName,&pStu,&name,&pNew);

printf(“%dn%dn”,pStu,pNew);

}

从打印的值完全可以理解内存中存放的是什么。

简单修改:

#include

#include

void main()

{

int name,stuName=1;

int *pStu = NULL;

int *pNew = NULL;

pStu = &stuName;

pNew = *(&pStu);

name = *pNew;

*pStu =100;

printf(“%dn%dn%dn%dnn”,stuName,*pStu,name,*pNew);

printf(“%dn%dn%dn%dnn”,&stuName,&pStu,&name,&pNew);

printf(“%dn%dn”,pStu,pNew);

}

指针与整数的加法。主要用于数组中。

int arr []= {1,2,3,4,5};<罚www.2cto.com/kf/ware/vc/“ target=”_blank“ class=”keylink“>vcD4KPHA+aW50ICpwTmV3ID0gYXJyOzwvcD4KPHA+cE5ldyYjNDM7JiM0Mzs7PC9wPgo8cD5wTmV3ID0gcE5ldyAmIzQzOyAyOzwvcD4KPHA+yv3X6cP7vs3Kx7Xa0ru49sr91+nUqsvYtcS12Na3oaMgaW50ICpwTmV3ID0gJmFtcDsgYXJyWzBdOzwvcD4KPHA+cE5ldyA9IHBOZXcgJiM0MzsgNzsgcE5ld7XE1rjP8tLRvq3Uvb3no6y+38zl1rjP8rK71qq1wKOsv8nE3MrH0tG05tTatcS12Na3u/LOtNaqtdjWt6Os1NrKudPDJiMyMDU0MDvKx7vht6LJ+s601qq1xLTtzvOho9TayrnTw9a41euy2df3yrGjrNK7tqjSqtei0uLKx7fxs6yz9sHLyv3X6bXEtPPQoaGjPGJyPgo8L3A+CjxwPsn5w/fSu7j21rjV66Gj1rjV67Hkwb/Kx7Hkwb+hozwvcD4KPHA+yv3X6da41eujurrN1rjV67Hkwb/Tw7eou/mxvtK70fmhozwvcD4KPHA+1rjV68r91+mjutK7z7XB0Na4z/LNrNK7yv2+3cDg0M21xNa41eux5MG/tcS8r7rPo6yzxs6q1rjV68r91+mho9a41evK/dfptcTL+dPQ1KrL2La8ysfWuNXrseTBv6Gjy/zDx7HY0Ou+39PQz+DNrLXEtKK05sDg0M2jrLHY0OvWuM/yz+DNrLXEyv2+3cDg0M2hozwvcD4KPHA+wODQzcu1w/e3+yAgKsr91+nD+1vK/dfps6S2yF07PC9wPgo8cD7A/cjno7ppbnQgICAqYXJyWzVdOzwvcD4KPHA+Y2hhciAqc3RyW10gPSB7”Chain“,”Beijing“,”LongMai“};

-)常量指针(指向可以修改,指向对应的值不可以修改)

常量是形容词,指针是名词,以指针为中心的一个偏正结构短语,

这样看,常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针(变量)。

指针指向的对象是常量,那么这个对象不能被更改。

在C/C++中,常量指针是这样声明的:

1)const int *p;

2)int const *p;

常量指针的使用要注意,指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改,也就是说常量指针可以被赋值为变量的地址,之所以叫做常量指针,是限制了通过这个指针修改变量的值。

例如:

int a = 5,b=6;

const int *c = &a; // 这是合法的,非法的是对c的使用

c = &b; //合法

*c = 6; // 非法,但可以这样修改c指向的对象的值:a = 6;

const int *d = &b; // b是常量,d可以指向b,d被赋值为b的地址是合法的

二) 指针常量(指向不可以修改,指向对应的值可以修改)

指针是形容词,常量是名词。这回是以常量为中心的一个偏正结构短语。那么,指针常量的本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针。

指针常量的值是指针,这个值因为是常量,所以不能被赋值。

在C/C++中,指针常量这样声明:

int a;

int *const b = &a; //const放在指针声明操作符的右侧

只要const位于指针声明操作符右侧,就表明声明的对象是一个常量,且它的内容是一个指针,也就是一个地址。上面的声明可以这么读,声明了一个常量b,它的值是变量a的地址(变量a的地址,不就是指向变量a的指针吗)。

因为指针常量是一个常量,在声明的时候一定要给它赋初始值。一旦赋值,以后这个常量再也不能指向别的地址。

虽然指针常量的值不能变,可是它指向的对象是可变的,因为我们并没有限制它指向的对象是常量。

因此,有这么段程序:

char *a = ”abcde1234“;

char *b = ”bcde";

char *const c = &a;

下面的操作是可以的。

a[0] = 'x'; // 我们并没有限制a为常量指针(指向常量的指针)

或者

*c[0] = 'x' // 与上面的操作一致

三)指向常量的指针常量(指向不可以修改,指向对应的值也不可以修改)

顾名思议,指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。

因为是一个指针常量,那么它指向的对象当然是一个指针对象,而它又指向常量,说明它指向的对象不能变化。

在C/C++中,这么声明:

提高计算机专业C语言教学效果的方法探讨

c语言学习总结

计算机二级考试Java语言程序设计考点:标识符

C笔试题及答案

CNC系统巨量NC程序解释实现的方法

大学c语言学习心得体会

C语言数组基本概念理解

软件开发笔试题目

c语言函数知识点总结

小小的C语言问题指针数组赋值关于指针和数组。

C和指针 (pointers on C)――第十二章:使用结构和指针
《C和指针 (pointers on C)――第十二章:使用结构和指针.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

【C和指针 (pointers on C)――第十二章:使用结构和指针(共8篇)】相关文章:

安全员c考试试题及答案2022-04-29

c语言实践报告总结2023-03-20

c语言笔试题目及答案2023-06-22

c语言学习心得2023-07-20

C++基础教程数组2022-12-09

大学c语言学习心得体会感想2022-11-09

面试网络工程师的题目2022-09-08

羊城晚报校招笔试题2023-06-22

惯有嵌入式系统内存管理方案研究2023-07-08

全国计算机等级考试二级MSOffice高级应用考试大纲2022-10-13

点击下载本文文档