指针和结构体知识学习

这一周主要学习了C语言中的最灵活的技巧 --指针。指针也是一个变量,它有自己的地址也有指向的地址,一般来说我们更关注的是指针指向的地址。指针的指向可以是整数、浮点数、字符、数组,同样的也可以是一个函数。

指针的基本操作有赋值、求值、取指针地址、将一个整数指针加给指针,增加指针的值、减小指针的值和求差值。如下程序所示:

 1 /*ptr_ops.c - 指针操作*/
 2 #include <stdio.h>
 3 int main()
 4 {
 5    int urn[5] = {100, 200, 300, 400, 500};
 6    int * ptr1, * ptr2, * ptr3;
 7    ptr1 = urn;           /*把一个地址赋给指针*/
 8    ptr2 = &urn[2];      /*把一个地址赋给指针,取得指针指向的值,并且取得指针的地址*/
 9    printf("pointer value , dereferenced pointer , pointer address : \n");
10    printf("ptr1 = 0x%x, *ptr1 = %d, &ptr1 = 0x%x",ptr1, *ptr1, &ptr1);
11    printf("\nurn = 0x%x\n",urn);
12    printf("\nurn[0] = 0x%x\n",urn[0]);
13    /*指针加法*/
14    ptr3 = ptr1 + 4;
15    printf("\nadding an int to pointer:\n");
16    printf("ptr1 +4 = 0x%x,*(ptr1 + 3)= %d\n",ptr1 + 4,*(ptr1 + 3));
17    ptr1++;         /*递增指针*/
18    printf("\nvalues after ptr1++\n");
19    printf("ptr1 = 0x%x,*ptr1 = %d,&ptr1 = 0x%x\n",ptr1,*ptr1,&ptr1);
20    ptr2--;        /*递减指针*/
21    printf("\nvaluse after --ptr2\n");
22    printf("ptr2 = 0x%x,*ptr2 = %d,&ptr2 = 0x%x\n",ptr2,*ptr2,&ptr2);
23    --ptr1;         /*恢复为初始值*/
24    ++ptr2;        /*恢复为初始值*/
25    printf("\nPointers reset to original values :\n");
26    printf("ptr1 = 0x%x,ptr2 = 0x%x\n",ptr1,ptr2);
27              /*一个指针减去另一个指针*/
28    printf("ubtracting one pointer from another :\n");
29    printf("ptr2 = 0x%x,ptr1 = 0x%x,ptr2 - ptr1 = %d\n",ptr2,ptr1,ptr2 -ptr1);
30              /*一个指针减去一个整数*/
31    printf("\nsubtracting an int from a pointer : \n");
32    printf("ptr3 = 0x%x,ptr3 - 2 = 0x%x\n",ptr3,ptr3 - 2);
33    return 0;
34
35 }

赋值:可以把一个地址赋值被指针,如果是数组的话可以直接进行赋值,如果是整数、浮点数或者字符等要用地址运算符&来进行赋值。在赋值的时候一定要注意变量的类型要与指针的类型匹配,比如int类型的地址要赋给一个指向int的指针。

取指针地址:上边程序中&ptr1指的就是ptr1这个指针变量的地址,而不是指针变量指向的地址。

将一个整数加给指针:这个整数将会和这个指针所指类型的字节相乘,。然后所得的结果会加到初始地址上。例如:ptr1 + 4的结果就等同于&urn[4].

增加指针的值:与我们的自加运算类似,对指向某数组元素的指针做累加运算,让指针指向该数组的下一个元素。例如ptr1++使ptr1指向urn[1],但是ptr1这个指针自己的地址没有变,改变的是指向的地址。

从指针中减去一个整数:与上边将一个整数加到指针上类似,比如ptr3-2的结果就等同于&urn[2],因为ptr3是指向&urn[4]的。

减小指针的值:与增加指针的值类似。

求差值:求差值通过计算出同一数组中两个指针的差来计算两个元素之间的距离,比如:ptr2-ptr1的值为2,代表两个指针所指元素之间距离为两个int数值大小。

比较:可以用与关系运算符比较两个指针的值,但是两个指针类型必须一致。

这些基础的东西一定要熟练才能更好的运用。在指针知识刚开始学习的时候搞不懂指针的地址和指针指向的地址,还有就是指针的值为问题,后来经过编程调试发现这些基本的东西就是定义,要记牢、会运用就可以了。

