C语言结构体

本文介绍了C语言中的结构体,包括如何定义、初始化和使用结构体,以及结构体指针的操作。通过示例代码展示了结构体在内存中的布局和指针的自动步长调整。还提到了结构体内的嵌套结构体以及动态内存分配。最后,讨论了结构体在内存操作中的灵活性和潜在的混淆之处。
摘要由CSDN通过智能技术生成

结构体简单介绍

一般来说,C的结构体是集合了多个数据的一个集合体,即把一组数据放到一起,然后给包含这些数据的代码块一个名字,以后在声名或是使用这些数据时,就可以只针对这个代码块的名字进行声名。当然我这种解释就非常不专业。

定义一个结构体,在C中一般使用struct关键字,以表明后面的代码段被编译器认为是一个结构体。一般的代码如下:

struct Animation
{
    char _name[32]; // 名字
    float _weight; // 重量
    float _height; // 身高
};

以上代码定义了一个叫做Animation的结构体,此结构体中有三个成员变量,在使用时,我们可以这样定义:

struct Animation a;
sprintf(a._name, "%s", "a1");
a._weight = 10.0f;
a._height = 5.0f;

在这里可以看到,在定义时也要写struct这个关键字,有时候为了更省事,可以在前面增加typedef关键字,这样原来的定义可以改成如下形式:

typedef struct
{
    char _name[32]; // 名字
    float _weight; // 重量
    float _height; // 身高
} Animation;
int main ( int argc, char *argv[] )
{
    Animation a;
}

说到这里,还是需要再看回指针,结构体的指针怎么表示?上一节中说到万物皆是指针。如下,声明一个结构体指针,声明结构体数组。

Animation *an = NULL;
an = malloc(sizeof( Animation) );
an->_weight = 20.0f;
an->_height = 22.0f;
free( an );// 指针不用后要及时释放
an = NULL; // 指针内存被释放掉后一定要记得置空,这是一个好习惯
// 这行代码是新分配5个Animation的内存大小,后面就可以像访问数组一样对结构体访问
an = malloc(sizeof( Animation) * 5 );
an[0]->_weight = 30.0f;

free( an );
an = NULL;

可以看到结构体一样可以使用序号访问。

这时候,可能会发生疑惑,为什么使用序号,就可以定位到指定的位置,并能正确的访问里面的变量,在C语言,指针这个类型在进行加减运算时,会根据这个指针的数据类型自动调整内存的加减步长,比如下面代码:

int *c = malloc(sizeof( int ) * 10 );
Animation *lpAnimation = malloc( sizeof( Animation ) * 10 );
printf("%p -> %p : %d\n%p -> %p : %d\n", c, c + 1, sizeof( int ), lpAnimation, lpAnimation + 1, sizeof( Animation ) );
free( c )
free( lpAnimation )

运行时输出如下:

0x7f94fec017c0->0x7f94fec017c4 : 4
0x7f94fec017f0->0x7f94fec01818 : 40

可以看到,int* 这样的指针,相差一个时候,内存位置相差4,而Animation*这样的指针,前后两个指针之间则相差的正好是Animation这个结体体的大小。

这其实是C语言自己做的事,我们使用时,只需要知道就好。

有时候,我们可能在某个结构体内再嵌套另一个结构体,如下:

typedef struct
{
    int _age;
    int _height;
} People;

typedef struct 
{
    People _p;
    int _count;
}Family;

int main( int argc, char *argv[] )
{
    Family f={{3,12},6};
    printf("%d,%d,%d\n", f._p._age, f._p._height, f._count );
    return 0;
}

可以看到,初始化时,还是和初始化其它结构体一样,把需要的变量按顺序放到{}中即可。

至于更多的内存操作,比如

People *lpPeople = malloc( sizeof( People ) );
printf("%p, %p\n", lpPeople, &( lpPeople->_age ) ); // 输出lpPeople的地址,输出lpPeople中变量_age的地址
*((int*)lpPeople) = 10;
printf("%d\n", lpPeople->_age );
*(((int*)lpPeople)+1) = 20;
printf("%d\n", lpPeople->_count );

当然,并不提倡这样使用,会让人迷惑,不过这也表明指针正是指向了某个内存块,只要知道某个内存地址,那么我们可以用这个内存地址做任何事。

另:

People *lpPeople = NULL;
printf("%p, %d\n", lpPeople, &( lpPeople->_age ), &(lpPeople->_count ) );

输出如下:

0x0, 0, 4

这段代码,只是输出了_age, _count相对于整个结体构的偏移

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值