3.预备知识【郝斌数据结构】

预备知识

1.指针

1) 指针的重要性:指针是C语言的灵魂

2)定义

   地址:内存单元的编号,从0开始非负整数。范围:0-FFFFFFFF(0-4G-1)

   指针:指针就是地址,地址就是指针

      指针变量是存放内存单元地址的变量

      指针的本质是一个操作受限的非负整数

例题:

 1 # include <stdio.h>
 2 int main(void)
 3 {
 4     int * p;//p是个指针变量,int * 表示该p变量只能存储int类型变量的地址
 5     int i = 10;
 6     int j;
 7     p = &i;
 8     j = *p;
 9     printf("%d\n", j); //j = *p;  <=> j = i        
10     return 0;
11 }
12 /*
13     在vc++6.0中的输出结果:
14 */

  如何通过被调函数修改主调函数中普通变量的值

  I实参为相关变量的地址

  II形参为以该变量的类型为类型的指针变量

  III在被调函数中通过 *形参变量名 的方式就可以修改主调函数中的变量

例题:

 1 # include <stdio.h>
 2 void f(int i)
 3 {
 4     i = 100;
 5 }
 6 int main(void)
 7 {
 8     int i = 9;
 9     f(i);
10     printf("i=%d\n", i);
11 }
12 /*
13     在vc++6.0中的输出结果:i=9
14 */

例题:

 1 # include <stdio.h>
 2 void f(int * p)
 3 {
 4     *p = 100;//*p = i
 5 }
 6 int main(void)
 7 {
 8     int i = 9;
 9     f(&i);
10     printf("i=%d\n", i);
11 }
12 /*
13     在vc++6.0中的输出结果:i=100
14 */

例题:

 1 # include <stdio.h>
 2 void f(int **);
 3 int main(void)
 4 {
 5     int i=9;
 6     int *p = &i;
 7     printf("%p\n", p);
 8     f(&p);
 9     printf("%p\n", p);
10     return 0;
11 }
12 void f(int ** q)
13 {
14     *q = (int *)0xFFFFFFFF;
15 }
16 /*
17     在vc++6.0中的输出结果:0061FF2C
18                            FFFFFFFF
19 */

总结:要想改变主调函数中某个变量的值,就必须要将变量地址发送给被调函数。

例题:主调函数调用被调函数来修改主调函数中数组中的内容

 1 # include <stdio.h>
 2 void Show_Array(int * p, int len)
 3 {
 4     p[0] = -1;//p[0] == *p
 5     p[2] = -2;//p[2] == *(p+2) == *(a+2)
 6     //p[i]就是主函数的a[i]
 7 }
 8 int main(void)
 9 {
10     int a[5] = {1, 2, 3, 4, 5};
11     printf("a[3]=%d, *(a+3)=%d\n", a[3], *(a+3));
12     Show_Array(a, 5);//a等价于&a[0], &a[0]本身就是int * 类型    
13     printf("%d\n", a[0]);
14     printf("%d\n", a[2]);
15     return 0;
16 }

如何通过被调函数修改主调函数中一维数组的内容

两个参数:存放数组元素的指针变量,存放数组元素长度的整形变量

2.结构体

  (1)为什么会出现结构体

    为了表示一些复杂的数据,而普通的基本类型变量无法满足要求。

  (2)如何使用结构体

    结构体是用户根据实际需要自己定义的复合数据类型。

  (3)注意事项

  结构体变量不能加减乘除,但可以相互赋值

  结构体变量和结构体指针变量作为函数参数传递的问题

例题:通过变量名.结构体成员访问

 1 # include <stdio.h>
 2 # include <string.h>
 3 //结构体定义了数据类型,数据类型是struct Student, sid name age是结构体成员
 4 struct Student
 5 {
 6     int sid;
 7     char name[200];
 8     int age;    
 9 };//分号不能省略
10 int main(void)
11 {
12     //整体赋值
13     struct Student st = {1000, "zhangsan", 20};
14     printf("%d %s %d\n",st.sid ,st.name , st.age);    
15     //单个赋值
16     st.sid = 99;
17     strcpy(st.name, "lishi");
18     st.age = 20;
19     printf("%d %s %d\n",st.sid ,st.name , st.age);
20     return 0;
21 }

