前端學習C語言

2023-06-09 18:00:27

前端學習C語言 - 開篇

前端學習C語言有很多理由:工作、興趣或其他。

C 語言幾個常見的使用場景:

  • 作業系統開發:Linux 作業系統的核心就是主要由 C 語言編寫的。其他作業系統也廣泛使用 C 語言進行核心部分的開發。
  • 系統級開發和嵌入式程式設計:C 語言具有強大的底層控制能力和高效的程式碼執行效率,非常適合進行系統級開發和嵌入式程式設計。
  • 遊戲開發和圖形處理:許多遊戲引擎和各種圖形應用程式都是使用 C 語言進行開發的。這是因為 C 語言相對於其他高階語言具有更好的效能和更直接的硬體控制能力,可以實現複雜的計算和高效能的圖形處理。
  • 資料庫系統開發:C 語言的高效性使得其在資料庫系統的內部元件中使用非常廣泛。例如,Berkeley DB、MySQL、PostgreSQL 等資料庫管理系統都是使用 C 語言進行開發的。
  • 底層驅動開發:由於 C 語言直接操作記憶體和硬體資源,可以用來編寫驅動程式、裝置控制器和微控制器的韌體等低階別的程式碼。
  • 微控制器(跟硬體打交道)

C 語言還可以用於許多其他方面的開發,包括網路程式設計、訊號處理、人工智慧等。

第一個程式

在 linux 中建立一個 .c 檔案:

pjl@pjl-pc:~/$ cat hello.c
#include <stdio.h> // 標頭檔案。提供了 I/O 功能,例如下面用的 printf() 函數

// int 函數返回值的型別
// main 入口函數,通常有且只有一個。沒有 main 在 linux 中也可以編譯通過,比如 gcc -nostartfiles 
int main(void) {
    // 必須加分號,否則編譯會報錯
    printf("Hello World\n");
    return 0;
}

編譯

這裡使用 gcc 來編譯 c。

Tip:gcc 代表GNU Compiler Collection,是一個開源的編譯器集合,由GNU專案開發。它主要用於編譯C和C++等程式語言的原始碼,並生成可執行程式

然後安裝 gcc:

// 更新源
pjl@pjl-pc:~/$ sudo apt update
// 安裝 gcc
pjl@pjl-pc:~/$ sudo apt-get install gcc

通過 gcc -v 確認以安裝:

pjl@pjl-pc:~/$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
....
gcc version 9.3.0 (Ubuntu 9.3.0-10kylin2)

編譯 hello.c 生成可執行檔案 hello,通常沒有擴充套件名,直接執行可執行檔案,輸出 Hello World。就像這樣:

pjl@pjl-pc:~/$ gcc hello.c -o hello

pjl@pjl-pc:~/$ ls
hello  hello.c  stdio.h

// 直接執行
pjl@pjl-pc:~/$ ./hello
Hello World

例如故意去掉 printf() 函數後的分號,編譯就會報錯。就像這樣:

pjl@pjl-pc:~/$ gcc hello.c -o hello
hello.c: In function ‘main’:
hello.c:4:28: error: expected ‘;’ before ‘return’
    4 |     printf("Hello World\n")
      |                            ^
      |                            ;
    5 |     return 0;
      |     ~~~~~~

Tip: 筆者找了兩款線上編寫 c 的環境,直接點選執行即可檢視結果。語法錯誤也無需等待編譯後檢視。:

  • lightly - 點選線上使用,使用微信掃一下即可登入,通過雲能儲存自己的專案。
  • dotcpp - 執行一次需要等20秒,可能為了緩解伺服器壓力。

標頭檔案

<stdio.h> 是 C 標準庫的標頭檔案之一,包含了許多與標準輸入輸出流(stdin、stdout 和 stderr)相關的函數和常數定義。

常見的函數包括:

  • printf() 和 fprintf():格式化輸出函數,可以將內容輸出到終端或檔案中;
  • scanf() 和 fscanf():格式化讀取函數,可以從終端或檔案中讀取輸入資料;
  • fgets() 和 fputs():以行為單位進行讀寫,可以讀寫字串;
  • fgetc() 和 fputc():以字元為單位進行讀寫;
  • fseek() 和 ftell():檔案定位函數,用於在檔案中移動位置以及得到檔案當前位置。
    此外,<stdio.h> 標頭檔案還包含許多輸入和輸出流相關的常數和宏定義,例如常見的 stdin、stdout、stderr 流物件指標等等。

總之,<stdio.h> 是 C 語言程式中使用最頻繁的標頭檔案之一,提供了強大的 I/O 功能支援,方便程式設計師完成輸入輸出操作。

在 Linux 系統中,<stdio.h> 一般存放在 /usr/include 目錄下

pjl@pjl-pc:~/$ sudo find / -name stdio.h
輸入密碼
find: ‘/run/user/1000/gvfs’: 許可權不夠
/opt/linux-stable/tools/include/nolibc/stdio.h
/opt/linux-stable/arch/powerpc/boot/stdio.h
// stdio.h 就是這個
/usr/include/stdio.h
/usr/include/x86_64-linux-gnu/bits/stdio.h
/usr/share/python3-pycparser/fake_libc_include/stdio.h

基本資料型別

要儲存資料,就得申請記憶體,就得告訴作業系統要申請多少位元組,於是 c 語言就是通過不同的型別申請記憶體。

基本資料型別有:

