深度剖析C语言结构体

做了挺久的开发,对于C这种东西,我不敢说自己已经精通了,毕竟还是有许多细节在学习的过程中会遗忘,然后再通过实践慢慢去一点点捡回来。所以只能算是熟练级别。

Linux内核的实现博大精深,从offsetof的实现到后面的container_of,为什么通过结构体的的成员就能获得整个结构体的指针呢?这就得益于offsetof宏的实现。关于这个宏,前面的博文也有讲解,但不够深入,今天的这个例子,足以对结构体本身的原理大彻大悟,我们来看下面这个例子:

#include <stdio.h>
//32位系统上,结构体在没指定对齐的时候,默认以四字节进行对齐
typedef struct __ST
{
 int id ;  //4
 char *name ; //4
 float math ; //4
}ST;
int main()
{
 ST st ;
 //获取结构体的第一个元素的首地址
 int *ptr_0 = (int *)(&st);
 printf("st:  %p  ptr:  %p \n",&st,ptr_0);
 //对结构体第一个元素赋值
 *ptr_0 = 100 ;
 printf("*ptr_0 = %d\n",*ptr_0);
 //获取结构体的第二个元素的首地址,因为第二个元素是一级指针,所以需要用一个二级指针来接
 char **ptr_1 = (char **)((int)&st+4) ;
 printf("ptr_1:%p\n",ptr_1);
 //对结构体的第二个元素赋值
 *ptr_1 = "hello world";
 printf("ptr_1:%s\n",*ptr_1);
 //获取结构体的第三个元素的首地址,根据对齐原则偏移算出第三个元素的地址
 float *ptr_2 = (float *)((int)&st+8) ;
 printf("ptr_2:%p \n",ptr_2);
 //对结构体的第三个元素进行赋值
 *ptr_2 = 96.78 ;
 printf("ptr_2:%.2f \n",*ptr_2);
 //输出结构体中所有成员的值
 printf("st.id = %d  st.name = %s  st.math = %.2f\n",st.id,st.name,st.math);
  return 0;
}

这里的根据对齐原则算出来的偏移量其实其实不就是offsetof宏的原理吗?

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

往后继续看待链表,函数指针,等等与结构体有关的概念,瞬间觉得一幕了然,彻底打通了这条曾经学习的阻塞道路。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • C语言使用结构体实现简单通讯录

    C语言用结构体实现一个通讯录,通讯录可以用来存储1000个人的信息,每个人的信息包括: 姓名.性别.年龄.电话.住址 提供方法: 1. 添加联系人信息 2. 删除指定联系人信息 3. 查找指定联系人信息 4. 修改指定联系人信息 5. 显示所有联系人信息 6. 清空所有联系人 代码实现: 头文件: #ifndef __HEAD_H__ ////防止头文件被多次调用 #define __HEAD_H__ #include<stdio.h> #include<string.h> #in

  • C语言中结构体变量私有化详解

    背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据结构.结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问. 问题描述 C语言结构体定义中的变量默认是公有(Public)属性,如果实现成员变量的

  • C#中结构体定义并转换字节数组详解

    最近的项目在做socket通信报文解析的时候,用到了结构体与字节数组的转换:由于客户端采用C++开发,服务端采用C#开发,所以双方必须保证各自定义结构体成员类型和长度一致才能保证报文解析的正确性,这一点非常重要. 首先是结构体定义,一些基本的数据类型,C#与C++都是可以匹配的: [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct Head { public

  • 解析C语言结构体及位段

    1.结构的定义 在实际情况中,数据经常以成组的形式存在.如果这些值的类型各不相同,他们无法同时存储于同一个数组中,在C中,可以使用结构把不同类型的值存储在一起,所以结构也是一些值的集合,这些值称为它的成员,但是这些成员的类型可以不同. 拓展: "结构"是一种构造数据类型,也叫做用户自定义数据类型,它是由若干"成员"组成的. 每一个成员可以是一个基本数据类型或者又是一个构造类型. 结构即是一种"构造"而成的数据类型, 那么在说明和使用之前必须先定义

  • C语言结构体数组同时赋值的另类用法

    说到C语言结构体数组的同时赋值,许多人一想就会想到用以下的这种方法,咱们来写一个例子: #include <stdio.h> struct student { int a; int b ; int c ; }; struct student array1[1000] ; int main(void) { int i ; for(i = 0 ; i < 1000 ; i++) { array[i].a = 1 ; array[i].b = 2 ; array[i].c = 3 ; } fo

  • 彻底搞懂PHP 变量结构体

    PHP5 中的 zval // 1. zval typedef struct _zval_struct { zvalue_value value; zend_uint refcount__gc; zend_uchar type; zend_uchar is_ref__gc; } zval; // 2. zvalue_value typedef union _zvalue_value { long lval; // 用于 bool 类型.整型和资源类型 double dval; // 用于浮点类型

  • C语言利用结构体数组实现学生成绩管理系统

    要求: 某班有最多不超过30人(具体人数由键盘输入)参加期末考试,最多不超过6门(具体门数由键盘输入).定义结构体类型描述学生信息,每个学生信息包括:学号.姓名.多门课的成绩.总成绩和平均成绩.用结构体数组作为函数参数,编程实现如下菜单驱动的学生成绩管理系统. (1) 录入每个学生的学号.姓名和各科考试成绩. (2) 计算每门课程的总分和平均分. (3) 计算每个学生的总分和平均分. (4) 按每个学生的总分由高到低排出名次表. (5) 按学号由小到大排出成绩表. (6) 按姓名的字典顺序排出成

  • C++中对C语言结构体用法的扩充

    最近在学习C++,了解到,C++中对C做了扩充,使用结构体时也可以像类一样,规定私有数据类型和公有数据类型,同时也可以在struct中实现方法设置等等. 但为了保持面对对象的特性,建议还是使用class来描述一个类. 案例如下: #include <iostream> #include <ctime> using namespace std ; typedef struct student { private : int a , b , c ; public : void set(

  • C++结构体struct和类class区别详解

    之前因为都在忙着毕业的开题答辩与投稿论文的事宜,一直没有时间更新这个系列的文章.师弟看了上一篇雾中风景的文章,希望我继续把这个系列的文章写下去.坦白说,C++的特性很多,这也不是教学指南的文章,我会选取一些自己在学习C++过程之中值得探讨的问题和大家聊一聊,来抛砖引玉.好的,今天先放点开胃菜,和大家聊聊struct与class关键字. 1.struct关键字: 在C++语言作为C语言的一个超集,是兼容C语言的所有语法规则的.C语言是我学习的第一门编程语言,我自然对于其中的语法规则十分熟悉,C语言

  • C语言结构体定义的方法汇总

    什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据结构.结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问. 结构体与数组的比较 (1) 都由多个元素组成 (2) 各个元素在内存中的存储空间是连续的 (3) 数组中各个元素的数据类型相同,而结构体中的各个元素的数据类型可以不相同 结

随机推荐