怎样找到C语言本身的源码(比如stdio),对学习C语言有帮助吗?
一、下载地址
如果你不想知道步骤,只想下载源码,这是2021-08-01发布的glibc-3.24的下载地址:
https://ftp.gnu.org/gnu/libc/glibc-2.34.tar.gz
二、怎么知道从哪里下载
stackoverflow上有一个问题:Where can I find the source code for all the C standard libraries?,其中有一个答案提到了glibc官网。
在glibc官网页面点这里:
在详情页面搜索
download
来到了gnu的ftp服务器,然后按版本号或年份去找对应的版本,比如2011年的在这里,点击就可以下载了:
三、C本身的源码对学习C语言有帮助吗
3.1 我的答案是:帮助不大
在上面的stackoverflow的答案中有这么一句话,意思是:所有人都建议你不要去看C语言的具体实现。(前人走弯路的经验啊)
我没信这个邪,偏要去下载。然后我看到:
3.2 printf
源码
printf
方法定义在glibc-2.34/stdio-common/printf.c
文件中,代码如下:
int
__printf (const char *format, ...)
{va_list arg;int done;va_start (arg, format);done = __vfprintf_internal (stdout, format, arg, 0);va_end (arg);return done;
}
里面调用了__vfprintf_internal
方法
3.3 __vfprintf_internal
的源码
__vfprintf_internal
方法定义在glibc-2.34/stdio-common/vfprintf-internal.c
文件中,__vfprintf_internal
是vfprintf
方法的别名(# define vfprintf __vfprintf_internal
),vfprintf
方法的代码如下(我已经看不懂这段300多行的代码了):
int
vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
{/* The character used as thousands separator. */THOUSANDS_SEP_T thousands_sep = 0;/* The string describing the size of groups of digits. */const char *grouping;/* Place to accumulate the result. */int done;/* Current character in format string. */const UCHAR_T *f;/* End of leading constant string. */const UCHAR_T *lead_str_end;/* Points to next format specifier. */const UCHAR_T *end_of_spec;/* Buffer intermediate results. */CHAR_T work_buffer[WORK_BUFFER_SIZE];CHAR_T *workend;/* We have to save the original argument pointer. */va_list ap_save;/* Count number of specifiers we already processed. */int nspecs_done;/* For the %m format we may need the current `errno' value. */int save_errno = errno;/* 1 if format is in read-only memory, -1 if it is in writable memory,0 if unknown. */int readonly_format = 0;/* Orient the stream. */
#ifdef ORIENTORIENT;
#endif/* Sanity check of arguments. */ARGCHECK (s, format);#ifdef ORIENT/* Check for correct orientation. */if (_IO_vtable_offset (s) == 0&& _IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1)!= (sizeof (CHAR_T) == 1 ? -1 : 1))/* The stream is already oriented otherwise. */return EOF;
#endifif (UNBUFFERED_P (s))/* Use a helper function which will allocate a local temporary bufferfor the stream and then call us again. */return buffered_vfprintf (s, format, ap, mode_flags);/* Initialize local variables. */done = 0;grouping = (const char *) -1;
#ifdef __va_copy/* This macro will be available soon in gcc's <stdarg.h>. We need itsince on some systems `va_list' is not an integral type. */__va_copy (ap_save, ap);
#elseap_save = ap;
#endifnspecs_done = 0;#ifdef COMPILE_WPRINTF/* Find the first format specifier. */f = lead_str_end = __find_specwc ((const UCHAR_T *) format);
#else/* Find the first format specifier. */f = lead_str_end = __find_specmb ((const UCHAR_T *) format);
#endif/* Lock stream. */_IO_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);_IO_flockfile (s);/* Write the literal text before the first format. */outstring ((const UCHAR_T *) format,lead_str_end - (const UCHAR_T *) format);/* If we only have to print a simple string, return now. */if (*f == L_('\0'))goto all_done;/* Use the slow path in case any printf handler is registered. */if (__glibc_unlikely (__printf_function_table != NULL|| __printf_modifier_table != NULL|| __printf_va_arg_table != NULL))goto do_positional;/* Process whole format string. */do{STEP0_3_TABLE;STEP4_TABLE;union printf_arg *args_value; /* This is not used here but ... */int is_negative; /* Flag for negative number. */union{unsigned long long int longlong;unsigned long int word;} number;int base;union printf_arg the_arg;CHAR_T *string; /* Pointer to argument string. */int alt = 0; /* Alternate format. */int space = 0; /* Use space prefix if no sign is needed. */int left = 0; /* Left-justify output. */int showsign = 0; /* Always begin with plus or minus sign. */int group = 0; /* Print numbers according grouping rules. */int is_long_double = 0; /* Argument is long double/ long long int. */int is_short = 0; /* Argument is short int. */int is_long = 0; /* Argument is long int. */int is_char = 0; /* Argument is promoted (unsigned) char. */int width = 0; /* Width of output; 0 means none specified. */int prec = -1; /* Precision of output; -1 means none specified. *//* This flag is set by the 'I' modifier and selects the use of the`outdigits' as determined by the current locale. */int use_outdigits = 0;UCHAR_T pad = L_(' ');/* Padding character. */CHAR_T spec;workend = work_buffer + WORK_BUFFER_SIZE;/* Get current character in format string. */JUMP (*++f, step0_jumps);/* ' ' flag. */LABEL (flag_space):space = 1;JUMP (*++f, step0_jumps);/* '+' flag. */LABEL (flag_plus):showsign = 1;JUMP (*++f, step0_jumps);/* The '-' flag. */LABEL (flag_minus):left = 1;pad = L_(' ');JUMP (*++f, step0_jumps);/* The '#' flag. */LABEL (flag_hash):alt = 1;JUMP (*++f, step0_jumps);/* The '0' flag. */LABEL (flag_zero):if (!left)pad = L_('0');JUMP (*++f, step0_jumps);/* The '\'' flag. */LABEL (flag_quote):group = 1;if (grouping == (const char *) -1){#ifdef COMPILE_WPRINTFthousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,_NL_NUMERIC_THOUSANDS_SEP_WC);
#elsethousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
#endifgrouping = _NL_CURRENT (LC_NUMERIC, GROUPING);if (*grouping == '\0' || *grouping == CHAR_MAX
#ifdef COMPILE_WPRINTF|| thousands_sep == L'\0'
#else|| *thousands_sep == '\0'
#endif)grouping = NULL;}JUMP (*++f, step0_jumps);LABEL (flag_i18n):use_outdigits = 1;JUMP (*++f, step0_jumps);/* Get width from argument. */LABEL (width_asterics):{const UCHAR_T *tmp; /* Temporary value. */tmp = ++f;if (ISDIGIT (*tmp)){int pos = read_int (&tmp);if (pos == -1){__set_errno (EOVERFLOW);done = -1;goto all_done;}if (pos && *tmp == L_('$'))/* The width comes from a positional parameter. */goto do_positional;}width = va_arg (ap, int);/* Negative width means left justified. */if (width < 0){width = -width;pad = L_(' ');left = 1;}}JUMP (*f, step1_jumps);/* Given width in format string. */LABEL (width):width = read_int (&f);if (__glibc_unlikely (width == -1)){__set_errno (EOVERFLOW);done = -1;goto all_done;}if (*f == L_('$'))/* Oh, oh. The argument comes from a positional parameter. */goto do_positional;JUMP (*f, step1_jumps);LABEL (precision):++f;if (*f == L_('*')){const UCHAR_T *tmp; /* Temporary value. */tmp = ++f;if (ISDIGIT (*tmp)){int pos = read_int (&tmp);if (pos == -1){__set_errno (EOVERFLOW);done = -1;goto all_done;}if (pos && *tmp == L_('$'))/* The precision comes from a positional parameter. */goto do_positional;}prec = va_arg (ap, int);/* If the precision is negative the precision is omitted. */if (prec < 0)prec = -1;}else if (ISDIGIT (*f)){prec = read_int (&f);/* The precision was specified in this case as an extremelylarge positive value. */if (prec == -1){__set_errno (EOVERFLOW);done = -1;goto all_done;}}elseprec = 0;JUMP (*f, step2_jumps);/* Process 'h' modifier. There might another 'h' following. */LABEL (mod_half):is_short = 1;JUMP (*++f, step3a_jumps);/* Process 'hh' modifier. */LABEL (mod_halfhalf):is_short = 0;is_char = 1;JUMP (*++f, step4_jumps);/* Process 'l' modifier. There might another 'l' following. */LABEL (mod_long):is_long = 1;JUMP (*++f, step3b_jumps);/* Process 'L', 'q', or 'll' modifier. No other modifier isallowed to follow. */LABEL (mod_longlong):is_long_double = 1;is_long = 1;JUMP (*++f, step4_jumps);LABEL (mod_size_t):is_long_double = sizeof (size_t) > sizeof (unsigned long int);is_long = sizeof (size_t) > sizeof (unsigned int);JUMP (*++f, step4_jumps);LABEL (mod_ptrdiff_t):is_long_double = sizeof (ptrdiff_t) > sizeof (unsigned long int);is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);JUMP (*++f, step4_jumps);LABEL (mod_intmax_t):is_long_double = sizeof (intmax_t) > sizeof (unsigned long int);is_long = sizeof (intmax_t) > sizeof (unsigned int);JUMP (*++f, step4_jumps);/* Process current format. */while (1){process_arg (((struct printf_spec *) NULL));process_string_arg (((struct printf_spec *) NULL));LABEL (form_unknown):if (spec == L_('\0')){/* The format string ended before the specifier is complete. */__set_errno (EINVAL);done = -1;goto all_done;}/* If we are in the fast loop force entering the complicatedone. */goto do_positional;}/* The format is correctly handled. */++nspecs_done;/* Look for next format specifier. */
#ifdef COMPILE_WPRINTFf = __find_specwc ((end_of_spec = ++f));
#elsef = __find_specmb ((end_of_spec = ++f));
#endif/* Write the following constant string. */outstring (end_of_spec, f - end_of_spec);}while (*f != L_('\0'));/* Unlock stream and return. */goto all_done;/* Hand off processing for positional parameters. */
do_positional:done = printf_positional (s, format, readonly_format, ap, &ap_save,done, nspecs_done, lead_str_end, work_buffer,save_errno, grouping, thousands_sep, mode_flags);all_done:/* Unlock the stream. */_IO_funlockfile (s);_IO_cleanup_region_end (0);return done;
}
3.4 还有很多汇编文件
在查东西的时候还发现源码里面有大量的汇编文件,比如glibc-2.34/sysdeps/x86_64/multiarch
目录下的文件:
即C文件里面又调用了汇编文件里面的方法。
我已经了解一些粗浅的C语言和汇编相关的知识了,但是看C语言源码中的C文件和汇编文件基本上还是看不懂,所以如果你不是钻研C语言源码的话,建议你直接放弃~
怎样找到C语言本身的源码(比如stdio),对学习C语言有帮助吗?相关推荐
- c语言远控源码,远控鼠标!C语言简单小程序:舍友要砸电脑了,送源码!
关注<一碳科技>有更多干货等着你哦! 远控鼠标 远控鼠标,顾名思义就是远程控制鼠标,听起来就有些复杂对不对?是的,有些人一听到这个词,就会感觉要实现远控鼠标是一件很麻烦的事情,但其实不是的 ...
- c语言物流管理信息系统,[源码和文档分享]基于C语言的物流配送管理信息系统...
一 需求分析 系统需要实现的功能如下: (一)各种基本数据的录入 配送路线基本信息录入 路线经停站点基本信息录入 站点经停车辆基本信息录入 其它信息录入 (二)各种基本数据的修改 即:允许对已经录入的 ...
- 易语言和python混合编程_易语言python交互源码,不需要把易语言编译成静态库
.版本 2 .支持库 spec .子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行 .局部变量 mothod, PyMethodDef .局部变量 创建结果, 整数型 .局部变量 错 ...
- Go 语言 bytes.Buffer 源码详解之1
转载地址:Go 语言 bytes.Buffer 源码详解之1 - lifelmy的博客 前言 前面一篇文章 Go语言 strings.Reader 源码详解,我们对 strings 包中的 Reade ...
- 易语言和html交互,易语言网页交互源码
易语言网页交互源码系统结构:浏览器消息处理函数,滚动到底部,添加文本,呼叫窗口函数地址_,设置窗口信息_,寻找子窗口_,DLL命令1, ======窗口程序集1 || ||------__启动窗口_创 ...
- c调用易语言串口,易语言串口API源码
易语言串口API源码系统结构:ReadCommPure,BuildCommDCB,CreateFilea,关闭句柄a,SetCommState,ReadFileA,GetCommState,Write ...
- 字符串固定长度 易语言_易语言字符串操作源码
易语言字符串操作源码 系统结构:字符串_取长度,字符串_取中间,字符串_取左边,字符串_取右边,字符串_替换,到宽字符,到多字节,取文本数据地址,取字节集数据地址,MultiByteToWideCha ...
- 易语言修改虚拟机硬盘id_易语言本地虚拟机源码
易语言本地虚拟机源码 系统结构:显示工具路径,读入未用分区,获取分区位置,设置虚拟机分区,读入虚拟分区,操作并显示日志,处理显示错误提示,取驱动器文本列表,写配置目录,处理结果文件,格式化时间,取Do ...
- 易语言模拟器中控源码 全新手游模拟器通用中控源码, 适用于各种游戏, 源码现成的只需要更换游戏就可以用哦
易语言模拟器中控源码 全新手游模拟器通用中控源码, 适用于各种游戏, 源码现成的只需要更换游戏就可以用哦, 带修改教程,带讲解说明, 简单易懂不需要别人指导在家可以自学. 降低新手编写多线程中控的门槛 ...
最新文章
- linux下各种格式的压缩包的压缩、解压方法
- 【深度学习】transformer 真的快要取代计算机视觉中的 CNN 吗?
- c语言实现循环单链表
- android5.1 显示方向,Android5.1 Settings.apk定制显示选项
- android中常见的错误及解决办法
- python课堂笔记之django-day02(7)
- 苹果公司官方证实,iPhone12延期!
- 人人都应该学习并成为优秀的产品经理,因为你要为《你自己》这个产品负责到底
- 吉林大学计算机学院刘衍衍教授,周柚-吉林大学计算机科学与技术学院
- 基于ssm的空气质量监测系统
- Python+Selenium爬虫实现:草料二维码微信群活码自动更新,提升社群运营效率
- Win10 ipv6无网络访问权限怎么解决
- cousera上的华盛顿机器学习专项课程的案例学习学习经历分享
- 全网最详细最基础的网络安全入门教程
- IO流_IO流小结图解
- L5W2作业1 Emojify!
- 苹果微信验证失败,安卓成功_苹果将​​在微软失败的地方成功吗?
- 芝加哥德保大学计算机排名怎么样,伊利诺伊大学芝加哥分校计算机科学computer science专业排名第201~250名(2020THE泰晤士高等教育世界大学排名)...
- 优质供应商选择标准_供应商选择原则
- 乔布斯《遗失的访谈》全文:尘封16年的预见
热门文章
- 调用淘宝接口有每IP数量/时间限制-负载均衡解决
- AngularJS中多种过滤器的使用
- USACO fact4, spin
- 通过unix时间戳获得两个时间相差多少自然日
- GPRS智能净水器方案
- MSCOCO数据集下载安装---image_caption
- stack expects each tensor to be equal size, but got [3, 40, 160] at entry 0 and [4, 40, 160] at entr
- Navicat 连接 sqlserver 带端口号配置
- python字典格式 城市和行政编码映射表(无序)
- Android ImageView 选中状态