在后来一章C语言的高级技术中讲到了结构体的知识,这一块在举例的时候举到了链表操作,删除结点,查找结点,插入结点等。看了程序之后了解了链表的流程之后,我觉得链表就是指针和结构体的综合运用。链表中每个结点都是一个结构体,里边包括的就是这个结点的值和一个指针,这个指针指向的是下一个结点的地址。我觉得了解到这一点之后对于链表的操作就会好理解一点。

 1 /*插入结点操作
 2 *先判断链是否是空链表。
 3 *新建一个结点,将结点结构中结点值的指针指向要插入的结点的值。
 4 *如果不是找到链表中的空结点。空结点的前一个结点中指向下一个结点的指针指向新结点。
 5 *如果是空链表,直接把新结点当作链表的链表头
 6 */
 7
 8 int insert(int val)
 9 {
10    Node p,q;   /*定义两个结点p和q*/
11    p = head;
12    if(p != NULL){     /*寻找适当的插入位置*/
13        while(p->next != NULL){  /*循环结束时p的下一个结点恰好是一个空结点*/
14            p = p->next;
15        }
16    }
17    q = (Node)malloc(sizeof(struct node)); /*创建一个新结点*/
18    if(q == NULL)
19       return -1;
20    q->next = NULL;                        /* 对新结点进行赋值*/
21    q->val = val;
22    if(p == NULL){ //如果链表是一个空链表的话,将要插入的链表作为链表头
23       head = q;
24       return 1;
25    }
26    p->next = q;
27    return 1;
28 }
29 //删除结点操作
30 int del(int val, Node * res)
31 {
32     Node p, q;
33     p = head;
34     if(p == NULL);
35       return -1;
36     if(p->val == val)
37      {
38          *res = p;
39          head = p->next;//将要删除结点中指向下一个结点的指针赋给链表头,删除这个结点
40          return 1;
41      }else if(p->next == NULL)//链表中只有一个结点的,并且不是我们要删除的结点,返回-1
42         return -1;
43     q = p;
44     p = p->next;
45     while(p !=NULL)
46     {
47         if(p->val != val){   //找到要删除的结点,将要删除的结点赋值给p,将要删除的结点的前一个结点赋值给q
48            q = p;
49            p = p->next;
50           }else{
51              q->next = p->next;  //删除结点,将要删除的结点的前一个结点直接指向要删除结点的后一个结点,等于删除了这个结点
52              p->next = NULL;     //删除的结点依旧存在,但是不在这个链表中,作为一个单独的结点,指向空结点
53              *res = p;
54              return 1;
55           }
56    }
57    return -1;
58 }
59 //遍历链表,打印每个结点的值
60 void print()
61 {
62     Node p = head;
63     while(p != NULL){
64       printf("%d\n",p->val);
65       p = p->next;
66     }
67 }
68 //遍历链表,释放每一个结点
69 void destory()
70 {
71     Node p = head;
72     while(p != NULL){
73       Node q;
74       q = p;
75       p = p->next;
76       free(q);
77 }
78      head = NULL;
79 }

上边分别是插入结点,删除结点,打印链表和释放每一个结点。之前我理解了链表的本质就是一个结构体,其中存放链表的值和指向下一个结点的指针。因此要想插入一个结点的思想应该是找到要插入的位置,比如是a,b两个结点之间。首先要将a中指向下一个结点的指针赋给要插入的结点中的指针,让要插入的指针指向b,然后修改a中指针的值,指向要插入的结点的地址。上边举例的程序中写的是插入指针在空白的地方,其实要想插入到某一个数值的前边和后边思想都是一致的,先找到要插入的位置,然后去修改指针就可以。同样的要想删除一个结点只需要把这个结点前一个结点的指针指向这个结点后一个结点,然后将删除的结点的指针指向空地址就可以了。

看完链表操作之后,我对于链表有了具体的了解,之前只是知道有链表这个东西,但是链表究竟是什么样的格式,怎么样操作并不知道。看完链表之后,我也进行了思考,链表中是每一个结点中有一个指针,那如果一个结点中有两个指针,分别指向两个地址,应该就是人们说的二叉树了吧。想到了这个东西但是还没有去实践,下一周有时间的话,可以去写一下这个程序试试看。

这是第二周的学习了,第二周的学习有一个感悟就是学代码不能仅仅局限在书中,要学会思考,在实践的基础上思考,再用实践去检验自己思考的结果。书毕竟篇幅有限,不可能所有的东西面面俱到,看懂书上的例子的同时要多问几个如果,如果修改一下会是什么样的结果。慢慢的学习过程中不仅要每天敲代码,而且要慢慢的敲自己代码,不能跟着别人的思路走,要把自己的思路用代码表现出来,然后再对比进行优化,从不敲代码到敲代码是开始阶段,从敲代码到敲自己的代码是提升阶段,慢慢的要开始提高自己代码的质量。

				
时间: 2024-10-20 18:51:52