空型別 void,常用於函數返回值,或指標,不會用於變數
字元型
數值型
  實型 - 表示小數
    單精度 float   精確到小數點6位
    雙精度 doubble 精確到小數點15位,表示的數也更大
  整型
    短整型
        有符號短整型
        無符號短整型
    整型
        有符號整型
        無符號整型
    長整型
        有符號長整型
        無符號長整型

重點說一下整型。其中無符號整數型別(unsigned int)只能表示非負整數,有符號整型則可以表示正數和負數。

# 無符號
unsigned int variable_name;

# 有符號
int variable_name;

型別所佔位元組

位元組是記憶體中最基本單元。

每個位元組由8位元組成,每一位將只有兩種可能的狀態:1或0。因此,一個位元組可以表示256個不同的值(2^8=256),包括從0到255的所有數位。

Tip:由於計算機晶片上只有兩個狀態,通常為高電平低電平,因此計算機只能處理0和1。雖然二進位制數系統看起來比較簡單,但它可以用來表示任意數位、字元和其他型別的資料。例如,整數和浮點數可以用二進位制數表示,字串可以將字元轉換為二進位制程式碼並儲存在記憶體中。因此,雖然計算機只能使用0和1,但它們可以處理和儲存各種不同型別的資料。

在C語言中,通常使用16進位製表示記憶體地址,比如 0x1000x101。把每個位元組比作一個房間,記憶體中有太多房間,16進位制比10進位制數位看起來要小點,比如同樣是數位10,16進位制就能表示16個房間。

十進位制
0 1 2 3 4 5 6 7 8 9 在加1 變成10

二進位制
0 1 在加1 變成10

八進位制
0 1 2 3 4 5 6 7 在加1 變成10

十六進位制
0 1 2 3 4 5 6 7 8 9 A B C D E F 在加1 10

比如 long 在 64位元系統中佔8個位元組,在32位元系統中佔4個位元組。可以通過 sizeof 計算每種型別在系統中所佔位元組數。就像這樣:

// 程式碼
pjl@pjl-pc:~/$ cat demo-4.c

#include <stdio.h>

int main() {
    printf("char型別所佔位元組數為:%zu\n", sizeof(char));
    printf("short型別所佔位元組數為:%zu\n", sizeof(short));
    printf("int型別所佔位元組數為:%zu\n", sizeof(int));
    printf("long型別所佔位元組數為:%zu\n", sizeof(long));
    printf("float型別所佔位元組數為:%zu\n", sizeof(float));
    printf("double型別所佔位元組數為:%zu\n", sizeof(double));
    printf("long long型別所佔位元組數為:%zu\n", sizeof(long long));
    return 0;
}
// 編譯
pjl@pjl-pc:~/$ gcc demo-4.c -o demo-4

// 執行可執行檔案
pjl@pjl-pc:~/$ ./demo-4
char型別所佔位元組數為:1
short型別所佔位元組數為:2
int型別所佔位元組數為:4
long型別所佔位元組數為:8
float型別所佔位元組數為:4
double型別所佔位元組數為:8
long long型別所佔位元組數為:8

Tip: sizeof 是一個關鍵字,雖然用法和函數類似,如果sizeof()是函數,那麼 sizeof() 中的 a++ 就會執行,將結果作為實參傳入 sizeof,那麼結果應該是 12,然而結果是 11。sizeof(a++) 等同於 sizeof(int)

#include <stdio.h>

int main(void) {
    int a = 10;
    a++;
    printf("%lu\n", sizeof(a++));
    printf("%d\n", a);
    return 0;
}
/*
4
11
*/

型別的範圍

我們首先詳細分析char能表示的範圍,其他型別計算的方法也類似。

char

char,佔1個位元組,也就是8位元。

無符號,最小是8位元都是0,也就是0,最大就是8位元全是1,也就是255。計算過程如下:

// 8位元都是1
1111 1111

// 加1得到 2^8 - 1,即255
+ 1

1 0000 0000 = 2^8 = Math.pow(2, 8) = 256 

256 - 1 = 255

Tip: 比如二進位制 1000 就是 Math.pow(2, 3),也就是8。

無符合 char 的範圍是 0 ~ 255,共 256 種。

有符號,最高位(即最左側)0 表示正數,1 表示負數。正數則是 0111 1111,也就是 127。

// 0 表示正數
0111 1111

+1 

1000 0000 = 2^7 = 128

128 - 1 = 127

負數則是 1000 0000,而不是 1111 1111(通常我們認為負的值越大,就越小)。假如是後者,有符號的範圍就是 -127 ~ 127,共255中可能,而無符號有256中可能。

1111 1111

// 只看這7位
 111 1111

+1

1000 0000 = 2^7 = 128

128 - 1 = 127

少的一個在這裡,一個正0,一個負0,數學中沒有這個說法,所以在計算機中是這麼規定的,最小數是 1000 0000,也就是 -128。

// 正0
0000 0000

// 負0
1000 0000

有符合 char 的範圍是 -128 ~ 127,也是 256 種。

有符號整型
singed char                      1                     -2^7(-128) ~ 2^7-1(127)
short int 或 short               2                     -2^15 ~ 2^15 -1
int                              4                     -2^31 ~ 2^31 -1
long 或 long int                 4(32位元) 8(64位元)    -2^31 ~ 2^31 -1
long long 或 long long int       8                     -2^63 ~ 2^63 -1

Tip: short 和 short int 等價;long 和 long int 等價;long long 和 long long int 等價。

