一、下载地址
如果你不想知道步骤,只想下载源码,这是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)
{
THOUSANDS_SEP_T thousands_sep = 0;
const char *grouping;
int done;
const UCHAR_T *f;
const UCHAR_T *lead_str_end;
const UCHAR_T *end_of_spec;
CHAR_T work_buffer[WORK_BUFFER_SIZE];
CHAR_T *workend;
va_list ap_save;
int nspecs_done;
int save_errno = errno;
int readonly_format = 0;
#ifdef ORIENT
ORIENT;
#endif
ARGCHECK (s, format);
#ifdef ORIENT
if (_IO_vtable_offset (s) == 0
&& _IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1)
!= (sizeof (CHAR_T) == 1 ? -1 : 1))
return EOF;
#endif
if (UNBUFFERED_P (s))
return buffered_vfprintf (s, format, ap, mode_flags);
done = 0;
grouping = (const char *) -1;
#ifdef __va_copy
__va_copy (ap_save, ap);
#else
ap_save = ap;
#endif
nspecs_done = 0;
#ifdef COMPILE_WPRINTF
f = lead_str_end = __find_specwc ((const UCHAR_T *) format);
#else
f = lead_str_end = __find_specmb ((const UCHAR_T *) format);
#endif
_IO_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);
_IO_flockfile (s);
outstring ((const UCHAR_T *) format,
lead_str_end - (const UCHAR_T *) format);
if (*f == L_('\0'))
goto all_done;
if (__glibc_unlikely (__printf_function_table != NULL
|| __printf_modifier_table != NULL
|| __printf_va_arg_table != NULL))
goto do_positional;
do
{
STEP0_3_TABLE;
STEP4_TABLE;
union printf_arg *args_value;
int is_negative;
union
{
unsigned long long int longlong;
unsigned long int word;
} number;
int base;
union printf_arg the_arg;
CHAR_T *string;
int alt = 0;
int space = 0;
int left = 0;
int showsign = 0;
int group = 0;
int is_long_double = 0;
int is_short = 0;
int is_long = 0;
int is_char = 0;
int width = 0;
int prec = -1;
int use_outdigits = 0;
UCHAR_T pad = L_(' ');
CHAR_T spec;
workend = work_buffer + WORK_BUFFER_SIZE;
JUMP (*++f, step0_jumps);
LABEL (flag_space):
space = 1;
JUMP (*++f, step0_jumps);
LABEL (flag_plus):
showsign = 1;
JUMP (*++f, step0_jumps);
LABEL (flag_minus):
left = 1;
pad = L_(' ');
JUMP (*++f, step0_jumps);
LABEL (flag_hash):
alt = 1;
JUMP (*++f, step0_jumps);
LABEL (flag_zero):
if (!left)
pad = L_('0');
JUMP (*++f, step0_jumps);
LABEL (flag_quote):
group = 1;
if (grouping == (const char *) -1)
{
#ifdef COMPILE_WPRINTF
thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
_NL_NUMERIC_THOUSANDS_SEP_WC);
#else
thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
#endif
grouping = _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);
LABEL (width_asterics):
{
const UCHAR_T *tmp;
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_('$'))
goto do_positional;
}
width = va_arg (ap, int);
if (width < 0)
{
width = -width;
pad = L_(' ');
left = 1;
}
}
JUMP (*f, step1_jumps);
LABEL (width):
width = read_int (&f);
if (__glibc_unlikely (width == -1))
{
__set_errno (EOVERFLOW);
done = -1;
goto all_done;
}
if (*f == L_('$'))
goto do_positional;
JUMP (*f, step1_jumps);
LABEL (precision):
++f;
if (*f == L_('*'))
{
const UCHAR_T *tmp;
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_('$'))
goto do_positional;
}
prec = va_arg (ap, int);
if (prec < 0)
prec = -1;
}
else if (ISDIGIT (*f))
{
prec = read_int (&f);
if (prec == -1)
{
__set_errno (EOVERFLOW);
done = -1;
goto all_done;
}
}
else
prec = 0;
JUMP (*f, step2_jumps);
LABEL (mod_half):
is_short = 1;
JUMP (*++f, step3a_jumps);
LABEL (mod_halfhalf):
is_short = 0;
is_char = 1;
JUMP (*++f, step4_jumps);
LABEL (mod_long):
is_long = 1;
JUMP (*++f, step3b_jumps);
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);
while (1)
{
process_arg (((struct printf_spec *) NULL));
process_string_arg (((struct printf_spec *) NULL));
LABEL (form_unknown):
if (spec == L_('\0'))
{
__set_errno (EINVAL);
done = -1;
goto all_done;
}
goto do_positional;
}
++nspecs_done;
#ifdef COMPILE_WPRINTF
f = __find_specwc ((end_of_spec = ++f));
#else
f = __find_specmb ((end_of_spec = ++f));
#endif
outstring (end_of_spec, f - end_of_spec);
}
while (*f != L_('\0'));
goto all_done;
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:
_IO_funlockfile (s);
_IO_cleanup_region_end (0);
return done;
}
3.4 还有很多汇编文件
在查东西的时候还发现源码里面有大量的汇编文件,比如glibc-2.34/sysdeps/x86_64/multiarch 目录下的文件: 即C文件里面又调用了汇编文件里面的方法。 我已经了解一些粗浅的C语言和汇编相关的知识了,但是看C语言源码中的C文件和汇编文件基本上还是看不懂,所以如果你不是钻研C语言源码的话,建议你直接放弃~
|