博客
关于我
音视频系列--c语言学习(结构体,指针,位运算,内存管理,异常指针)
阅读量:263 次
发布时间:2019-03-01

本文共 4711 字,大约阅读时间需要 15 分钟。

C语言入门:结构体、指针与内存管理

C语言作为一门底层编程语言,在音视频开发中具有重要地位。掌握其基本语法和数据结构是每个开发者的必修课。本文将从结构体、指针、位运算、内存管理等方面入手,为读者提供实用的编程知识。


一、结构体

1.1 结构体类型的定义

结构体是一种用户自定义的数据类型,用于存储多个不同数据类型的数据。其定义方式如下:

struct Person {     char name[64];     int age; };typedef struct {     char name[64];     int age; } Person;

注意事项:在定义结构体时,不能直接给成员赋值。结构体只是一个类型定义,变量分配空间时才会赋值。


1.2 结构体变量的定义

结构体变量可以通过以下方式定义:

struct Person {     char name[64];     int age; } p1;  // 定义类型同时定义变量struct {     char name[64];     int age; } p2;  // 定义类型同时定义变量struct Person p3;  // 通过类型直接定义

1.3 结构体变量的初始化

结构体变量可以通过以下方式初始化:

struct Person {     char name[64];     int age; } p1 = { "john", 10 }; struct {     char name[64];     int age; } p2 = { "Obama", 30 }; struct Person p3 = { "Edward", 33 };

1.4 结构体成员的使用

通过指针或数组方式访问结构体成员:

