---
# System prepended metadata

title: C99 閱讀筆記
tags: [C]

---

---
title: C99 閱讀筆記
description: C99 標準規格書的閱讀筆記
tags: C
lang: zh_tw
---

# [C99 閱讀筆記](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)
[TOC]

# 前言
這篇筆記記錄閱讀規格書時所發現跟原本想法不同的部分, 而不是單純一篇翻譯文

> 只要這種格式的文字加上 LJP-TW 的署名, 都只是我自己的 mermer, 可能不是事實, 參考就好
> [name=LJP-TW]

# 3. Terms, definitions, and symbols
## 3.4.1 implementation-defined behavior
規格書中未規範、交由各家編譯器自行定義的行為
> EXAMPLE 
> An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.
> 
signed integer 右移時, 最高位要用 1 或 0 來填補, 規格書中沒有明確定義怎麼做

## 3.4.2 locale-specific behavior
依據當地語言、文化而有所不同的行為
> EXAMPLE
> An example of locale-specific behavior is whether the islower function returns true for characters other than the 26 lowercase Latin letters.
> 

> 應該是類英文字母體系國家會遇到這個問題 (e.g. 希臘文?)
> [name=LJP-TW]

## 3.4.3 undefined behavior
規範中沒定義的行為

## 3.4.4 unspecified behavior
> use of an unspecified value, or other behavior where this International Standard provides
two or more possibilities and imposes no further requirements on which is chosen in any
instance
>
規範中有提供好幾種可能的做法, 而未強制指定要用何種做法

> EXAMPLE 
> An example of unspecified behavior is the order in which the arguments to a function are evaluated
> 

## 3.6 byte
> NOTE 2
> A byte is composed of a contiguous sequence of bits, the number of which is implementation defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order
bit

C Standard 並沒有規範 byte 是 8 bits, 而是交給實作去定義

# 5. Environment
## 5.1.2.2.1 Program startup
> If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0] shall be the null character if the
program name is not available from the host environment. If the value of argc is
greater than one, the strings pointed to by argv[1] through argv[argc-1]
represent the program parameters

- `argc` 可以是 0
- `argv[0][0]` 可以是 NULL

[這篇](https://stackoverflow.com/questions/2794150/when-can-argv0-have-null)有給解釋

## 5.1.2.2.3 Program termination
這邊提到 `main()` 的 return 值
> If the return type is not compatible with int, the termination status returned to the host environment is unspecified.

## 5.1.2.3 Program execution
這邊有幾個名詞被提及

- `Side effects`:
    > Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all **side effects**, which are changes in the state of the execution environment

- `Sequence points`:
    > At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. (A summary of the sequence points is given in annex C.)
    - Annex C 中列出 `Sequence points` 定義
    - [這個網站](http://shihyu.github.io/books/ch16s03.html)有詳細說明

- `integer promotions`:
    - 以下程式碼
        ```c
        char c1, c2;
        ...
        c1 = c1 + c2;
        ```
        > the ‘‘integer promotions’’ require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum
        > 
        兩者要先提升為 int size 後再相加

- 以下程式碼, 因為浮點數有精度 roundoff 問題所以要多注意
    ```c
    double x, y, z;
    /* ... */
    x=(x*y)*z;    // not equivalent to x *=y*z;
    z=(x-y)+y;    // not equivalent to z=x;
    z=x+x*y;      // not equivalent to z=x*(1.0 + y);
    y=x/5.0;      // not equivalent to y=x*0.2;
    ```
    
    以下寫了個測試程式
    ```c
	#include <stdio.h>
	#define A 2.3
	#define B 10.3
	#define C 7.3
	
	int main()
	{
	    double a1 = A;
	    double b1 = B;
	    double c1 = C;
	    double a2 = A;
	    double b2 = B;
	    double c2 = C;
	
	    a1 = (a1 * b1) * c1;
	    a2 *= b2 * c2;
	
	    if (a1 == a2)
	        printf("a1 == a2\n");
	    else
	        printf("a1 != a2\n");
	
	}
    ```
    輸出是 `a1 != a2`, 但改一下 `A` `B` `C` 的值又有可能出現 `a1 == a2`
    
## 5.2.1.1 Trigraph sequences
Source code 中有以下 mapping table

都是連續三個字會對應成一個字

設計這個的原因是早期有一些裝置沒辦法輸入某些符號, 只能以此做為替代

目前 gcc 預設會忽略此特性, 要使用 `-trigraphs` 參數才能啟用

| Trigraph | Corresponding char
| -------- | -------- 
| `??=` | `#`
| `??(` | `[`
| `??/` | `\`
| `??)` | `]`
| `??'` | `^`
| `??<` | `{`
| `??!` | `|`
| `??>` | `}`
| `??-` | `~`

## 5.2.2 Character display semantics
- `active position`:
    是指在 display device 上會輸出下一個文字的位置, 若 `active position` 已經在最後一格了, 行為是 unspecified

- Alphabetic escape sequences:
    其中幾個比較有趣的
    - `\b`: backspace
    - `\v`: vertical tab

    以下程式碼:
	```c
	#include <stdio.h>
	
	int main()
	{
	    printf("horizontal\ttab\n");
	    printf("vertical\vtab\n");
	    printf("vertical & backspace\b\b\b\b\b\b\b\b\b\vtab\n");
	}
	```
    輸出如下
	```
	horizontal	tab
	vertical
	        tab
	vertical & backspace
	           tab
	```

## 5.2.4.2.2 Characteristics of floating types <float.h>
提到了 `FLT_ROUNDS` macro, 查看 `float.h` 原始碼
```c
/* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown.  */
/* ??? This is supposed to change with calls to fesetround in <fenv.h>.  */
#undef FLT_ROUNDS
#define FLT_ROUNDS 1
```

而規格書中也有註解
> Evaluation of FLT_ROUNDS correctly reflects any execution-time change of rounding mode through
the function fesetround in <fenv.h>.

詳細可以看[這篇](https://en.cppreference.com/w/c/numeric/fenv/feround)

:::danger
TBD. 本章節第9點之後(含)
:::

# 6. Language
## 6.2.1 Scopes of identifiers
> There are four kinds of scopes: function, file, block, and function prototype
> 
Scope 就四種
- function
- file
- block
- function prototype





