PoEdu培训 C语言提高班2 结构体和union和void
文章类别: 培训笔记 0 评论

PoEdu培训 C语言提高班2 结构体和union和void

文章类别: 培训笔记 0 评论

结构体和union和void

struct结构体

声明

struct StructName { ..... }
举例:

struct tagHadesStruct 
{
    int iVal,
    char* szVal,
    char szVal2[255],
    int* pIntVal
};

使用

// 举个例子
#include <stdio.h>

struct tagHadesStruct 
{
    int iVal,
    char* szVal,
    char szVal2[255],
    int* pIntVal
};

int main()
{
    struct tagHadesStruct  structTest = {0}, *pStructTest = NULL;
    structTest.iVal = 0;
    strcpy(structTest.szVal2, "花心胡萝卜工作室");

    pStructTest = &structTest;
    pStructTest->iVal = 1;
    strcpy(pStructTest->szVal2, "Hades Studio");

    return 0;
}

小技巧

struct经常和typedef配合使用

// 举个例子
typedef struct tagHadesStruct 
{
    int iVal,
    char* szVal,
    char szVal2[255],
    int* pIntVal
} HadesStruct, *pHadesStruct;

HadesStruct structTest = {0};
pHadesStruct pStructTest = &structTest;

大小(sizeof)

理论上, 结构体大小就是结构体成员的各类型的长度的总和.
但是, 我们的编译器(VS2015)默认是4byte对齐的, 当我们的结构体大小不能被4整除的时候, 编译器会自动给我们补齐
一定要注意结构体的数据对齐
默认对齐字节是可以设置的, 通过 #pragma pack (2)指令强制对齐字节为2

拿我们 "小技巧" 章节的例子计算一下(32位环境下)
我们手工计算的大小 4 + 4 + 255 + 4 = 267
但是实际sizeof(HadesStruct)结果是268

柔性数组

#include <stdio.h>

typedef struct tagSoftArray
{
    int iLen;
    int array[]
} SoftArray;

int main()
{
    size_t nLen = 10;
    // 在 堆区 分配空间
    SoftArray* sa = (SoftArray*)malloc(sizeof(SoftArray) + sizeof(int) * nLen);
    
    for (size_t i = 0; i < nLen; i++)
    {
        printf("-->[%d]\n", sa->array[i]);
        // 等同于
        printf("-->[%d]\n", *(sa->array + i);
    }
    // 其他操作
    free(sa);

    return 0;
}

对于以上结构体, 使用sizeof(SoftArray)结果是4
因为, 我们的 int array[] 相当于占位符, 不占用空间.

union结构体

// 举个例子
typedef union utagHadesUnion
{
    int iVal;
    char cVal;
} HadesUnion;

上诉结构体的sizeof(HadesUnion) == 4
与struct不同的是, union是共享空间的, 只会分配最大的数据类型的内存空间

作用

判断大小端内存存储
大端存储: 数据高位存储于内存高位
小端存储: 数据高位存储于内存低位

void类型

它表示
它是无法被使用的, 因为它没有大小
经常用于返回值或者参数

void hello(void);

void*类型

我们经常使用void*, 它的意义, 就代表它是一个地址
这个地址的大小, 数据类型我们都不知道, 只知道它是一个地址

void* 可以接受 任何类型的指针.
我们又称之为 "万能指针"
因为它能够提供给我们一种 数据抽象 的能力.
    地址 + 大小 代表了一种数据类型
    而 void* + 大小, 就可以读取任意数据类型的数据.
// 举个例子
#include <stdio.h>
#include <string.h>

#define STR_LEN 10

void swap(void* src, void* dst, size_t size)
{
    void* pTmp = malloc(size);
    memcpy(pTmp, src, size);
    memcpy(dst, pTmp, size);
    free(pTmp);
}

int main()
{
    int iA = 10, iB = 20;
    char cA = 'H', cB = 'a';
    char szA[STR_LEN] = 'Hades';
    char szB[STR_LEN] = 'Studio';
    swap(&iA, &iB, sizeof(int));
    swap(&cA, &cB, sizeof(char));
    swap(szA, szB, STR_LEN);

    printf("iA:[%d], iB:[%d]\n", iA, iB);
    printf("cA:[%c], cB:[%c]\n", cA, cB);
    printf("szA:[%s], szB:[%s]\n", szA, szB);

    return 0;
}

如有错误,请提出指正!谢谢.

回复