無符號整型
unsinged char              1                     0~2^8 -1 (255)
unsinged short             2                     0~2^16 -1(65535)
unsinged int               4                     0~2^32 -1(4294 9672 95)
unsinged long              4(32位元) 8(64位元)    0~2^32 -1
unsinged long long         8                     0~2^64 -1
浮點

float 是4個位元組,32位元,範圍是 -3.40282347e+38 ~ 3.40282347e+38。最大有38個數。

unsinged int 同樣也是 4個位元組,範圍卻只有 10個數。

同樣是 4 個位元組,為何 float 能表示的數更大?

這是因為它的表示方法不一樣:最左側 1 位表示符號,中間 8 位8 位表示指數,最後 23 位為尾數。符號位用來表示數位的正負,指數位則表示小數點在有效數位中向左或向右移動多少位(即階碼),而尾數位則包含實際的有效數位

單精度浮點(float)數採用了分數形式的科學計數法(即尾數和指數分別表示大數整數部分和小數部分的方式)來表示實數,但由於單精度浮點數的尾數只有 23 位,而指數只有 8 位,因此這種近似值可能會存在精度誤差,導致與原來的值略有不同。

雙精度浮點數(double)和單精度 float 一樣由三部分組成。雙精度浮點數使用更多的位數表示指數尾數,因此可以表示更廣闊範圍的實數,並具有更高的精度。

長雙精度浮點數(long double)也由三部分組成:符號位、指數和尾數。長雙精度浮點數的規格並沒有在 IEEE 754 中具體規定。因此這一點取決於不同實現及其所用硬體平臺的架構。在 x86 架構下,一般將 long double 定義為 80 位或者 128 位,而在 ARM 架構下則分別將其定義為 96 位和 128 位。通常情況下它的儲存長度要比雙精度浮點數更長,同時在精度方面也有所提升。

練習

char的計算
#include <stdio.h>

int main(void) {
    char a = -128;
    char num = a -1;
    printf("%d \n", num);
}

答案是 127。過程如下:

  1. num 是 char 型別,範圍是 -128 ~ 127,所以不可能是 -129
  2. 計算機中,有許多處理負數的方式,其中二補數是最常見和普遍的一種。
  3. -128 原始碼是 1000 0000,取反碼 1111 1111(標誌位不動,其他取反。0變1,1變0),反碼加1得二補數 1000 0000
原始碼 1000 0000
反碼 1111 1111
二補數 1 1000 0000 —— 由於只有七位,刪除最高位(1000 0000)得到 000 0000
     1000 0000
  1. -1 的二補數是 1111 1111:
原始碼 1000 0001
反碼 1111 1110
二補數 1111 1111
  1. 兩個二補數相加得 0111 1111,也就是 127
1000 0000
1111 1111
1 0111 1111 —— 只有8位元,刪除最高位
0111 1111 
有符號轉無符號
pjl@pjl-pc:~/$ cat demo-3.c
#include <stdio.h>

int main(void) {
   int i = -20;
   unsigned int j = 10;
   if(i + j > 0){
       printf("i + j > 0\n");
   }
   printf("%u\n", i + j);

}

結果是:4294967286。

pjl@pjl-pc:~/$ gcc demo-3.c -o demo-3
pjl@pjl-pc:~/$ ./demo-3
i + j > 0
4294967286

解答過程:i是有符號int,j是無符號int,需要將有符號轉為無符號。i是負數,得轉為二補數,最高位就不再表示符號,需要參與計算,二補數轉為十進位制是 4294967276,在加上 10 就是結果。

-20 

原始碼 10000000 00000000 00000000 00010100
反碼 11111111 11111111 11111111 11101011
二補數 11111111 11111111 11111111 11101100

現在最高位也得參與運算,開啟 windows 的計算器,從`檢視`進入`程式設計師`,選擇`二進位制`,將二補數貼上,在點選`十進位制`,得到4294967276

Tip:型別不同,比如 char + int,把1個位元組的 char 轉為 4 個位元組的 int 很好理解。就是範圍小的轉為範圍大的。比如有符號char 的範圍是 -128~127,無符號 char 的範圍是 0~255,計算機認為無符號的255比有符號的127更大!?

int的計算
#include <stdio.h>

int main(void) {
   unsigned int a = 3;
   printf("%u\n", -1 * a);
}

結果是 4294967293

結果分析:

  • -1 轉為二補數,二補數對應的十進位制:4294967295
  • 4294967295*3 結果12884901885,12884901885的二進位制是 1011 11111111 11111111 11111111 11111101
  • int 就4個位元組,也就是32位元,這裡是36位元,超出int。刪除最高4位元,得到 11111111 11111111 11111111 11111101,轉為十進位制就是 4294967293。
-1

原碼:10000000 00000000 00000000 00000001
反碼:11111111 11111111 11111111 11111110
二補數:11111111 11111111 11111111 11111111

二補數對應的十進位制:4294967295

4294967295*3

1011 11111111 11111111 11111111 11111101

刪除高4位元,值保留int的32位元

11111111 11111111 11111111 11111101
小數的二進位制表示

小數1.5625的二進位制表示?

答案:1.1001。步驟如下:

首先,將1.5625轉化為二進位制整數部分1。

然後,將小數部分0.5625乘以2,得到1.125。將其整數部分1新增到二進位制小數部分的末尾,得到1.1。

繼續將小數部分0.125乘以2,得到0.25。將其整數部分0新增到二進位制小數部分的末尾,得到1.10。

繼續將小數部分0.25乘以2,得到0.50。將其整數部分0新增到二進位制小數部分的末尾,得到1.100。

