C语言中隐藏结构体的细节

我们都知道,在C语言中,结构体中的字段都是可以访问的。或者说,在C++ 中,类和结构体的主要区别就是类中成员变量默认为private,而结构体中默认为public。结构体的这一个特性,导致结构体中封装的数据,实际上并没有封装,外界都可以访问结构体重的字段。

C++中我们尚可用类来替代结构体,但是,C语言中是没有类的,只能用结构体,但很多时候,我们需要隐藏结构体的字段,不让外界直接访问,而是通过我们写的函数进行间接访问,这样就提高了程序的封装性。

实现方法,简单来说,就是,结构体定义时,要定义在.c文件中,然后我们自己定义一些访问结构体的函数,在.h文件中,只存放函数原型声明和对结构体的声明。

看个例子

.c文件中

//stu.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stu{
  char id[10];
  int score;
};

struct stu *new_stu()
{
  struct stu *s;
  s = (struct stu *)malloc(sizeof(struct stu));

  return s;
}

void set_id(struct stu *s,char *id)
{
  strcpy(s->id,id);
}
char *get_id(struct stu *s)
{
  return s->id;
}

可以看到,在.c文件中,我定义了一个结构体,并且定义了一些用于操作这个结构体的函数。

在.h文件中

stu.h
#ifndef STU_H
#define STU_H

struct stu;
extern void set_id(struct stu *s,char *id);
extern char *get_id(struct stu *s);

extern struct stu *new_stu();

#endif

在.h中我声明了一下结构体struct stu,并且写了函数的原型声明,供其他文件调用。

在main.c中我引用了stu.h

下面是main.c

#include <stdio.h>
#include "stu.h"

int main()
{
  //struct stu s;
  //s.score = 100;
  //struct stu s = {{0}};

  struct stu *s;
  s = new_stu();

  set_id(s, "950621");
  char *id = NULL;

  id = get_id(s);

  printf("设置的id为:%s\n",id);
  return 0;

}

可以看到,在main函数中,我先是定义了一个struct stu类型的指针,然后通过new_stu()给这个指针分配了空间,在通过另外两个函数对其进行了操作。

这里需要注意一下我注释掉的部分,说明一下:

这种情况下,不能定义struct stu类型的变量!!!

因为:

.h文件中,只是对结构体进行了声明,并没有结构体具体细节的描述,也就是在main.c中只是声明了一下struct stu,这样编译器就知道有个结构体类型叫struct stu,但是它并不知道stu的内部细节。

我们都知道,定义一个变量,编译器是要给它分配内存空间的,但是,此时编译器并不知道stu的内部细节,也就不知道stu这个结构体的变量要占多少空间,自然无法分配内存。这样在编译时期就会报错。

但是定义一个指针变量就不一样啦,不管是什么类型的指针,占据的内存空间都是4个字节,编译器只需要确定有个叫struct stu 的类型存在就好了,而.h中那个声明,就是在告诉编译器,有这么一个类型。

同时,这种情况下也不能访问结构体的字段,比如,s->score=100;这条语句在编译时就会报错,原因和上面一样,编译器并不知道struct stu结构体的内部细节。

通过上面的方法,在除了stu.c文件之外的其他文件中,只能通过stu.c中定义的函数来间接操作结构体变量,而不能直接对结构体变量进行操作,包括不能创建一个结构体变量!

这样就很好地体现了程序的封装性,也提高了程序的安全性。但是就需要我们写很多操作函数啦,包括创建结构体指针变量分配空间的函数。

我们也可以在.h文件中用typedef声明一个结构体的指针类型,如  typedef struct sut * pStu;

这样在main.c中就可以用pStu声明结构体指针变量了。

(0)

