指针和结构体知识学习

这一周主要学习了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中指针的值,指向要插入的结点的地址。上边举例的程序中写的是插入指针在空白的地方,其实要想插入到某一个数值的前边和后边思想都是一致的,先找到要插入的位置,然后去修改指针就可以。同样的要想删除一个结点只需要把这个结点前一个结点的指针指向这个结点后一个结点,然后将删除的结点的指针指向空地址就可以了。

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

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

				



				
时间: 12-04

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

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

数据结构复习之C语言指针与结构体

数据结构指针复习: #include <stdio.h> void main() { int a[5] = {8, 2, 3, 4, 5}; // a[3] == *(3+a) printf("%d\n", *(3+a)); // a[3] 4 printf("*a其实就是a[0]: %d\n", *a); // 8 // 地址是连续的 printf("%p\n", a+1); printf("%p\n", a+2

STM32——C语言知识点:指针、结构体

1 /* 2 ============================================================================ 3 Name : Cyuyanfuxi.c 4 Author : 5 Version : 6 Copyright : Your copyright notice 7 Description : Hello World in C, Ansi-style 8 ======================================

Delphi调用API时到底应该是指针还是结构体?

看MSDN,GetWindowRect的说明如下: BOOL WINAPI GetWindowRect( _In_  HWND   hWnd, _Out_ LPRECT lpRect ); 但是实际调用直接传递结构体,而不是指针: procedure TWinControl.UpdateBounds; var ParentHandle: HWnd; Rect: TRect; WindowPlacement: TWindowPlacement; begin // 非最小化状态下,取得Win控件显示

指向结构体变量的指针引用结构体变量的成员

#define _CRT_SECURE_NO_WARNINGS 1 #include<string> #include<iostream> using namespace std; struct Student { int num; string name; char sex; float score; }; int main() { Student stu; Student *p = &stu; stu.num = 10301; stu.name = "Wang

C编译器剖析_1.5 结合C语言来学汇编_指针、数组和结构体

让我们再来看一份C代码,及其经UCC编译器编译后产生的主要汇编代码,如图1.33所示,其中包含了数组.指针和结构体. 图1.33 数组.指针和结构体 按照C的语义,图1.33第9行的C代码是对局部数组number的初始化,需要把number[0]初始化为2015,而数组中的其他元素皆被初始化为0.UCC编译器采取的翻译方法是:先调用memset函数来把数组number所占的内存空间清0,然后再把number[0]设为2015,如图1.33的第17至24行所示.C库函数memset的API如下所示

结构体指针

结构体与指针 1.结构体指针的数值为某个结构体的内存空间的地址,从而指针指向某个结构体. 2.结构体指针的初始值为空(0),不指向任何结构体. 3.malloc操作:创建一个新的内存空间(从内存中选择一个内存空间存储结构体),p指向这个结构体,p的值为这个结构体的内存空间的地址. 4.结构体指针的赋值:一个结构体指针的数值等于另外一个结构体指针的数值,从而两个结构体指针指向相同的结构体.当对某个结构体进行访问时,选择的结构体指针只要满足该结构体指针指向这个结构体即可,即可以有很多种选择. 5.当

结构体学习心得

结构体 1.简单认识结构体 #include<stdio.h> /*struct tag(member list)(varible list)*/ 成员列表     变量列表 struct stu { char name[20]; int age; char sex[5]; char tele[12]; char addr[30]; }; int main() { struct stu stu2; struct stu arr[10]; return 0; } 2.结构体的重命名 ①.type