首页 > 编程语言 >C++学习---cstdio的源码学习分析01-类型定义

C++学习---cstdio的源码学习分析01-类型定义

时间:2022-12-07 23:31:58浏览次数:73  
标签:__ char 01 FILE int --- 源码 IO struct

引言

cstdio文件是C++对stdio.h头文件的封装,Standard Input and Output Library,定义了一系列标准输入输出函数,包括文件操作(fopen/fclose等),格式化打印(printf/scanf)等。 通过该文件的学习,我们能够洞悉一些底层机制的本质,同时,也能够学习了解这些函数的实现方式,接下来,我们就一一学习这些函数的源码。

代码参考:因为这个头文件是相对比较特殊的,我们没有再采取阅读AOSP源码中bionic代码的方式,取而代之,我们参考glibc中的源码,这也是linux环境下,使用最为广泛的C标准库。

glibc源码下载:​​www.gnu.org/software/li…​

git clone https://sourceware.org/git/glibc.git
cd glibc
git checkout master

后文的源码阅读也都基于glibc代码的实现方式。

头文件位置

在glibc代码中搜索stdio.h,可以看到如下文件:

1      1  /home/sangyu/WorkSpace/Code/C++/glibc/include/bits/stdio.h <<<unknown>>>
2 1 /home/sangyu/WorkSpace/Code/C++/glibc/include/stdio.h <<<unknown>>>
3 1 /home/sangyu/WorkSpace/Code/C++/glibc/libio/bits/stdio.h <<<unknown>>>
4 1 /home/sangyu/WorkSpace/Code/C++/glibc/libio/stdio.h <<<unknown>>>

通过查看头文件的包含关系:

glibc/include/bits/stdio.h include glibc/libio/bits/stdio.h实现

glibc/include/stdio.h include glibc/libio/stdio.h实现

实际上,实现函数定义以及相关接口的是glibc/libio/stdio.h

类型定义与宏定义

stdio.h头文件中定义了后续即将用到的类型与宏定义。

类型定义

FILE类型---文件流对象

/glibc/libio/bits/types/FILE.h,发现了FILE的实际定义_IO_FILE,继续进行追踪

4 struct _IO_FILE;
5
6 /* The opaque type of streams. This is the definition used elsewhere. */
7 typedef struct _IO_FILE FILE;

/glibc/libio/bits/types/struct_FILE.h中最终定义了_IO_FILE,其中的数据类型分为以下几类:

  • int _flags:用于控制文件流的访问权限(如读写执行,注意高位被_IO_MAGIC占用,剩余位用来表示flags)
  • streambuf控制的:用于标识当前读写位置,buffer大小等。
  • char *_IO_read_ptr:当前读取的指针
  • char *_IO_read_end:get区域的末尾
  • char *_IO_read_base:putback+get区域的开始
  • char *_IO_write_base:put区域的开始
  • char *_IO_write_ptr:当前写入的指针
  • char *_IO_write_end:put区域的末尾
  • char *_IO_buf_base:剩余数据的开始
  • char *_IO_buf_end:剩余数据的末尾
  • 备份和回退控制的:用于文件备份和回退控制的指针
  • char *_IO_save_base:非当前get区域的开始位置
  • char *_IO_backup_base:备份区域第一个合法字符
  • char *_IO_save_end:非当前get区域的末尾位置
  • struct _IO_marker *_markers:记录buffer中的位置(后面查看源码分析)
  • struct _IO_FILE *_chain:指向链接的下一个_IO_FILE对象
  • int _fileno:file的number
  • int _flags2:扩展flags
  • __off_t _old_offset:旧版的offset,最终定义为(long int,32位)
  • unsigned short _cur_column:当前列
  • signed char _vtable_offset:vtable表的偏移
  • char _shortbuf[1]:只存储一个字符的buffer
  • _IO_lock_t *_lock:访问IO锁 注意:这里针对旧版的IO_FILE做了兼容,下面是新版增加的内容
  • __off64_t _offset:64位offset(定义为__int64_t,64位)
  • 针对宽字符的处理buff
  • struct _IO_codecvt *_codecvt:字符转换
  • struct _IO_wide_data *_wide_data:宽数据
  • struct _IO_FILE *_freeres_list:剩余的_IO_FILE list
  • size_t __pad5:对齐信息
  • int _mode:mode信息
  • char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]:预留位置保证追加部分是16个(加上int _mode)sizeof(int)对齐的。
