[郝斌]数据结构C语言—前导知识

数据结构学习C语言前导知识

指针:C语言的灵魂

  1. 内存被释放的意思是说,操作系统回收了对一个变量所分配内存的控制权限,但是保存其中的垃圾数据依旧在保存着,不会清空遗留下的数据。所以任何变量要初始化后才能使用,否则里面可能存放着之前的垃圾数据。

  2. 内存是多字节组成的线性一维存储空间。内存的基本划分单位是字节。每个字节含有8位。每一位存放1个0或1个1,字节和编号是一一对应的。每个字节都有一个唯一确定的编号,一个编号对应一个字节。这个编号也叫地址。一个系统所能管理的内存空间的大小取决于参与编号的二进制位数,而二进制位数由地址总线位数决定。

  3. 指针初始化:

    int i = 10; 
    int *p = &i; 

    p指向i,改变p的值不影响i的值,改变i的值不影响p的值;*p与 i完全等价。常量和表达式之前不能加取地址&

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

  • 实参为相关变量的地址

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

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

#include <stdio.h>  
int f(int * p)
{
    *p = 100;
}
​
int main()
{
    int i = 9;
    f(&i);
    printf("%d\n", i);
    return 0;
}

指针和一维数组

  1. 数组名

    一维数组名是个指针常量,它存放的是一维数组第一个元素的地址,它的值不能改变,一维数组名指向的是数组的第一个元素

  2. 下标和指针的关系:

    a[ i ] 等价于* (a+i),a[3]在汇编语言中也可以写成3[a]。

    假设指针变量的名字为p,则p + i的值是p + i *(p所指向的变量所占的字节数)

  3. 指针变量的运算: 指针变量不能相加,不能相乘,不能相除,如果两个指针变量属于同一数组,则可以相减。指针变量可以加减一个整数,前提是最终结果不能超过指针允许指向的范围。

    p++ 等价于p+1

  4. 使用 %p 打印地址,按照16进制形式打印指针地址,32位编译器下会打印16进制的21位地址,64位编译器下会打印16进制的32位地址。

  5. 如何使用被调函数修改主调函数中一维数组的内容:通过①存在数组首元素的指针变量。②存放数据元素长度的整型变量。

指针的大小

指针变量,无论它指向的变量占几个字节,该指针变量本身只占四个字节。以32位地址空间为例,32根地址总线,每个字节表示8位,因此有4字节。一个变量的地址使用该变量首字节的地址来表示。

至于如何通过指针取对应类型的数字,看这个指针是什么类型,例如如果是(char *),会往后取一个字节,如果是(double * )指向前八个字节。但是指针变量本身只占4个字节。

char数组赋值问题

遇到一个对char数组赋值的问题,对字符数组赋值只有三个方式

  1. 在定义的时候直接用字符串赋值:

    char a[10]="hello";

    绝对不能先定义再给它赋值,如下这样是错误的。

    char a[10];   
    a[10]="hello"; 

  2. 对数组中字符逐个赋值,字符串可以赋值给字符指针变量,或者将字符串用字符数组保存。

    char a[10]={'h','e','l','l','o'};
    
  3. 函数把 src 所指向的字符串复制到 dest,例如

    char *strcpy(char *dest, const char *src);
    ​
    char src[40];
    strcpy(src, "This is runoob.com");
    

使用这个函数在VS2005以上版本(VS2005、VS2008、VS2010)下编译需要在开头添加

#define _CRT_SECURE_NO_WARNINGS

结构体的使用

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

普通结构体变量和结构体指针变量作为函数传参的问题,与通过指针被调函数修改主调函数的值的方式相同。(*和&)

使用结构体的两种方式:

struct student
{   int sid;
    char name[200];
    double age;
};  
​
struct student std;     
struct student *pstd = &std;
std.age = 10;    //方式①
pstd->age = 30;//方式②,pstd->age等价于(*pstd).age

内存的动态分配和释放用法

  1. malloc()只能返回第一个字节的地址,但并不知道此刻指向的第一个字节是什么类型,所以必须添加数据指针类型强制转换。

    比如(char * )malloc(200)返回200个变量的指针;

    (int * )malloc(200)返回50个变量的指针;

    (double* )malloc(200)返回25个变量的指针。

  2. int* p = (int * )malloc(4);  这个函数分配了8个字节的空间,其中p变量占4个字节,p所指向的内存也占了4个字节。p本身所占的内存是静态分配的,p所指向的内存是动态分配的。p本身所占的内存是静态的,不能由程序员手动去释放,只能由p变量所在的函数运行终止时由系统释放。然后free(p);

  3. 释放p指向的动态分配的内存。( * p)同样表示一个int变量,只是这个整形变量的内存分配方式是动态的。

    
    #include <stdio.h>
    #include <malloc.h>
    int main() 
    {
        int len = 0;
        printf("输入你的数组长度:\n ");
        scanf_s(" %d", &len, len);
        int* Arrlist = (int *)malloc(sizeof(int) * len);
    ​
        for (int i = 0; i < len; i++)
            scanf_s(" %d", &Arrlist[i]);
        for (int j = 0; j < len; j++)
            printf("%d ", *(Arrlist + j));
            free(Arrlist);
            return 0; 
    }
     
      

    scanf_s() 是针对“ scanf()在读取字符串时不检查边界,可能会造成内存泄露”这个问题设计的。scanf_s()用于读取字符串时,必须提供一个数字以表明最多读取多少位字符,以防止溢出。

  4. void *realloc(void *ptr, size_t size) 

    表示尝试重新调整之前调用 malloc 所分配的 ptr 所指向的内存块的大小

    ptr -- 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。

    size -- 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

        char *str;
        str = (char*)malloc(sizeof(char) * 4);
        str = (char*)realloc(str, sizeof(char) * 100);
  5. 传统数组不能跨函数使用,静态内存是由栈分配的,函数的调用通过压栈和出栈实现,静态内存在函数执行结束的时候就会被释放。需要使用malloc()申请动态内存,但是一定记得要释放空间。

typedef关键字

typedef 关键字,您可以使用它来为类型取一个新的名字,如下是一个新的使用方法,更加便于使用。

#include <stdio.h>
typedef struct student
{
    int age;
    char name[100];
    int ID;
}*PST, STU; //PST等价于*struct student,STU相当于struct student
​
int main()
{
    STU students;
    PST pst = &students;
    pst->age = 33;
    printf("age is %d\n", pst->age);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值