10深入理解C指针之---指针运算和比较
该系列文章源于《深入理解C指针》的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教。
指针运算有很多种,主要有指针的声明*、指针的解引*、指针指向(*).或->、指针+、指针-、指针==、指针!=、指针>、指针>=、指针<、指针<=、指针转换(数据类型)。
通过代码:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 char charVar; 6 short shortVar; 7 int intVar; 8 long longVar; 9 float floatVar; 10 double doubleVar; 11 12 printf("不同数据类型的长度如下:\n"); 13 printf("数据类型\t\t长度(字节)\n"); 14 printf("char\t\t\t %d\n", sizeof(charVar)); 15 printf("short\t\t\t %d\n", sizeof(shortVar)); 16 printf("int\t\t\t %d\n", sizeof(intVar)); 17 printf("long\t\t\t %d\n", sizeof(longVar)); 18 printf("float\t\t\t %d\n", sizeof(floatVar)); 19 printf("double\t\t\t %d\n", sizeof(doubleVar)); 20 21 return 0; 22 }
代码结果:
不同数据类型的长度如下: 数据类型 长度(字节) char 1 short 2 int 4 long 8 float 4 double 8
不同系统的基本数据类型可能稍微不同,请自己测试。知道自己系统的基本数据类型的大小之后,就可以继续学习下面的内容了,指针的声明和解引,前面已经学习过,下面主要进行其他部分。
一、指针指向->:用于访问结构指针引用的字段内容,是(*).的简化版本而已,
1、定义:可以通过指针方便快捷的访问结构的字段,而且书写更加简单方便,可以减少两次敲击键盘的次数
2、特征:
1)、使用前需要声明结构体
2)、使用前需要声明结构体指针
3)、可以使用->指针指向访问结构体指针的字段
4)、也可以使用(*).解引指针和成员运算符访问结构体指针的字段
3、应用:
1)、结构体的声明方式是非常多样化的,不同的声明方式,使用方式略有不同
2)、使用结构体指针需要先分配内存
3)、如果结构体中含有指针,需要二次分配内存
4)、如果结构体中含有指针,释放内存顺序与分配内存顺序完全相反
代码如下:代码很简单,仔细阅读即可:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 int main(int argc, char **argv) 6 { 7 //结构体的普通声明 8 struct _person{ 9 char* firstName; 10 char* lastName; 11 char* title; 12 int age; 13 }; 14 struct _person* person1; 15 person1 = (struct _person*)malloc(sizeof(struct _person)); 16 (*person1).firstName = (char*)malloc(sizeof(char) * 20); 17 strcpy((*person1).firstName, "zhang"); 18 (*person1).lastName = (char*)malloc(sizeof(char) * 30); 19 strcpy((*person1).lastName, "san"); 20 (*person1).title = (char*)malloc(sizeof(char) * 100); 21 strcpy((*person1).title, "A"); 22 (*person1).age = 29; 23 24 printf("The struct _person *person1 info:\n"); 25 printf("(*person1).firstName: %s\n", (*person1).firstName); 26 printf("(*person1).lastName: %s\n", (*person1).lastName); 27 printf("(*person1).title: %s\n", (*person1).title); 28 printf("(*person1).age: %d\n", (*person1).age); 29 30 free((*person1).firstName); 31 free((*person1).lastName); 32 free((*person1).title); 33 free(person1); 34 35 struct _person* person2; 36 person2 = (struct _person*)malloc(sizeof(struct _person)); 37 person2->firstName = (char*)malloc(sizeof(char) * 20); 38 strcpy(person2->firstName, "li"); 39 person2->lastName = (char*)malloc(sizeof(char) * 30); 40 strcpy(person2->lastName, "si"); 41 person2->title = (char*)malloc(sizeof(char) * 100); 42 strcpy(person2->title, "B"); 43 person2->age = 21; 44 45 printf("The struct _person *person2 info:\n"); 46 printf("person2->firstName: %s\n", person2->firstName); 47 printf("person2->lastName: %s\n", person2->lastName); 48 printf("person2->title: %s\n", person2->title); 49 printf("person2->age: %d\n", person2->age); 50 51 free(person2->firstName); 52 free(person2->lastName); 53 free(person2->title); 54 free(person2); 55 56 //结构体的高级声明,声明方式不一样,使用方式稍微有点不同 57 typedef struct _personNew{ 58 char* firstName; 59 char* lastName; 60 char* title; 61 int age; 62 } Person; 63 64 Person* person3; 65 person3 = (Person*)malloc(sizeof(Person)); 66 (*person3).firstName = (char*)malloc(sizeof(char) * 20); 67 strcpy((*person3).firstName, "wang"); 68 (*person3).lastName = (char*)malloc(sizeof(char) * 30); 69 strcpy((*person3).lastName, "wu"); 70 (*person3).title = (char*)malloc(sizeof(char) * 100); 71 strcpy((*person3).title, "C"); 72 (*person3).age = 29; 73 74 printf("The struct _person *person3 info:\n"); 75 printf("(*person3).firstName: %s\n", (*person3).firstName); 76 printf("(*person3).lastName: %s\n", (*person3).lastName); 77 printf("(*person3).title: %s\n", (*person3).title); 78 printf("(*person3).age: %d\n", (*person3).age); 79 80 free((*person3).firstName); 81 free((*person3).lastName); 82 free((*person3).title); 83 free(person3); 84 85 Person* person4; 86 person4 = (Person*)malloc(sizeof(Person)); 87 person4->firstName = (char*)malloc(sizeof(char) * 20); 88 strcpy(person4->firstName, "zhao"); 89 person4->lastName = (char*)malloc(sizeof(char) * 30); 90 strcpy(person4->lastName, "liu"); 91 person4->title = (char*)malloc(sizeof(char) * 100); 92 strcpy(person4->title, "D"); 93 person4->age = 21; 94 95 printf("The struct _person *person4 info:\n"); 96 printf("person4->firstName: %s\n", person4->firstName); 97 printf("person4->lastName: %s\n", person4->lastName); 98 printf("person4->title: %s\n", person4->title); 99 printf("person4->age: %d\n", person4->age); 100 101 free(person4->firstName); 102 free(person4->lastName); 103 free(person4->title); 104 free(person4); 105 106 typedef struct _personNewN{ 107 char* firstName; 108 char* lastName; 109 char* title; 110 int age; 111 } *PersonN; 112 113 PersonN person5; 114 person5 = (PersonN)malloc(sizeof(PersonN)); 115 (*person5).firstName = (char*)malloc(sizeof(char) * 20); 116 strcpy((*person5).firstName, "zhou"); 117 (*person5).lastName = (char*)malloc(sizeof(char) * 30); 118 strcpy((*person5).lastName, "qi"); 119 (*person5).title = (char*)malloc(sizeof(char) * 100); 120 strcpy((*person5).title, "E"); 121 (*person5).age = 29; 122 123 printf("The struct _person *person5 info:\n"); 124 printf("(*person5).firstName: %s\n", (*person5).firstName); 125 printf("(*person5).lastName: %s\n", (*person5).lastName); 126 printf("(*person5).title: %s\n", (*person5).title); 127 printf("(*person5).age: %d\n", (*person5).age); 128 129 free((*person5).firstName); 130 free((*person5).lastName); 131 free((*person5).title); 132 free(person5); 133 134 PersonN person6; 135 person6 = (PersonN)malloc(sizeof(PersonN)); 136 person6->firstName = (char*)malloc(sizeof(char) * 20); 137 strcpy(person6->firstName, "wu"); 138 person6->lastName = (char*)malloc(sizeof(char) * 30); 139 strcpy(person6->lastName, "ba"); 140 person6->title = (char*)malloc(sizeof(char) * 100); 141 strcpy(person6->title, "F"); 142 person6->age = 21; 143 144 printf("The struct _person *person6 info:\n"); 145 printf("person6->firstName: %s\n", person6->firstName); 146 printf("person6->lastName: %s\n", person6->lastName); 147 printf("person6->title: %s\n", person6->title); 148 printf("person6->age: %d\n", person6->age); 149 150 free(person6->firstName); 151 free(person6->lastName); 152 free(person6->title); 153 free(person6); 154 155 return 0; 156 } ~
代码结果:
The struct _person *person1 info: (*person1).firstName: zhang (*person1).lastName: san (*person1).title: A (*person1).age: 29 The struct _person *person2 info: person2->firstName: li person2->lastName: si person2->title: B person2->age: 21 The struct _person *person3 info: (*person3).firstName: wang (*person3).lastName: wu (*person3).title: C (*person3).age: 29 The struct _person *person4 info: person4->firstName: zhao person4->lastName: liu person4->title: D person4->age: 21 The struct _person *person5 info: (*person5).firstName: zhou (*person5).lastName: qi (*person5).title: E (*person5).age: 29 The struct _person *person6 info: person6->firstName: wu person6->lastName: ba person6->title: F person6->age: 21
通过以上代码,相比阅读者对数据结构有了比较深刻的认识吧。有人可能会想到鲁迅笔下的孔乙己吧,这种做法会不会有茴香豆的茴字有四种写法的卖弄,如果这样想就错了,编程过程中,会碰到各种奇怪的应用场景,每一种用法都要学习点,以备不时之需吧。代码阅读完毕了,相比读者对使用->指针指向访问结构体指针的字段和使用(*).解引指针和成员运算符访问结构体指针的字段有了比较深入的理解了。
二、指针+和指针-:用于访问数组下表对应的内容,
1、定义:可以通过对指针进行简单的加减法,这点同普通变量一样,但是计算机的体现又是不一样的
2、特征:
1)、指针+和指针-的大小与加减的数值有关
2)、指针+和指针-的大小与指针的数据类型有关
3)、指针+和指针-的最终大小就是加减的数值与数据类型的大小的乘积
4)、不同的指针的指针+和指针-的大小是复杂的,要特别注意
5)、void类型的指针最好不要作加减操作
3、应用:
见如下代码:
代码如下:
1 #include <stdio.h>
2
3 int main(int argc, char **argv)
4 {
5 int iArray[] = {28, 32, 89, 77};
6 int *ptrArray = iArray;
7
8 //普通数组的访问
9 printf("The iArray:\n");
10 for(int i = 0; i < 4; i++){
11 printf("%d\t", iArray[i]);
12 }
13 printf("\n");
14
15 //普通数组的特殊访问
16 printf("The Other iArray:\n");
17 for(int i = 0; i < 4; i++){
18 printf("%d\t", i[iArray]);
19 }
20 printf("\n");
21
22 //普通数组的指针访问
23 printf("The Pointer+ iArray:\n");
24 for(int i = 0; i < 4; i++){
25 printf("%d\t", *ptrArray);
26 ptrArray += 1;
27 }
28 printf("\n");
29
30 printf("The Pointer- iArray:\n");
31 for(int i = 0; i < 4; i++){
32 ptrArray -= 1;
33 printf("%d\t", *ptrArray);
34 }
35 printf("\n");
36
37 return 0;
38 }
代码结果:
The iArray:
28 32 89 77
The Other iArray:
28 32 89 77
The Pointer+ iArray:
28 32 89 77
The Pointer- iArray:
77 89 32 28
代码中的26行使用了指针+操作,32行使用了指针-操作,由于指针是int型,因此,指针每增加或减少1,地址都会增加或减少整型数据的长度4。将指针值打印出来,在25行和33行下面增加如下:
printf("%p\t", ptrArray);
则代码结果为:
The iArray: 28 32 89 77 The Other iArray: 28 32 89 77 The Pointer+ iArray: 28 0x7ffd8b190ed0 32 0x7ffd8b190ed4 89 0x7ffd8b190ed8 77 0x7ffd8b190edc The Pointer- iArray: 77 0x7ffd8b190edc 89 0x7ffd8b190ed8 32 0x7ffd8b190ed4 28 0x7ffd8b190ed0
三、指针相减和指针比较:主要是方便定位两个指针对应的数组元素的先后顺序,
1、定义:可以通过对指针进行简单的加减法,这点同普通变量一样,但是计算机的体现又是不一样的
2、特征:
1)、指针 - 指针的结果是两个地址的差值,利用该差值可以很容易判别数组中的元素的顺序
2)、指针+和指针-的大小与指针的数据类型有关
3)、指针与指针的比较确定指针对应数组元素的相对顺序
4)、指针相减的结果大于0表示前者指针的值大于后者指针
5)、指针比较的结果1为真,0为假
3、应用:
见如下代码:
代码如下:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 int iArray[] = {28, 32, 89, 77,}; 6 int *ptr0Array = iArray; 7 int *ptr1Array = iArray + 1; 8 int *ptr2Array = iArray + 2; 9 int *ptr3Array = iArray + 3; 10 11 printf("指针减法演示:\n"); 12 printf("ptr3Array - ptr1Array: %d\n", ptr3Array - ptr1Array); 13 printf("ptr1Array - ptr3Array: %d\n", ptr1Array - ptr3Array); 14 15 printf("指针比较演示:\n"); 16 printf("ptr3Array > ptr1Array: %d\n", ptr3Array > ptr1Array); 17 printf("ptr1Array > ptr3Array: %d\n", ptr1Array > ptr3Array); 18 19 return 0; 20 }
代码结果:
指针减法演示: ptr3Array - ptr1Array: 2 ptr1Array - ptr3Array: -2 指针比较演示: ptr3Array > ptr1Array: 1 ptr1Array > ptr3Array: 0
代码比较简单,就不再啰嗦了。