#include 
#include
#include
struct Person { char name[64]; int age; };void test() { // 栈上分配空间 struct Person p1; strcpy(p1.name, "John"); p1.age = 30; // 堆上分配空间 struct Person* p2 = (struct Person*)malloc(sizeof(struct Person)); strcpy(p2->name, "Obama"); p2->age = 33; printf("Name:%s Age:%d\n", p1.name, p1.age); printf("Name:%s Age:%d\n", p2->name, p2->age);}

1.5 结构体赋值

结构体变量可以相互赋值,但不会影响原变量的空间:

struct Person {     char name[64];     int age; };void test() {    // 在栈上分配空间    struct Person p1 = { "John", 30 };    struct Person p2 = { "Obama", 33 };        printf("Name:%s Age:%d\n", p1.name, p1.age);    printf("Name:%s Age:%d\n", p2.name, p2.age);        // 将p2的值赋值给p1    p1 = p2;    printf("Name:%s Age:%d\n", p1.name, p1.age);    printf("Name:%s Age:%d\n", p2.name, p2.age);}

二、指针强化

2.1 指针变量

指针是一种数据类型,用于存储内存地址。以下是指针的基本使用示例:

void test01() {    int* p1 = 0x1234;  // 1    int*** p2 = 0x1111; // 2    printf("p1 size:%d\n", sizeof(p1)); // 8字节    printf("p2 size:%d\n", sizeof(p2)); // 8字节        int a = 10;    p1 = &a;    printf("p1 address:%p\n", p1); // 0x7fffe080    printf("p1 address:%p\n", p1); // p1值的地址    printf("a address:%p\n", &a); // a元素的地址}

2.2 空指针

空指针(NULL指针)用于表示不指向任何对象。可以通过以下方式赋值:

void test() {    char *p = NULL; // 空指针    // 读写空指针会导致错误    strcpy(p, "1111"); // err    char *q = 0x1122; // 野指针    strcpy(q, "2222"); // err}

2.3 野指针

野指针是指指针未初始化或指向已释放的内存。避免野指针的出现:

  • 初始化指针为 NULL。
  • 释放后的指针立即置空。

  • 2.4 间接访问操作符

    通过 * 操作符解引用指针:

    void test01() {    int a = 10;    int* p = &a;    *p = 20;        int b = *p; // 必须确保内存可写        const char* str = "hello world!";    *str = 'm';    printf("a:%d\n", a);    printf("*p:%d\n", *p);    printf("b:%d\n", b);}

    2.5 指针的步长

    指针的步长由其指向的数据类型决定:

    int a = 0xaabbccdd;unsigned int *p1 = &a; // p1指向整数类型,步长为4字节unsigned char *p2 = &a; // p2指向字符类型,步长为1字节printf("%x\n", *p1);   // aabbccddprintf("%x\n", *p2);   // ddprintf("p1 =%d\n", p1); // 6421980printf("p1+1=%d\n", p1 + 1); // 6421984printf("p2 =%d\n", p2); // 6421980printf("p2+1=%d\n", p2 + 1); // 6421981

    三、位运算

    3.1 位逻辑运算符

    C语言提供丰富的位运算符:

    3.1.1 按位取反 ~

    ~(10011010) 01100101unsigned char a = 2; // 00000010unsigned char b = ~a; // 11111101

    3.1.2 位与 &

    (10010011) & (00111101) = (00010001)val &= 0377; // 将val的前三个字节置为0

    3.1.3 位或 |

    (10010011) | (00111101) = (10111111)val |= 0377; // 将val的前三个字节置为1

    3.1.4 位异或 ^

    (10010011) ^ (00111101) = (10101110)val ^= 0377; // 将val的前三个字节两两异或

    3.1.5 常用用法

    • 打开位flag | 00000100
    • 关闭位flag & ~flag
    • 转置位flag ^ 0xff
    • 交换两个数
    int a = 10;int b = 30;a = a ^ b;b = a ^ b;a = a ^ b;

    四、指针详解

    4.1 指针的作用

    指针用于存储内存地址,常用于数组、链表和动态内存分配。

    4.2 指针的定义

    指针的定义可以是单级或多级:

    int *p; // int*类型的指针int *p[3]; // int**类型的指针,指向数组int (*p)[3]; // 指针指向数组int **p; // 两级指针

    4.3 指针的算术运算

    指针加减操作会移动内存地址:

    char a[20] = "You_are_a_girl";int *ptr = (int *)a;printf("* ptr addr %p\n", ptr); // 0x1000f000ptr += 1;printf("* ptr addr %p\n", ptr); // 0x1000f004printf("* ptr=%c\n", *ptr); // 'r'

    五、内存分配

    C语言提供 malloccallocreallocfree 函数用于内存管理。

    5.1 使用方式

    • malloc(size): 分配 size 字节内存。
    • calloc(n, size): 分配 n 个 size 字节的内存,初始化为 0。
    • realloc(ptr, size): 修改已有指针的内存大小。
    • free(ptr): 释放 ptr 所指向的内存。

    六、内存管理机制

    6.1 内存区域

  • 代码区:存放程序代码和常数。
  • 静态区:存放全局变量和静态变量。
  • 栈区:存放函数参数和局部变量。
  • 堆区:存放动态分配的内存。
  • 6.2 内存分配与释放

    使用 mallocfree 函数时,需谨慎管理内存:

    #include 
    #include
    #include
    void print_array(char *p, int n) { for (int i = 0; i < n; i++) { printf("p[%d] = %d\n", i, p[i]); }}int main(int argc, char *argv[]) { char *p = (char *)malloc(1024 * 1024 * 1024); // 分配内存 memset(p, 'a', sizeof(int) * 10); // 初始化内存 int i = 0; for (i = 0; i < 10; i++) { p[i] = i + 65; // 'A' 到 'J' } print_array(p, 10); // 打印数组 free(p); // 释放内存 return 0;}

    七、异常指针

    7.1 悬空指针

    悬空指针指向已释放的对象,需及时置空。

    int *p; // 未初始化,属于悬空指针

    7.2 野指针

    野指针指向垃圾内存,需避免使用。

    void test() {    int *p; // 野指针    *p = 10; // 错误}

    7.3 空指针

    空指针通过 NULL 表示不指向任何对象。

    int *p = NULL; // 空指针

    通过以上内容,希望读者能够掌握 C语言中的结构体、指针和内存管理的基础知识,为后续的音视频开发打下坚实的基础。

    转载地址:http://eihx.baihongyu.com/

    你可能感兴趣的文章
    MSB与LSB
    查看>>
    MSCRM调用外部JS文件
    查看>>
    MSCRM调用外部JS文件
    查看>>
    MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
    查看>>
    MsEdgeTTS开源项目使用教程
    查看>>
    msf
    查看>>
    MSSQL数据库查询优化(一)
    查看>>
    MSSQL数据库迁移到Oracle(二)
    查看>>
    MSSQL日期格式转换函数(使用CONVERT)
    查看>>
    MSTP多生成树协议(第二课)
    查看>>
    MSTP是什么?有哪些专有名词?
    查看>>
    Mstsc 远程桌面链接 And 网络映射
    查看>>
    Myeclipse常用快捷键
    查看>>
    MyEclipse更改项目名web发布名字不改问题
    查看>>
    MyEclipse用(JDBC)连接SQL出现的问题~
    查看>>
    mt-datetime-picker type="date" 时间格式 bug
    查看>>
    myeclipse的新建severlet不见解决方法
    查看>>
    MyEclipse设置当前行背景颜色、选中单词前景色、背景色
    查看>>
    Mtab书签导航程序 LinkStore/getIcon SQL注入漏洞复现
    查看>>
    myeclipse配置springmvc教程
    查看>>