最後,將小數部分0.50繼續乘以2,得到1.00。將其整數部分1新增到二進位制小數部分的末尾,得到1.1001。

因此,1.5625的二進位制表示為1.1001

擴充套件

計算機如何把人類理解的資訊轉為0和1

將人類理解的資訊轉換成0和1,需要使用編碼方式來表示不同型別的資訊。這個過程通常稱為數位化。

例如,對於文字資訊,可以使用ASCII編碼或Unicode編碼將每個字元對映到一個二進位制數位。比如字母「A」在ASCII編碼中對應的二進位制數位是01000001,字母「B」對應的是01000010等等。通過這種方式,計算機可以識別並處理文字資訊。

對於影象和音訊等複雜的資訊,數位化的過程更為複雜,需要使用更加高階的編碼方式和演演算法來實現。例如,JPEG、PNG等格式用於儲存圖片,MP3、AAC等格式用於儲存音訊。這些格式都會將影象和音訊分割成小塊並使用壓縮演演算法來減小檔案大小,以節省儲存空間和傳輸頻寬,並且保持足夠的質量以滿足人類對影象和聲音的要求。

總之,將人類理解的資訊轉換成0和1,是通過使用不同的編碼方式來表示資料,從而使計算機能夠理解和處理這些資料。

stdio.h 標頭檔案

將該檔案匯出:

pjl@pjl-pc:~/$ cat /usr/include/stdio.h > stdio.h

stdio.h 檔案一共 875 行,完整內容如下,例如 printf 等函數就在裡面:

/* Define ISO C stdio on top of C++ iostreams.
   Copyright (C) 1991-2020 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <https://www.gnu.org/licenses/>.  */

/*
 *	ISO C99 Standard: 7.19 Input/output	<stdio.h>
 */

#ifndef _STDIO_H
#define _STDIO_H	1

#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
#include <bits/libc-header-start.h>

__BEGIN_DECLS

#define __need_size_t
#define __need_NULL
#include <stddef.h>

#define __need___va_list
#include <stdarg.h>

#include <bits/types.h>
#include <bits/types/__fpos_t.h>
#include <bits/types/__fpos64_t.h>
#include <bits/types/__FILE.h>
#include <bits/types/FILE.h>
#include <bits/types/struct_FILE.h>

#ifdef __USE_GNU
# include <bits/types/cookie_io_functions_t.h>
#endif

#if defined __USE_XOPEN || defined __USE_XOPEN2K8
# ifdef __GNUC__
#  ifndef _VA_LIST_DEFINED
typedef __gnuc_va_list va_list;
#   define _VA_LIST_DEFINED
#  endif
# else
#  include <stdarg.h>
# endif
#endif

#if defined __USE_UNIX98 || defined __USE_XOPEN2K
# ifndef __off_t_defined
# ifndef __USE_FILE_OFFSET64
typedef __off_t off_t;
# else
typedef __off64_t off_t;
# endif
# define __off_t_defined
# endif
# if defined __USE_LARGEFILE64 && !defined __off64_t_defined
typedef __off64_t off64_t;
# define __off64_t_defined
# endif
#endif

#ifdef __USE_XOPEN2K8
# ifndef __ssize_t_defined
typedef __ssize_t ssize_t;
# define __ssize_t_defined
# endif
#endif

/* The type of the second argument to `fgetpos' and `fsetpos'.  */
#ifndef __USE_FILE_OFFSET64
typedef __fpos_t fpos_t;
#else
typedef __fpos64_t fpos_t;
#endif
#ifdef __USE_LARGEFILE64
typedef __fpos64_t fpos64_t;
#endif

/* The possibilities for the third argument to `setvbuf'.  */
#define _IOFBF 0		/* Fully buffered.  */
#define _IOLBF 1		/* Line buffered.  */
#define _IONBF 2		/* No buffering.  */


/* Default buffer size.  */
#define BUFSIZ 8192


/* The value returned by fgetc and similar functions to indicate the
   end of the file.  */
#define EOF (-1)


/* The possibilities for the third argument to `fseek'.
   These values should not be changed.  */
#define SEEK_SET	0	/* Seek from beginning of file.  */
#define SEEK_CUR	1	/* Seek from current position.  */
#define SEEK_END	2	/* Seek from end of file.  */
#ifdef __USE_GNU
# define SEEK_DATA	3	/* Seek to next data.  */
# define SEEK_HOLE	4	/* Seek to next hole.  */
#endif


#if defined __USE_MISC || defined __USE_XOPEN
/* Default path prefix for `tempnam' and `tmpnam'.  */
# define P_tmpdir	"/tmp"
#endif


/* Get the values:
   L_tmpnam	How long an array of chars must be to be passed to `tmpnam'.
   TMP_MAX	The minimum number of unique filenames generated by tmpnam
		(and tempnam when it uses tmpnam's name space),
		or tempnam (the two are separate).
   L_ctermid	How long an array to pass to `ctermid'.
   L_cuserid	How long an array to pass to `cuserid'.
   FOPEN_MAX	Minimum number of files that can be open at once.
   FILENAME_MAX	Maximum length of a filename.  */
#include <bits/stdio_lim.h>


/* Standard streams.  */
extern FILE *stdin;		/* Standard input stream.  */
extern FILE *stdout;		/* Standard output stream.  */
extern FILE *stderr;		/* Standard error output stream.  */
/* C89/C99 say they're macros.  Make them happy.  */
#define stdin stdin
#define stdout stdout
#define stderr stderr

