本文共 4806 字,大约阅读时间需要 16 分钟。
C语言作为一门底层编程语言,在音视频开发中具有重要地位。掌握其基本语法和数据结构是每个开发者的必修课。本文将从结构体、指针、位运算、内存管理等方面入手,为读者提供实用的编程知识。
结构体是一种用户自定义的数据类型,用于存储多个不同数据类型的数据。其定义方式如下:
struct Person { char name[64]; int age; };typedef struct { char name[64]; int age; } Person;
注意事项:在定义结构体时,不能直接给成员赋值。结构体只是一个类型定义,变量分配空间时才会赋值。
结构体变量可以通过以下方式定义:
struct Person { char name[64]; int age; } p1; // 定义类型同时定义变量struct { char name[64]; int age; } p2; // 定义类型同时定义变量struct Person p3; // 通过类型直接定义
结构体变量可以通过以下方式初始化:
struct Person { char name[64]; int age; } p1 = { "john", 10 }; struct { char name[64]; int age; } p2 = { "Obama", 30 }; struct Person p3 = { "Edward", 33 };
通过指针或数组方式访问结构体成员:
#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);}
结构体变量可以相互赋值,但不会影响原变量的空间:
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);}
指针是一种数据类型,用于存储内存地址。以下是指针的基本使用示例:
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元素的地址}
空指针(NULL指针)用于表示不指向任何对象。可以通过以下方式赋值:
void test() { char *p = NULL; // 空指针 // 读写空指针会导致错误 strcpy(p, "1111"); // err char *q = 0x1122; // 野指针 strcpy(q, "2222"); // err}
野指针是指指针未初始化或指向已释放的内存。避免野指针的出现:
通过 *
操作符解引用指针:
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);}
指针的步长由其指向的数据类型决定:
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
C语言提供丰富的位运算符:
~
~(10011010) 01100101unsigned char a = 2; // 00000010unsigned char b = ~a; // 11111101
&
(10010011) & (00111101) = (00010001)val &= 0377; // 将val的前三个字节置为0
|
(10010011) | (00111101) = (10111111)val |= 0377; // 将val的前三个字节置为1
^
(10010011) ^ (00111101) = (10101110)val ^= 0377; // 将val的前三个字节两两异或
flag | 00000100
flag & ~flag
flag ^ 0xff
int a = 10;int b = 30;a = a ^ b;b = a ^ b;a = a ^ b;
指针用于存储内存地址,常用于数组、链表和动态内存分配。
指针的定义可以是单级或多级:
int *p; // int*类型的指针int *p[3]; // int**类型的指针,指向数组int (*p)[3]; // 指针指向数组int **p; // 两级指针
指针加减操作会移动内存地址:
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语言提供 malloc
、calloc
、realloc
和 free
函数用于内存管理。
malloc(size)
: 分配 size 字节内存。calloc(n, size)
: 分配 n 个 size 字节的内存,初始化为 0。realloc(ptr, size)
: 修改已有指针的内存大小。free(ptr)
: 释放 ptr 所指向的内存。使用 malloc
和 free
函数时,需谨慎管理内存:
#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;}
悬空指针指向已释放的对象,需及时置空。
int *p; // 未初始化,属于悬空指针
野指针指向垃圾内存,需避免使用。
void test() { int *p; // 野指针 *p = 10; // 错误}
空指针通过 NULL
表示不指向任何对象。
int *p = NULL; // 空指针
通过以上内容,希望读者能够掌握 C语言中的结构体、指针和内存管理的基础知识,为后续的音视频开发打下坚实的基础。
转载地址:http://eihx.baihongyu.com/