相关推荐

  • C语言中的结构体的入门学习教程

    C语言中数组允许定义类型的变量,可容纳相同类型的多个数据项,但结构体在C语言编程中,它允许定义不同种类的数据项可供其他用户定义的数据类型. 结构是用来代表一个记录,假设要跟踪图书馆的书籍.可能要跟踪有关每本书以下属性: Title - 标题 Author - 作者 Subject - 科目 Book ID - 编号 定义结构体 定义一个结构体,必须使用结构体的struct语句.该struct语句定义了一个新的数据类型,程序不止一个成员.struct语句的格式是这样的: struct [struc

  • php读取二进制流(C语言结构体struct数据文件)的深入解析

    尽管php是用C语言开发的,不过令我不解的是php没有提供对结构体struct的直接支持.不过php提供了pack和unpack函数,用来进行二进制数据(binary data)和php内部数据的互转: 复制代码 代码如下: string pack ( string $format [, mixed $args [, mixed $...]] )   //Pack given arguments into binary string according to format.  array unp

  • C语言 结构体(Struct)详解及示例代码

    前面的教程中我们讲解了数组(Array),它是一组具有相同类型的数据的集合.但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放. 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{     结构体所包含的变量或数组 }; 结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可

  • 深入分析C语言中结构体指针的定义与引用详解

    指向结构体类型变量的使用首先让我们定义结构体:struct stu{char name[20];long number;float score[4];} ;再定义指向结构体类型变量的指针变量:struct stu *p1, *p2 ;定义指针变量p 1.p 2,分别指向结构体类型变量.引用形式为:指针变量→成员:[例7-2] 对指向结构体类型变量的正确使用.输入一个结构体类型变量的成员,并输出. 复制代码 代码如下: #include <stdlib.h> /*使用m a l l o c (

  • C语言中结构体(struct)的几种初始化方法

    本文给大家总结的struct数据有3种初始化方法 1.顺序 2.C风格的乱序 3.C++风格的乱序 下面通过示例代码详细介绍这三种初始化方法. 1)顺序 这种方法很常见,在一般的介绍C的书中都有介绍.顺序初始化的特点是: 按照成员定义的顺序,从前到后逐个初始化:允许只初始化部分成员:在被初始化的成员之前,不能有未初始化的成员. 示例: struct User oneUser = {10, "Lucy", "/home/Lucy"}; 2)乱序(C风格) 顺序的缺陷是

  • 浅谈C语言中结构体的初始化

    <代码大全>建议在变量定义的时候进行初始化,但是很多人,特别是新人对结构体或者结构体数组定义是一般不会初始化,或者不知道怎么初始化.1.初始化 复制代码 代码如下: typedef struct _TEST_T {        int i;        char c[10];}TEST_T;TEST_T gst  = {1, "12345"};//可以初始化,设置i为1,s为一个字符串.TEST_T gst  = {1};//初始化个数少于实际个数时,只初始化前面的成员

  • 详解C语言中结构体的自引用和相互引用

    结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针. 结构体的相互引用(mutual reference),就是说在多个结构体中,都包含指向其他结构体的指针. 1. 自引用 结构体 1.1 不使用typedef时 错误的方式: struct tag_1{ struct tag_1 A; /* 结构体 */ int value; }; 这种声明是错误的,因为这种声明实际上是一个无限循环,成员b是一个结构体,b的内部还会有成员是结构体,依次下去,无线循环.

  • C语言中结构体struct编写的一些要点解析

    一.关于结构体的声明 1.匿名声明.如: struct { int i,j; }point; 说明: 这段代码的含义是,声明一个无名(anonymous)的结构体,并创建了一个结构体变量point.如果这段声明是放在全局域(在任意函数(比如main函数)外)内,那么point内的变量将被初始化为默认值,换句话说,以这种方式声明结构体变量时就已经为它分配了内存空间. 适用于该结构体只需要产生一个变量!本例中,该匿名结构体将有且仅有point这个结构体变量! 不同的匿名结构体变量,类型是不同的!如

  • C语言中隐藏结构体的细节

    我们都知道,在C语言中,结构体中的字段都是可以访问的.或者说,在C++ 中,类和结构体的主要区别就是类中成员变量默认为private,而结构体中默认为public.结构体的这一个特性,导致结构体中封装的数据,实际上并没有封装,外界都可以访问结构体重的字段. C++中我们尚可用类来替代结构体,但是,C语言中是没有类的,只能用结构体,但很多时候,我们需要隐藏结构体的字段,不让外界直接访问,而是通过我们写的函数进行间接访问,这样就提高了程序的封装性. 实现方法,简单来说,就是,结构体定义时,要定义在.

  • 浅谈Go语言中的结构体struct & 接口Interface & 反射

    结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struct类型理解为类,可以定义方法,和函数定义有些许区别: struct类型是值类型. struct定义 type User struct { Name string Age int32 mess string } var user User var user1 *User = &User{} var user2 *User = new(User) struct使用 下面示例中user1和

  • C语言中的结构体在Python中实现转换

    目录 struct介绍 struct中的常用接口 pack() unpack() fmt 示例 struct介绍 Python中提供了struct接口,用来处理类似C语言中的结构体. 处理的方式是将结构体表现位字符串,这个字符串其实就是结构体的一个个字节. struct中的常用接口 主要就是两个,pack()和unpack(). pack()就是将结构体转换成字符串(或者说字节序),unpack()则相反. pack() pack()函数的说明如下(来自Python 2.7.15 documen

  • C语言中的结构体快排算法

    目录 C语言结构体快排算法 基于结构体数组的快速排序 C语言结构体快排算法 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> struct Stu{ char name[100]; //名字 char xue[100]; //学号 int c; //成绩 }stu[10010]; int comp(const void* a,const void* b) { struct Stu *aa = (str

  • Go语言学习函数+结构体+方法+接口

    目录 1. 函数 1.1 函数返回值 同一种类型返回值 带变量名的返回值 函数中的参数传递 函数变量 1.2 匿名函数——没有函数名字的函数 在定义时调用匿名函数 将匿名函数赋值给变量 匿名函数用作回调函数 可变参数——参数数量不固定的函数形式 1.3 闭包 1.4 defer语句 处理运行时发生的错误 1.5 宕机恢复(recover)——防止程序崩溃 2. 结构体 2.1 定义与给结构体赋值 3. 方法 3.1 结构体方法 3.2 接收器 指针接收器 非指针类型接收器 4. 接口 4.1 声

  • C语言 structural body结构体详解用法

    目录 结构体 结构体类型的声明 举个现实例子 程序实例 结构体成员的类型: 结构体变量的定义和初始化 程序一 结构体嵌套情况下,初始化和定义 结构体成员的访问 结构体传参 程序一: 程序二 结构体 结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量 结构体类型的声明 创建 结构体类型 没有占 内存空间,因为还 没有 创建变量 举个现实例子                 盖房子 图纸 --------------------> 房子 结构体类型        结构体变量

  • C语言 详细分析结构体的内存对齐

    目录 一.结构体 二.结构体内存对齐 1.非嵌套结构体的大小 2.含嵌套结构体的大小 三.为什么要内存对齐 1.平台原因(移植原因) 2.性能原因 一.结构体 结构体 (struct)是一种数据结构,可以包含很多数据类型,可以实现比较复杂的数据结构. 常见的int,char类型变量,我们可以一眼看出占多少字节,但对于结构体,可就有点难度了. 让我们来猜猜以下程序的输出 struct S1 { char c1; int i; char c2; }; struct S2 { char c1; cha

  • C语言详解结构体的内存对齐与大小计算

    目录 结构体的内存对齐 1.计算结构体的大小 2.结构体的对齐规则 3.为什么存在内存对齐? 4.总结 结构体的内存对齐 1.计算结构体的大小 struct S1 { char c1; // 1 byte,默认对齐数为8,所以c1的对齐数是1,第一个成员变量放在与结构体变量偏移量为0的地址处 int i; // 4 byte,默认对齐数为8,所以i的对齐数是4,所以i要放到偏移量为 4的整数倍 的地址处 char c2; // 1 byte,默认对齐数为8,所以c2的对齐数是1,所以c2要放到偏

  • go语言数组及结构体继承和初始化示例解析

    目录 分类 数组 数组定义 结构体 结构体继承 结构体初始化 成员的操作 同名字段 其它匿名字段 非结构体类型 结构体指针类型 结构体字段实现接口 分类 类型 名称 长度 默认值 说明 pointer 指针   nil   array 数组   0   slice 切片   nil 引⽤类型 map 字典   nil 引⽤类型 struct 结构体       数组 如果要存储班级里所有学生的数学成绩,应该怎样存储呢?可能有同学说,通过定义变量来存储.但是,问题是班级有80个学生,那么要定义80

随机推荐