/* Remove file FILENAME.  */
extern int remove (const char *__filename) __THROW;
/* Rename file OLD to NEW.  */
extern int rename (const char *__old, const char *__new) __THROW;

#ifdef __USE_ATFILE
/* Rename file OLD relative to OLDFD to NEW relative to NEWFD.  */
extern int renameat (int __oldfd, const char *__old, int __newfd,
		     const char *__new) __THROW;
#endif

#ifdef __USE_GNU
/* Flags for renameat2.  */
# define RENAME_NOREPLACE (1 << 0)
# define RENAME_EXCHANGE (1 << 1)
# define RENAME_WHITEOUT (1 << 2)

/* Rename file OLD relative to OLDFD to NEW relative to NEWFD, with
   additional flags.  */
extern int renameat2 (int __oldfd, const char *__old, int __newfd,
		      const char *__new, unsigned int __flags) __THROW;
#endif

/* Create a temporary file and open it read/write.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
#ifndef __USE_FILE_OFFSET64
extern FILE *tmpfile (void) __wur;
#else
# ifdef __REDIRECT
extern FILE *__REDIRECT (tmpfile, (void), tmpfile64) __wur;
# else
#  define tmpfile tmpfile64
# endif
#endif

#ifdef __USE_LARGEFILE64
extern FILE *tmpfile64 (void) __wur;
#endif

/* Generate a temporary filename.  */
extern char *tmpnam (char *__s) __THROW __wur;

#ifdef __USE_MISC
/* This is the reentrant variant of `tmpnam'.  The only difference is
   that it does not allow S to be NULL.  */
extern char *tmpnam_r (char *__s) __THROW __wur;
#endif


#if defined __USE_MISC || defined __USE_XOPEN
/* Generate a unique temporary filename using up to five characters of PFX
   if it is not NULL.  The directory to put this file in is searched for
   as follows: First the environment variable "TMPDIR" is checked.
   If it contains the name of a writable directory, that directory is used.
   If not and if DIR is not NULL, that value is checked.  If that fails,
   P_tmpdir is tried and finally "/tmp".  The storage for the filename
   is allocated by `malloc'.  */
extern char *tempnam (const char *__dir, const char *__pfx)
     __THROW __attribute_malloc__ __wur;
#endif


/* Close STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fclose (FILE *__stream);
/* Flush STREAM, or all streams if STREAM is NULL.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fflush (FILE *__stream);

#ifdef __USE_MISC
/* Faster versions when locking is not required.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern int fflush_unlocked (FILE *__stream);
#endif

#ifdef __USE_GNU
/* Close all streams.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern int fcloseall (void);
#endif


#ifndef __USE_FILE_OFFSET64
/* Open a file and create a new stream for it.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern FILE *fopen (const char *__restrict __filename,
		    const char *__restrict __modes) __wur;
/* Open a file, replacing an existing stream with it.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern FILE *freopen (const char *__restrict __filename,
		      const char *__restrict __modes,
		      FILE *__restrict __stream) __wur;
#else
# ifdef __REDIRECT
extern FILE *__REDIRECT (fopen, (const char *__restrict __filename,
				 const char *__restrict __modes), fopen64)
  __wur;
extern FILE *__REDIRECT (freopen, (const char *__restrict __filename,
				   const char *__restrict __modes,
				   FILE *__restrict __stream), freopen64)
  __wur;
# else
#  define fopen fopen64
#  define freopen freopen64
# endif
#endif
#ifdef __USE_LARGEFILE64
extern FILE *fopen64 (const char *__restrict __filename,
		      const char *__restrict __modes) __wur;
extern FILE *freopen64 (const char *__restrict __filename,
			const char *__restrict __modes,
			FILE *__restrict __stream) __wur;
#endif

#ifdef	__USE_POSIX
/* Create a new stream that refers to an existing system file descriptor.  */
extern FILE *fdopen (int __fd, const char *__modes) __THROW __wur;
#endif

#ifdef	__USE_GNU
/* Create a new stream that refers to the given magic cookie,
   and uses the given functions for input and output.  */
extern FILE *fopencookie (void *__restrict __magic_cookie,
			  const char *__restrict __modes,
			  cookie_io_functions_t __io_funcs) __THROW __wur;
#endif

#if defined __USE_XOPEN2K8 || __GLIBC_USE (LIB_EXT2)
/* Create a new stream that refers to a memory buffer.  */
extern FILE *fmemopen (void *__s, size_t __len, const char *__modes)
  __THROW __wur;

/* Open a stream that writes into a malloc'd buffer that is expanded as
   necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
   and the number of characters written on fflush or fclose.  */
extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __THROW __wur;
#endif


/* If BUF is NULL, make STREAM unbuffered.
   Else make it use buffer BUF, of size BUFSIZ.  */
extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __THROW;
/* Make STREAM use buffering mode MODE.
   If BUF is not NULL, use N bytes of it for buffering;
   else allocate an internal buffer N bytes long.  */
extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
		    int __modes, size_t __n) __THROW;

#ifdef	__USE_MISC
/* If BUF is NULL, make STREAM unbuffered.
   Else make it use SIZE bytes of BUF for buffering.  */
extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
		       size_t __size) __THROW;

/* Make STREAM line-buffered.  */
extern void setlinebuf (FILE *__stream) __THROW;
#endif