指针和结构体知识学习的相关文章

结构体知识梳理4-浅拷贝深拷贝

应用场景分析,我们希望对一个学生的信息做备份 代码一 typedef struct student{ int num; int age; char name[10]; }s_stu,*p_stu; //stu1 stu2 有独立的内存空间,存储 num age name s_stu stu1; s_stu stu2; stu1.num = 1; stu1.age = 1; strcpy(stu1.name,"lilei"); //以下做的是memcpy(&stu2,&s

【阅读笔记】《C程序员 从校园到职场》第七章 指针和结构体

原文地址:让你提前认识软件开发(13):指针及结构体的使用 CSDN博客 https://blog.csdn.net/zhouzhaoxiong1227/article/details/23872995 [文章摘要] 指针在C语言中占有很重要的地位,同时也是学习C语言的难点所在.结构体属于用户自己建立的数据类型,在实际的软件开发项目中应用很广泛. 本文以实际的例子介绍了C语言中指针和结构体的使用方法,为进一步的学习和应用提供了有益的参考. [关键词] C语言 指针  结构体 文件 1.指针和结构

C语言--- 高级指针2(结构体指针,数组作为函数参数)

一.结构体指针 1. 什么是结构体指针?指向结构体变量的指针     结构体:     typedef  struct stu{                          char name[20];                          char sex;                          int age;                    }Student;     Student stu1 = {"zhangsan",'m',23};  

一维数组,二维数组,三维数组,数组与指针,结构体数组,通过改变指针类型改变访问数组的方式

 打印数组中的每个元素,打印每个元素的地址: #include <stdio.h> #include <stdlib.h> void main(void) { int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for (int *p = a; p < a + 10;p++)  //指针类型决定4个字节 { printf("\n%p,%d", p, *p); } getchar(); } 指针数组 #inclu

指针、结构体

指针的应用,根据数据可分为变量和常量占有一定数目连续的储存单位,以首地址作称为数据的地址.变量的地址称为指针,存放地址的变量称为指针变量.指针也是一种变量,也占有储存单位 特殊之处在于它存放是另一个变量所占存储单位的起始地址. 定义初始化  intx=10 ,*p=&x,反之错误对于复杂形式的指针的判断,找到标示符,由关键字向右看遇到)就向左...遇到( 就是函数.int (*p ) [3] ;  double * p [5] ;    int *p ( float a);    指向数组的整形

[转]C语言指针 之 结构体指针

在C语言中几乎可以创建指向任何类型的指针,包括用户自定义的类型.创建结构体指针是极常见的.下面是一个例子: 1 typedef struct 2 { 3 char name[21]; 4 char city[21]; 5 char state[3]; 6 } Rec; 7 typedef Rec *RecPointer; 8 9 RecPointer r; 10 r=(RecPointer)malloc(sizeof(Rec)); r是一个指向结构体的指针.请注意,因为r是一个指针,所以像其他指

结构体指针和结构体成员指针

在添加sqlite3的加解密功能函数时,由于网上资料针对的版本是旧版sqlite3源码,现在新版上做修改遇到了一个宏,该宏是旧版上的,它作用是由结构体成员指针pData找到它所属的结构体指针.下面转的文章详解了这种机制. 1.通过结构体成员指针寻找其所属结构体指针 转自http://blog.csdn.net/mycwq/article/details/9327743 宏CONTAINING_RECORD,可以直接根据结构体成员指针找到结构体指针. 我们看一下它的定义: 1 #define CO

Visual Studio 调试中将结构体指针转换为结构体数组查看

Visual Studio 调试中将结构体指针转换为结构体数组查看 1. 首先,我们在调试过程中,发现一个指针,无法显示其数组形式,很难受... 2. 将其添加到"监视"窗口 3. 修改监视的值,后面加上查看的索引个数 4. 其转化为数组 原文地址:https://www.cnblogs.com/onetrainee/p/12232646.html

C和指针之结构体和联合体

1.结构体基础知识 聚合数据类型(aggregate data type)能够同时存储超过一个的单独数据.C语言提供了两种类型的聚合数据结构,数组和结构体. 数组是相同类型的数据元素的集合,它的每个元素都是通过下标引用或者指针间接访问来选择的:结构也是一些值的集合,这些值称为它的成员(member),结构体的每个成员可以是不同类型的数据,要访问结构体中的数据,是通过成员名来访问的. 结构变量属于标量类型,所以你可以像对待其他标量类型一样执行相同类型的操作.结构体可以作为传递给函数的参数,也可以作