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

编程达人挑战赛·第4期 10w+人浏览 240人参与

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

1. void* —— C 语言的“万能指针”

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

1.1 void* 能做什么?

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

示例:

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++ 递增(无类型 → 无步长)

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

(int*)(p) + 1
(char*)(p) + 1

2. 自定义 memcpy / mystrcpy / myintcpy

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

⭐ 2.1 mystrcpy — 字符串拷贝

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

2.2 myintcpy — int 数组拷贝

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)

关键代码:

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 结构体定义

struct date
{
    int year;
    int month;
    int day;
};

3.2 结构体初始化

struct date d1 = {2025, 11, 24};  // 完全初始化

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

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


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

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

d1.year;

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

struct date *p = &d1;
p->year;

等价于:

(*p).year;

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

字节对齐的目的:

提高 CPU 访问内存的效率

对齐规则:

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

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

struct per
{
    char name[50];
    char sex;
    int age;
    int score;
};

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

输出结构体大小:

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. 结构体数组与函数传参

结构体数组:

struct PER
{
    char name[50];
    float heigh;
};

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

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

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);
}

调用:

show_array(per, 3);

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

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);

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值