/* Write formatted output to STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fprintf (FILE *__restrict __stream,
		    const char *__restrict __format, ...);
/* Write formatted output to stdout.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int printf (const char *__restrict __format, ...);
/* Write formatted output to S.  */
extern int sprintf (char *__restrict __s,
		    const char *__restrict __format, ...) __THROWNL;

/* Write formatted output to S from argument list ARG.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
		     __gnuc_va_list __arg);
/* Write formatted output to stdout from argument list ARG.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
/* Write formatted output to S from argument list ARG.  */
extern int vsprintf (char *__restrict __s, const char *__restrict __format,
		     __gnuc_va_list __arg) __THROWNL;

#if defined __USE_ISOC99 || defined __USE_UNIX98
/* Maximum chars of output to write in MAXLEN.  */
extern int snprintf (char *__restrict __s, size_t __maxlen,
		     const char *__restrict __format, ...)
     __THROWNL __attribute__ ((__format__ (__printf__, 3, 4)));

extern int vsnprintf (char *__restrict __s, size_t __maxlen,
		      const char *__restrict __format, __gnuc_va_list __arg)
     __THROWNL __attribute__ ((__format__ (__printf__, 3, 0)));
#endif

#if __GLIBC_USE (LIB_EXT2)
/* Write formatted output to a string dynamically allocated with `malloc'.
   Store the address of the string in *PTR.  */
extern int vasprintf (char **__restrict __ptr, const char *__restrict __f,
		      __gnuc_va_list __arg)
     __THROWNL __attribute__ ((__format__ (__printf__, 2, 0))) __wur;
extern int __asprintf (char **__restrict __ptr,
		       const char *__restrict __fmt, ...)
     __THROWNL __attribute__ ((__format__ (__printf__, 2, 3))) __wur;
extern int asprintf (char **__restrict __ptr,
		     const char *__restrict __fmt, ...)
     __THROWNL __attribute__ ((__format__ (__printf__, 2, 3))) __wur;
#endif

#ifdef __USE_XOPEN2K8
/* Write formatted output to a file descriptor.  */
extern int vdprintf (int __fd, const char *__restrict __fmt,
		     __gnuc_va_list __arg)
     __attribute__ ((__format__ (__printf__, 2, 0)));
extern int dprintf (int __fd, const char *__restrict __fmt, ...)
     __attribute__ ((__format__ (__printf__, 2, 3)));
#endif


/* Read formatted input from STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fscanf (FILE *__restrict __stream,
		   const char *__restrict __format, ...) __wur;
/* Read formatted input from stdin.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int scanf (const char *__restrict __format, ...) __wur;
/* Read formatted input from S.  */
extern int sscanf (const char *__restrict __s,
		   const char *__restrict __format, ...) __THROW;

/* For historical reasons, the C99-compliant versions of the scanf
   functions are at alternative names.  When __LDBL_COMPAT is in
   effect, this is handled in bits/stdio-ldbl.h.  */
#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT
# ifdef __REDIRECT
extern int __REDIRECT (fscanf, (FILE *__restrict __stream,
				const char *__restrict __format, ...),
		       __isoc99_fscanf) __wur;
extern int __REDIRECT (scanf, (const char *__restrict __format, ...),
		       __isoc99_scanf) __wur;
extern int __REDIRECT_NTH (sscanf, (const char *__restrict __s,
				    const char *__restrict __format, ...),
			   __isoc99_sscanf);
# else
extern int __isoc99_fscanf (FILE *__restrict __stream,
			    const char *__restrict __format, ...) __wur;
extern int __isoc99_scanf (const char *__restrict __format, ...) __wur;
extern int __isoc99_sscanf (const char *__restrict __s,
			    const char *__restrict __format, ...) __THROW;
#  define fscanf __isoc99_fscanf
#  define scanf __isoc99_scanf
#  define sscanf __isoc99_sscanf
# endif
#endif

#ifdef	__USE_ISOC99
/* Read formatted input from S into argument list ARG.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,
		    __gnuc_va_list __arg)
     __attribute__ ((__format__ (__scanf__, 2, 0))) __wur;

/* Read formatted input from stdin into argument list ARG.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
     __attribute__ ((__format__ (__scanf__, 1, 0))) __wur;

/* Read formatted input from S into argument list ARG.  */
extern int vsscanf (const char *__restrict __s,
		    const char *__restrict __format, __gnuc_va_list __arg)
     __THROW __attribute__ ((__format__ (__scanf__, 2, 0)));

/* Same redirection as above for the v*scanf family.  */
# if !__GLIBC_USE (DEPRECATED_SCANF)
#  if defined __REDIRECT && !defined __LDBL_COMPAT
extern int __REDIRECT (vfscanf,
		       (FILE *__restrict __s,
			const char *__restrict __format, __gnuc_va_list __arg),
		       __isoc99_vfscanf)
     __attribute__ ((__format__ (__scanf__, 2, 0))) __wur;
extern int __REDIRECT (vscanf, (const char *__restrict __format,
				__gnuc_va_list __arg), __isoc99_vscanf)
     __attribute__ ((__format__ (__scanf__, 1, 0))) __wur;
extern int __REDIRECT_NTH (vsscanf,
			   (const char *__restrict __s,
			    const char *__restrict __format,
			    __gnuc_va_list __arg), __isoc99_vsscanf)
     __attribute__ ((__format__ (__scanf__, 2, 0)));
#  elif !defined __REDIRECT
extern int __isoc99_vfscanf (FILE *__restrict __s,
			     const char *__restrict __format,
			     __gnuc_va_list __arg) __wur;
