16、C 语言高级指针与结构体

C 语言高级指针与结构体:void*、结构体、字节对齐、memcpy

1. void* ------ C 语言的"万能指针"

void* 又叫"通用指针",可以接收任意类型的地址,是很多底层库函数(如 memcpy、qsort)的基础。

1.1 void* 能做什么?

  • 可以存储任意指针
  • 可以作为函数参数 → 实现泛型效果
  • 可以作为函数返回值
  • 适合实现通用库函数(如 memcpy)

示例:

c 复制代码
int a = 20;
char s[100] = "hello";

void *p = &a;
printf("%d\n", *(int*)p);

p = s;
printf("%s\n", (char*)p);

1.2 void* 不能直接做什么?

  • ❌ 不能解引用:*p(因为不知道类型)
  • ❌ 不能 p++ 递增(无类型 → 无步长)

必须 强制转换后 才能使用:

c 复制代码
(int*)(p) + 1
(char*)(p) + 1

2. 自定义 memcpy / mystrcpy / myintcpy

为了理解 void* 和内存操作,我们手写了简单的内存拷贝函数。

⭐ 2.1 mystrcpy --- 字符串拷贝

c 复制代码
char* mystrcpy(char* dst,char* src)
{
    char* tmp = dst;
    while(*src!='\0')
    {
        *dst = *src;
        dst++;
        src++;
    }
    *dst='\0';
    return tmp;
}

2.2 myintcpy --- int 数组拷贝

c 复制代码
int *myintcpy(int *dst,int *src,int len)
{
    int *tmp=dst;
    for(int i=0;i<len;i++)
    {
        *dst=*src;
        dst++;
        src++;
    }
    return tmp;
}

⭐ 2.3 mymemcpy(万能 memcpy)

关键代码:

c 复制代码
int *mymemcpy(void *dst, void *src, int len)
{
    void *tmp = dst;
    char *d = (char*)dst;
    char *s = (char*)src;

    for(int i=0;i<len;i++)
    {
        *d = *s;
        d++;
        s++;
    }
    return tmp;
}

解释:

  • 使用 char* 进行拷贝,因为 char 是 1 字节,最适合逐字节复制。
  • 这就实现了真正意义上的通用 memcpy。

3. 结构体(struct)基础

3.1 结构体定义

c 复制代码
struct date
{
    int year;
    int month;
    int day;
};

3.2 结构体初始化

c 复制代码
struct date d1 = {2025, 11, 24};  // 完全初始化

struct date d2 = {                 // 部分初始化
    .year = 2025,
    .day = 10
};

未赋值的成员会自动设为 0


4. 结构体指针与成员访问

结构体变量使用点号访问:

c 复制代码
d1.year;

结构体指针使用箭头访问:

c 复制代码
struct date *p = &d1;
p->year;

等价于:

c 复制代码
(*p).year;

5. 结构体字节对齐(重点)

字节对齐的目的:

提高 CPU 访问内存的效率

对齐规则:

  1. 每个成员的地址必须是其类型大小的整数倍(如 int 必须对齐到 4 的倍数)
  2. 结构体总大小 必须是 最大成员类型大小的整数倍

示例代码(来自你今天的实验):

c 复制代码
struct per
{
    char name[50];
    char sex;
    int age;
    int score;
};

struct per3
{
    double a;
    char c;
    short s;
    struct per2 p;
};

输出结构体大小:

c 复制代码
printf("sizeof p is %lu\n", sizeof(p));
printf("sizeof p3 is %lu\n", sizeof(p3));
printf("sizeof p4 is %lu\n", sizeof(p4));

通过观察不同类型排列导致的对齐变化,可以深入理解结构体布局规则。


6. 结构体数组与函数传参

结构体数组:

c 复制代码
struct PER
{
    char name[50];
    float heigh;
};

struct PER per[3] =
{
    {"zhangsan",1.75},
    {"lisi",1.70},
    {"wangmazi",1.95},
};

传给函数时应使用指针,提高效率:

c 复制代码
void show_array(struct PER* per, int len)
{
    for(int i=0;i<len;i++)
        printf("%d %s %f\n", i, per[i].name, per[i].heigh);
}

调用:

c 复制代码
show_array(per, 3);

7. 综合示例:结构体操作与 mymemcpy

c 复制代码
struct person per = {"zhangsan",20,90.5};
struct person per2 = {0};

mymemcpy(&per2, &per, sizeof(per));

printf("%s %d %f\n", per2.name, per2.age, per2.score);

这就实现了结构体的深拷贝。

相关推荐
达文汐1 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗1 分钟前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子1 分钟前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
算法_小学生2 分钟前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode
执着2593 分钟前
力扣hot100 - 234、回文链表
算法·leetcode·链表
Gorgous—l4 分钟前
数据结构算法学习:LeetCode热题100-多维动态规划篇(不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离)
数据结构·学习·算法
熬夜造bug5 分钟前
LeetCode Hot100 刷题路线(Python版)
算法·leetcode·职场和发展
2501_927773079 分钟前
imx6驱动
linux·运维·服务器
hy____12324 分钟前
Linux_进程间通信
linux·运维·服务器
2401_8384725127 分钟前
C++中的访问者模式
开发语言·c++·算法