# C notes
###### tags: `C`
## [Why does calloc exists?](https://vorpus.org/blog/why-does-calloc-exist/)
Let memory allocator and OS have chance to optimize.
## [Why My Print Didn't Output Before a Segmentation Fault](https://blog.yelinaung.com/posts/what-happened-to-my-print/)
stdout => [The stream stdout is line-buffered when it points to a terminal](https://linux.die.net/man/3/stdout)
stderr => [always unbuffered](https://linux.die.net/man/3/stderr)
=> does not define in C spec.
The buffering mode of the standard streams (or any other stream) can be changed using the setbuf(3) or setvbuf(3) call.
```lang=c
#include <stdio.h>
void setbuf(FILE * restrict stream,
char * restrict buf);
int setvbuf(FILE * restrict stream,
char * restrict buf,
int mode, size_t size);
```
##### mode
_IOFBF: full buffered
_IOLBF: line buffered
_IONBF: unbuffered
Except that it returns no value, the setbuf function is equivalent to the setvbuf
function invoked with the values _IOFBF for mode and BUFSIZ for size, or (if buf
is a null pointer), with the value _IONBF for mode.
which means
```lang=c
void setbuf(s, b)
{
if (b) setbuf(s, b, _IOFBF, BUFSIZ);
else setvbuf(s, b, _IONBF, 0);
}
```
BUFSIZ is standard macro.
The value of the macro BUFSIZ shall be at least 256.
## Floating point
3 types: float/double/long double(Subset next type)
Promoted: unchanged
Demoted:
1. can be represented exactly in the new type -> unchanged
2. in the range -> either the nearest higher or nearest lower representable value, chosen in an implementation-defined manner.
3. outside the range -> behavior is undefined
The accuracy of the floating-point operations (+, -, *, /) and of the library functions in
<math.h> and <complex.h> that return floating-point results is implementationdefined. The implementation may state that the accuracy is unknown.
沒有保證實作是參照 IEEE 754,Annex F 說明: 如果有照標準實作,會定義 __STDC_IEC_559__,但實際在 Win11 測試,MSVC & GCC 都沒有定義。
IEC 60559 是 IEEE 754 的國際標準化版本。
https://stackoverflow.com/questions/31181897/status-of-stdc-iec-559-with-modern-c-compilers
IEEE754 定義的浮點數計算並不能用單一公式計算,exponent bit 都是 0 時,會變成 subnormal float. 目的是處理很小的數字。
C99 也有定義 float 的分類,還有 macro fpclassify 可以判斷類別
```
FP_INFINITE
FP_NAN
FP_NORMAL
FP_SUBNORMAL
FP_ZERO
```
Compiler 也可以實作額外的分類,但 macro 必須是 FP_ 開頭 & 大寫。
規格書真嚴謹。
NaN 分兩種: quiet NaN & signaling NaN(defined in IEEE754)
In addition to normalized floating-point numbers ( f1 > 0 if x ≠ 0), floating types may be
able to contain other kinds of floating-point numbers, such as subnormal floating-point
numbers (x ≠ 0, e = emin, f1 = 0) and unnormalized floating-point numbers (x ≠ 0,
e > emin, f1 = 0), and values that are not floating-point numbers, such as infinities and
NaNs. A NaN is an encoding signifying Not-a-Number. A quiet NaN propagates
through almost every arithmetic operation without raising a floating-point exception; a
signaling NaN generally raises a floating-point exception when occurring as an arithmetic operand.
https://stackoverflow.com/questions/18118408/what-is-the-difference-between-quiet-nan-and-signaling-nan
The values of operations with floating operands and values subject to the usual arithmetic
conversions and of floating constants are evaluated to a format whose range and precision
may be greater than required by the type. The use of evaluation formats is characterized
by the implementation-defined value of FLT_EVAL_METHOD:
-1 indeterminable;
0 evaluate all operations and constants just to the range and precision of the type;
1 evaluate operations and constants of type float and double to the
range and precision of the double type, evaluate long double
operations and constants to the range and precision of the long double
type;
2 evaluate all operations and constants to the range and precision of thelong double type.
ChatGPT explain above
這段是 C 語言標準(C99 以後) 對浮點運算中「中間運算精度」的定義,關鍵字是 FLT_EVAL_METHOD,其值決定 浮點運算在編譯/執行時實際使用的精度,可能高於原始型別。
🔧 目的
允許編譯器使用更高精度(如 x86 FPU 使用 80-bit extended precision)來進行浮點運算,減少誤差累積,但這樣會造成:
運算結果不符合開發者預期(例如 float 運算結果卻有 double 精度)
運算順序改變時,數值結果不同(因為中間精度不同)
🔍 FLT_EVAL_METHOD 值含義:
值 意義
-1 無法得知,可能每次編譯結果不同(非可移植,避用)
0 所有運算與常數皆使用其原始類型精度,例如 float 保持 float 精度
1 float 和 double 升級為 double 精度,long double 保持原樣
2 所有浮點常數與運算皆升級為 long double 精度
< 0 且 ≠ -1 實作自定義行為,非標準定義
試了幾個 online c compiler 結果都是 0