extern int __isoc99_vscanf (const char *__restrict __format,
			    __gnuc_va_list __arg) __wur;
extern int __isoc99_vsscanf (const char *__restrict __s,
			     const char *__restrict __format,
			     __gnuc_va_list __arg) __THROW;
#   define vfscanf __isoc99_vfscanf
#   define vscanf __isoc99_vscanf
#   define vsscanf __isoc99_vsscanf
#  endif
# endif
#endif /* Use ISO C9x.  */


/* Read a character from STREAM.

   These functions are possible cancellation points and therefore not
   marked with __THROW.  */
extern int fgetc (FILE *__stream);
extern int getc (FILE *__stream);

/* Read a character from stdin.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int getchar (void);

#ifdef __USE_POSIX199506
/* These are defined in POSIX.1:1996.

   These functions are possible cancellation points and therefore not
   marked with __THROW.  */
extern int getc_unlocked (FILE *__stream);
extern int getchar_unlocked (void);
#endif /* Use POSIX.  */

#ifdef __USE_MISC
/* Faster version when locking is not necessary.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern int fgetc_unlocked (FILE *__stream);
#endif /* Use MISC.  */


/* Write a character to STREAM.

   These functions are possible cancellation points and therefore not
   marked with __THROW.

   These functions is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fputc (int __c, FILE *__stream);
extern int putc (int __c, FILE *__stream);

/* Write a character to stdout.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int putchar (int __c);

#ifdef __USE_MISC
/* Faster version when locking is not necessary.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern int fputc_unlocked (int __c, FILE *__stream);
#endif /* Use MISC.  */

#ifdef __USE_POSIX199506
/* These are defined in POSIX.1:1996.

   These functions are possible cancellation points and therefore not
   marked with __THROW.  */
extern int putc_unlocked (int __c, FILE *__stream);
extern int putchar_unlocked (int __c);
#endif /* Use POSIX.  */


#if defined __USE_MISC \
    || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
/* Get a word (int) from STREAM.  */
extern int getw (FILE *__stream);

/* Write a word (int) to STREAM.  */
extern int putw (int __w, FILE *__stream);
#endif


/* Get a newline-terminated string of finite length from STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
     __wur;

#if __GLIBC_USE (DEPRECATED_GETS)
/* Get a newline-terminated string from stdin, removing the newline.

   This function is impossible to use safely.  It has been officially
   removed from ISO C11 and ISO C++14, and we have also removed it
   from the _GNU_SOURCE feature list.  It remains available when
   explicitly using an old ISO C, Unix, or POSIX standard.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern char *gets (char *__s) __wur __attribute_deprecated__;
#endif

#ifdef __USE_GNU
/* This function does the same as `fgets' but does not lock the stream.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern char *fgets_unlocked (char *__restrict __s, int __n,
			     FILE *__restrict __stream) __wur;
#endif


#if defined __USE_XOPEN2K8 || __GLIBC_USE (LIB_EXT2)
/* Read up to (and including) a DELIMITER from STREAM into *LINEPTR
   (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
   NULL), pointing to *N characters of space.  It is realloc'd as
   necessary.  Returns the number of characters read (not including the
   null terminator), or -1 on error or EOF.

   These functions are not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation they are cancellation points and
   therefore not marked with __THROW.  */
extern __ssize_t __getdelim (char **__restrict __lineptr,
                             size_t *__restrict __n, int __delimiter,
                             FILE *__restrict __stream) __wur;
extern __ssize_t getdelim (char **__restrict __lineptr,
                           size_t *__restrict __n, int __delimiter,
                           FILE *__restrict __stream) __wur;

/* Like `getdelim', but reads up to a newline.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern __ssize_t getline (char **__restrict __lineptr,
                          size_t *__restrict __n,
                          FILE *__restrict __stream) __wur;
#endif


/* Write a string to STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fputs (const char *__restrict __s, FILE *__restrict __stream);

/* Write a string, followed by a newline, to stdout.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int puts (const char *__s);


/* Push a character back onto the input buffer of STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int ungetc (int __c, FILE *__stream);


/* Read chunks of generic data from STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern size_t fread (void *__restrict __ptr, size_t __size,
		     size_t __n, FILE *__restrict __stream) __wur;
/* Write chunks of generic data to STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern size_t fwrite (const void *__restrict __ptr, size_t __size,
		      size_t __n, FILE *__restrict __s);

#ifdef __USE_GNU
/* This function does the same as `fputs' but does not lock the stream.

   This function is not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation it is a cancellation point and
   therefore not marked with __THROW.  */
extern int fputs_unlocked (const char *__restrict __s,
			   FILE *__restrict __stream);
#endif

#ifdef __USE_MISC
/* Faster versions when locking is not necessary.

   These functions are not part of POSIX and therefore no official
   cancellation point.  But due to similarity with an POSIX interface
   or due to the implementation they are cancellation points and
   therefore not marked with __THROW.  */
extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
			      size_t __n, FILE *__restrict __stream) __wur;
extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,
			       size_t __n, FILE *__restrict __stream);
#endif


/* Seek to a certain position on STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fseek (FILE *__stream, long int __off, int __whence);
/* Return the current position of STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern long int ftell (FILE *__stream) __wur;
/* Rewind to the beginning of STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern void rewind (FILE *__stream);

/* The Single Unix Specification, Version 2, specifies an alternative,
   more adequate interface for the two functions above which deal with
   file offset.  `long int' is not the right type.  These definitions
   are originally defined in the Large File Support API.  */