46 /* The tag name of this struct is _IO_FILE to preserve historic
47 C++ mangled names for functions taking FILE* arguments.
48 That name should not be used in new code. */49 struct _IO_FILE50 {
51 int _flags; /* High-order word is _IO_MAGIC; rest is flags. */52
53 /* The following pointers correspond to the C++ streambuf protocol. */54 char *_IO_read_ptr; /* Current read pointer */55 char *_IO_read_end; /* End of get area. */56 char *_IO_read_base; /* Start of putback+get area. */57 char *_IO_write_base; /* Start of put area. */58 char *_IO_write_ptr; /* Current put pointer. */59 char *_IO_write_end; /* End of put area. */60 char *_IO_buf_base; /* Start of reserve area. */61 char *_IO_buf_end; /* End of reserve area. */62
63 /* The following fields are used to support backing up and undo. */64 char *_IO_save_base; /* Pointer to start of non-current get area. */65 char *_IO_backup_base; /* Pointer to first valid character of backup area */66 char *_IO_save_end; /* Pointer to end of non-current get area. */67
68 struct _IO_marker *_markers;
69
70 struct _IO_FILE *_chain;
71
72 int _fileno;
73 int _flags2;
74 __off_t _old_offset; /* This used to be _offset but it's too small. */75
76 /* 1+column number of pbase(); 0 is unknown. */77 unsigned short _cur_column;
78 signed char _vtable_offset;
79 char _shortbuf[1];
80
81 _IO_lock_t *_lock;
82 #ifdef _IO_USE_OLD_IO_FILE83 };
84
85 struct _IO_FILE_complete86 {
87 struct _IO_FILE _file;
88 #endif89 __off64_t _offset;
90 /* Wide character stream stuff. */91 struct _IO_codecvt *_codecvt;
92 struct _IO_wide_data *_wide_data;
93 struct _IO_FILE *_freeres_list;
94 void *_freeres_buf;
95 size_t __pad5;
96 int _mode;
97 /* Make sure we don't get into trouble again. */98 char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
99 };

_IO_marker定义为包含下一个_IO_marker指针,指向当前的FILE* _sbuf,以及标识的位置_pos。

104 /* A streammarker remembers a position in a buffer. */
105 struct _IO_marker {
106 struct _IO_marker *_next;
107 FILE *_sbuf;
108 /* If _pos >= 0
109 it points to _buf->Gbase()+_pos. FIXME comment */
110 /* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */
111 int _pos;
112 };

_IO_lock_t定义包含int lock; int cnt; void *owner;lock用来指定锁,cnt记录访问数量,owner执向对应的IO。

typedef struct { int lock; int cnt; void *owner; } _IO_lock_t;

fpos_t类型---file特定位置的类型

根据具体的offset位数进行定义

82 /* The type of the second argument to `fgetpos' and `fsetpos'.  */83 #ifndef __USE_FILE_OFFSET6484 typedef __fpos_t fpos_t;                                                                                                                             
85 #else86 typedef __fpos64_t fpos_t;
87 #endif88 #ifdef __USE_LARGEFILE6489 typedef __fpos64_t fpos64_t;
90 #endif

对应查看glibc/libio/bits/types/__fpos_t.h,区别__fpos64_t中__pos被定义为__off64_t __mbstate_t是转换状态信息,包括一个__count信息和__value信息(union结构体进行uint32位到4个字符char的转换)

7 /* The tag name of this struct is _G_fpos_t to preserve historic
8 C++ mangled names for functions taking fpos_t arguments.
9 That name should not be used in new code. */10 typedef struct _G_fpos_t11 {
12 __off_t __pos; //32位偏移,long int13 __mbstate_t __state;
14 } __fpos_t;

10 typedef struct _G_fpos64_t11 {
12 __off64_t __pos;//64位偏移,int_64t13 __mbstate_t __state;
14 } __fpos64_t;

//glibc/wcsmbs/bits/types/__mbstate_t.h8 #ifndef __WINT_TYPE__9 # define __WINT_TYPE__ unsigned int10 #endif11
12 /* Conversion state information. */13 typedef struct14 {
15 int __count;
16 union17 {
18 __WINT_TYPE__ __wch;
19 char __wchb[4];
20 } __value; /* Value so far. */21 } __mbstate_t;

size_t类型---unsigned int类型

这个就不需过多解释了,#define size_t unsigned int

标签:__,char,01,FILE,int,---,源码,IO,struct
From: https://blog.51cto.com/u_15830688/5920169

相关文章

  • 【Linux】循序渐进学运维-服务篇-LNMP环境部署
    文章目录前言一.LNMP的介绍二.什么是Fast-CGI三.部署实战安装php和mysqlnginx和php的结合a.编译nginxb.配置nginx与php的结合c.重启nginx让配置生效d.配置index......
  • 学成在线项目-精品推荐模块
    学成在线项目-精品推荐模块思路:大盒子包含三个小盒子,左边精品推荐,中间用小li包含小a,右边是修改盒子。分析完毕,开干。1、效果图如下2、html代码如下:<!DOCTYPEhtml......
  • 嵌入式-链表尾插法插入
    链表通过尾部插入#include<stdio.h>#include<stdlib.h>structTest{intdata;structTest*next;};printfLink(structTest*head){while(head!=NUL......
  • 软件技术基础(4)-小组介绍
    这个作业属于哪个课程软件技术基础第四次作业这个作业的目标成立小组,讨论并确定大作业的题目及分工小组成员严隽铭-2019330301032陈奕涛-2019330301007......
  • CF799E Aquarium Decoration - 贪心 - 堆 -
    题目链接:https://codeforces.com/contest/799/problem/E题解:考虑枚举都喜欢的个数\(s\),那么只有A喜欢的有\(k-s\)个,B喜欢的\(k-s\)个然后我只需要找所有的\(x\)......
  • ArcGIS插件-太乐地图
    在很多行业,打败你的往往不是竞争对手,而是你意想不到的其他因素。回想十年前,如果能预料到现在的处境,也许当时的心态和做法会有所不同。在多年前,市场上出现包括水经注、太乐......
  • 03-添加图片
    添加图片指定添加图片的位置加载所有图片//初始化图片privatevoidinitImage(){intnumber=1;//外循环---把内循环重复执行了4次......
  • TS.001. 安装 编译TS 的工具包
    本次学习,基于bilibili网,黑马程序员课程<黑马程序员前端TypeScript教程,TypeScript零基础入门到实战全套教程> 01.安装“编译TS”工具包的原因:Node.js/浏览器,只......
  • 安卓APP源码和设计报告——健身系统
    一、设计背景1.需求分析对于很多人来说拥有一副好身材能让自己增添不少魅力;对于爱吃而又担心自己发胖的人来说适当的运动健身是最好的选择。移动互联网时代,市场上“约跑”......
  • 安卓APP源码和设计报告——小说阅读器
    班级姓名学号答辩情况考核项满分成绩得分掌握计算机系统软硬件资源管理的原理,能够设计针对计算机领域复杂工程问题的解决方案,设计满足特定需求的软硬件系统,并具有对解决方......