例题:通过结构体指针变量->结构体成员变量的方式访问

 1 # include <stdio.h>
 2 # include <string.h>
 3 # include <malloc.h>
 4 //结构体定义了数据类型,数据类型是struct Student, sid name age是结构体成员
 5 struct Student
 6 {
 7     int sid;
 8     char name[200];
 9     int age;    
10 };//分号不能省略
11 int main(void)
12 {
13     struct Student st = {1000, "wangwu", 30};
14     struct Student * pst;
15     pst = &st;
16     pst->sid = 99;//pst->sid <=> (*pst).sid <=> st.sid
17     strcpy(pst->name, "zhaoliu") ;
18     pst->age = 35;
19     printf("%d %s %d", pst->sid, pst->name , pst->age);
20     return 0;
21 }

规定:pst->sid <=> (*pst).sid <=> st.sid

   pst所指向的结构体变量中的sid这个成员

例题:

 

# include <stdio.h>
# include <string.h>
struct Student
{
    int sid;
    char name[200];
    int age;
};
void f(struct Student * );
void g(struct Student );
int main(void)
{
    struct Student st;//变量声明没有初始化,里面的值还是垃圾值
    f(&st);
    g(st);

    return 0;
}
void f(struct Student * pst)
{
    pst->sid = 2004;//(*pst).sid
    strcpy(pst->name, "黑神悟空2004");
    pst->age = 500;
}
//这种方式耗内存、耗时间 不推荐
void g(struct Student st)
{
    printf("%d %s %d", st.sid, st.name, st.age);    
}

 

改良程序:

 

# include <stdio.h>
# include <string.h>
struct Student
{
    int sid;
    char name[200];
    int age;
};
void f(struct Student * );
void g(struct Student *);
int main(void)
{
    struct Student st;//变量声明没有初始化,里面的值还是垃圾值
    f(&st);
    g(&st);

    return 0;
}
void f(struct Student * pst)
{
    pst->sid = 2004;//(*pst).sid
    strcpy(pst->name, "黑神话悟空");
    pst->age = 500;
}
//这种方式耗内存、耗时间 不推荐
void g(struct Student * pst)
{
    printf("%d %s %d", pst->sid, pst->name, pst->age);    
}

 

 

 

 

3.动态内存的分配和释放

 

# include <stdio.h>
# include <malloc.h>
int main(void)
{
    //定义静态数组
    int a[5] = {4, 10, 2, 8, 6};
    //动态分配内存
    int len;
    printf("请输入需要分配的数组的长度:len=");
    scanf("%d", &len);
    int * pArr = (int *)malloc(len * sizeof(int));
    //malloc函数只能返回第一个字节的地址,此时地址没有实际意义,要进行强制转换(int*)
    *pArr = 4; //pArr[0] = 4
    *(pArr+1) = 10;//pArr[1] = 10
    *(pArr+2) = 2;//pArr[2] = 2
    *(pArr+3) = 8;//pArr[3] = 8
    *(pArr+4) = 6;//pArr[4] = 6
    //我们可以把PArr当做一个普通数组来使用
    for (int i=0; i<len; ++i)
    {
        scanf("%d", &pArr[i]);    
    }    
    for (int i=0; i<len; i++)
    {
        printf("%d ", *(pArr+i));
    }
    free(pArr);
    //把pArr指向的动态分配的20个字节的内存释放
    return 0;
}

 

4.跨函数使用内存实例

 

 

# include <stdio.h>
# include <malloc.h>
struct Student
{
    int sid;
    int age;
};
struct Student * CreateStudent(void);
void ShowStudent(struct Student * );
//函数声明是用";"结束
int main(void)
{
    struct Student * ps;
    ps = CreateStudent();
    ShowStudent(ps);
    return 0;
}
//定义CreateStudent()函数,返回值类型为struct Student * 类型
struct Student * CreateStudent(void)
{
    struct Student * p = (struct Student *)malloc(sizeof(struct Student));
    p->sid = 99;
    p->age = 100;
    return p;
};
void ShowStudent(struct Student * pst)
{
    printf("%d %d\n",pst->sid, pst->age);
}

 

posted @ 2024-08-24 09:29  java帝国  阅读(8)  评论(0)    收藏  举报