#if defined __USE_LARGEFILE || defined __USE_XOPEN2K
# ifndef __USE_FILE_OFFSET64
/* Seek to a certain position on STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fseeko (FILE *__stream, __off_t __off, int __whence);
/* Return the current position of STREAM.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern __off_t ftello (FILE *__stream) __wur;
# else
#  ifdef __REDIRECT
extern int __REDIRECT (fseeko,
		       (FILE *__stream, __off64_t __off, int __whence),
		       fseeko64);
extern __off64_t __REDIRECT (ftello, (FILE *__stream), ftello64);
#  else
#   define fseeko fseeko64
#   define ftello ftello64
#  endif
# endif
#endif

#ifndef __USE_FILE_OFFSET64
/* Get STREAM's position.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);
/* Set STREAM's position.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fsetpos (FILE *__stream, const fpos_t *__pos);
#else
# ifdef __REDIRECT
extern int __REDIRECT (fgetpos, (FILE *__restrict __stream,
				 fpos_t *__restrict __pos), fgetpos64);
extern int __REDIRECT (fsetpos,
		       (FILE *__stream, const fpos_t *__pos), fsetpos64);
# else
#  define fgetpos fgetpos64
#  define fsetpos fsetpos64
# endif
#endif

#ifdef __USE_LARGEFILE64
extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence);
extern __off64_t ftello64 (FILE *__stream) __wur;
extern int fgetpos64 (FILE *__restrict __stream, fpos64_t *__restrict __pos);
extern int fsetpos64 (FILE *__stream, const fpos64_t *__pos);
#endif

/* Clear the error and EOF indicators for STREAM.  */
extern void clearerr (FILE *__stream) __THROW;
/* Return the EOF indicator for STREAM.  */
extern int feof (FILE *__stream) __THROW __wur;
/* Return the error indicator for STREAM.  */
extern int ferror (FILE *__stream) __THROW __wur;

#ifdef __USE_MISC
/* Faster versions when locking is not required.  */
extern void clearerr_unlocked (FILE *__stream) __THROW;
extern int feof_unlocked (FILE *__stream) __THROW __wur;
extern int ferror_unlocked (FILE *__stream) __THROW __wur;
#endif


/* Print a message describing the meaning of the value of errno.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern void perror (const char *__s);

/* Provide the declarations for `sys_errlist' and `sys_nerr' if they
   are available on this system.  Even if available, these variables
   should not be used directly.  The `strerror' function provides
   all the necessary functionality.  */
#include <bits/sys_errlist.h>


#ifdef	__USE_POSIX
/* Return the system file descriptor for STREAM.  */
extern int fileno (FILE *__stream) __THROW __wur;
#endif /* Use POSIX.  */

#ifdef __USE_MISC
/* Faster version when locking is not required.  */
extern int fileno_unlocked (FILE *__stream) __THROW __wur;
#endif


#ifdef __USE_POSIX2
/* Create a new stream connected to a pipe running the given command.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern FILE *popen (const char *__command, const char *__modes) __wur;

/* Close a stream opened by popen and return the status of its child.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int pclose (FILE *__stream);
#endif


#ifdef	__USE_POSIX
/* Return the name of the controlling terminal.  */
extern char *ctermid (char *__s) __THROW;
#endif /* Use POSIX.  */


#if (defined __USE_XOPEN && !defined __USE_XOPEN2K) || defined __USE_GNU
/* Return the name of the current user.  */
extern char *cuserid (char *__s);
#endif /* Use X/Open, but not issue 6.  */


#ifdef	__USE_GNU
struct obstack;			/* See <obstack.h>.  */

/* Write formatted output to an obstack.  */
extern int obstack_printf (struct obstack *__restrict __obstack,
			   const char *__restrict __format, ...)
     __THROWNL __attribute__ ((__format__ (__printf__, 2, 3)));
extern int obstack_vprintf (struct obstack *__restrict __obstack,
			    const char *__restrict __format,
			    __gnuc_va_list __args)
     __THROWNL __attribute__ ((__format__ (__printf__, 2, 0)));
#endif /* Use GNU.  */


#ifdef __USE_POSIX199506
/* These are defined in POSIX.1:1996.  */

/* Acquire ownership of STREAM.  */
extern void flockfile (FILE *__stream) __THROW;

/* Try to acquire ownership of STREAM but do not block if it is not
   possible.  */
extern int ftrylockfile (FILE *__stream) __THROW __wur;

/* Relinquish the ownership granted for STREAM.  */
extern void funlockfile (FILE *__stream) __THROW;
#endif /* POSIX */

#if defined __USE_XOPEN && !defined __USE_XOPEN2K && !defined __USE_GNU
/*  X/Open Issues 1-5 required getopt to be declared in this
   header.  It was removed in Issue 6.  GNU follows Issue 6.  */
# include <bits/getopt_posix.h>
#endif

/* Slow-path routines used by the optimized inline functions in
   bits/stdio.h.  */
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);

/* If we are compiling with optimizing read this file.  It contains
   several optimizing inline functions and macros.  */
#ifdef __USE_EXTERN_INLINES
# include <bits/stdio.h>
#endif
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
# include <bits/stdio2.h>
#endif
#ifdef __LDBL_COMPAT
# include <bits/stdio-ldbl.h>
#endif

__END_DECLS

#endif /* <stdio.h> included.  */