---
# System prepended metadata

title: C KeyWord
tags: [EMBEDDED_C]

---

# C KeyWord
###### tags: `EMBEDDED_C`
- [ ]  static(注意用在變數跟函式的差別)
- [ ]  extern
- [ ]  volatile
- [ ]  const
- [ ]  union
- [ ]  enum
- [ ]  struct(注意裡面變數順序會影響實際size這點)
- [ ]  function pointer
- [ ]  sizeof(這有蠻多易錯小細節)
- [ ]  call back function(OOP)

- [ ]  call by reference\value(注意C\C++差異)
- [ ]  atomic (I guess that is unsigned long long)
- [ ]  typedef
- [ ]  sizeof
- [ ]  inline 

# C lib
- [ ]  malloc / calloc
- [ ]  free
## C Key word(Storage Class)

## static 
  * static function
    > 單一檔案看到symbol
  * static global var
    > 單一檔案看到symbol
    ```
    因此對global變數加static的用意是希望限制該變數scope在此source file內而不是整個程式
    ```
* static local var
    > memory 不會隨著stack消失,存在bss或data sectuin 
    ![](https://i.imgur.com/9XAyFP5.png)
  * static local variable without init.
    > layout in .bss section
    > static int y;
    > you need to zeroize this section in the startup code.
  * static variable with init.
    > layout in .data section
    > static int y = 7;
    > Reference: https://www.geeksforgeeks.org/memory-layout-of-c-program/
## Memory Layout
+++++ High Adress +++++

* Stack
    *  儲存哪種型態的memory
    `C 語言中的「參數、函數返回點、區域變數、框架指標」等資料，被儲存在堆疊段中，這個區段會隨著函數呼叫的層次數目而增長或縮短。如果這個區段成長過頭，導致堆疊段覆蓋到堆積段的空間時，就被稱為堆疊溢位 (Stack Overflow)，這種情況通常是因為程式進行遞回呼叫，卻又沒有正確判斷終止條件，導致遞迴層數過多所產生的錯誤情況`
* Heap
    * 儲存哪種型態的memory
    `假如我們用 malloc() 函數分配記憶體空間，則 malloc() 函數會從堆積段 (heap) 中找到一個夠大的區塊，分配給 malloc() 函數傳回。然後，當我們使用 free() 函數釋放記憶體空間時，則原先分配的區塊會歸還給堆積系統，此時通常會在堆積的記憶空間中留下一個空洞。在程式的執行過程當中，malloc() 與 free() 會交錯執行，因而導致整個堆積區塊開始產生許多空洞，這將會造成記憶體管理的負擔，假如堆積系統無法找到足夠大的堆積區塊時，就會造成記憶體分配失敗的情況，因而導致程式無法繼續執行。`
* bss(unintialized data)
* Intialized 
* Global
* Text

+++++ Low Adress +++++


## const
> const 宣告是用來告訴編譯器該變數不該被更改, read only
### const with variable

### const with pointer
>Hint:從右邊看到左,  const在*左邊或右邊來判斷修飾的變數
```clike=
    const int * foo;       // 一個 pointer，指向 const int 變數。
    int const * foo;       // 一個 pointer，指向 const int 變數。
    int * const foo;       // 一個 const pointer，指向 int 變數。
    int const * const foo; // 一個 const pointer，指向 const int 變數
```
### Accessing fixed memory locations
Embedded systems are often characterized by requiring the programmer to access a specific memory location. On a certain project it is required to set an integer variable at the absolute address 0x67a9 to the value 0xaa55.
```cpp=
int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa55;
```
A more obfuscated approach is:
```cpp=
*(int * const)(0x67a9) = 0xaa55;
```

## volatile
 > 給 compiler 看的, 告知compiler 這個global variable在其他地方會被通知

1. 對於非volatile變數, 編譯過後有可能因為優化的關係導致一些不預期結果, 
因此加入volatile使得每次存取變數都是對此變數的位址存取
用volatile的變數 你讀寫他都去記憶體
非volatile你讀寫他會去Cache (CPU的暫存器)

> 1. Ensure the program can obatin the value which is synchronized and without.
> 2. Avoid the aggressive optimization by compiler.

Q8.1:

( b ) Can a pointer be volatile? Explain your answer.
( c ) What is wrong with the following function?:
```cpp=
int square(volatile int * ptr)
{
    return *ptr * *ptr ;
}
```
A8.1:

( b ) Yes. Although this is not very common. An example is when an interrupt
service routine modies a pointer to a buer.
( c ) This one is wicked. The intent of the code is to return the square of
the value pointed to by *ptr. However, since *ptr points to a volatile
parameter, the compiler will generate code that looks something like this:
```cpp=
int square( volatile int * ptr)
{
    int a , b ;
    a = ∗ ptr;
    b = ∗ ptr;
    return a * b;
}
```
Since it is possible for the value of *ptr to change unexpectedly, it is possible
for a and b to be dierent. Consequently, this code could return a number thatis not a square! The correct way to code this is:
```cpp=
    long square(volatile int * ptr)
    {
        int a;
        a = * ptr;
        return a ∗ a ;
}
```

### Can a parameter be both const and volatile?
> YES
#### e.g 1:
在嵌入式系統中,硬體的register的值(status of register)是只能被讀取,而且不應該被軟體寫入。
```clike=
unsigned int const volatile *status_reg; // assume these are assigned to point to the 
unsigned char const volatile *recv_reg;  //   correct hardware addresses


#define UART_CHAR_READY 0x00000001

int get_next_char()
{
    while ((*status_reg & UART_CHAR_READY) == 0) {
        // do nothing but spin
    }

    return *recv_reg;
}

```
我們可以舉UART serial port當一個例子,當我們在傳輸資料的時候會需要
比如說transmit register可以作為一個flag通知是否可以接受新的register,每次在對這個flag判讀的時候,我們需要得當最新當下硬體的register的status,相反的cached value在前一次的讀取是無法得知當下的

””假設你要(監看)一個 CPU flag 時就是不錯的時機

[Stack Overflow Reference](https://stackoverflow.com/questions/4592762/difference-between-const-const-volatile)

## extern Symbol
> 給 compiler 看的, 告訴compiler 待會消失的symbol會link
```
告訴compiler此變數或function已經存在, 另compiler去其他地方找定義
```
> Tell compiler that this symbol is defined by other files and linker can find it in likage time.
## Inline
>行內函式是一種編譯最佳化的方式，對於一些內容較為簡短又常使用的函式，編譯器在程式設計師的建議 (使用關鍵字inline) 下，可以將指定的函式插入並取代每一處呼叫該函式的地方，做展開編譯，從而減少呼叫函式耗費的時間
* 30s
在呼叫函式時會有額外的資源負擔，一些小函式，可以「建議」編譯器設為 inline 行內，若建議被採納，該函式會自動在呼叫點展現為程式碼，例如：
### Inline vs macro
## Marco
## BitFilds
## Union
## Structure
- [ ]  Union vs Structure
- [ ]  floating point && Endian Check
- [ ]  C語言中的 struct 在函數調用的時候 如何傳遞？
- [ ]  如何struct太大會怎樣？ 我說stack overflow.
how OS detects stack overflow？ 說了半天，好像他不是很滿意


## Null Pointer
1. To initialize a pointer variable when that pointer variable isn’t assigned any valid memory address yet.
1. To check for a null pointer before accessing any pointer variable. By doing so, we can perform error handling in pointer related code e.g. dereference pointer variable only if it’s not NULL.
1. To pass a null pointer to a function argument when we don’t want to pass any valid memory address.


---

## Segmentfault
>當記憶體存取到超出程式可用的範圍時，或是去寫入 read-only 的記憶體區段，就會產生 segmentation fault 的錯誤。






---

## Sizeof()
### <font style="color:red" >how to find sizeof(data type) without using sizeof()</font>
> Use the feature of pointer in C   [reference](https://www.geeksforgeeks.org/how-to-find-size-of-array-in-cc-without-using-sizeof-operator/)


### 64bit

```clike=
sizeof(string)       = 8
sizeof(char)         = 1
sizeof(p)            = 8
sizeof(short)        = 2
sizeof(int)          = 4
sizeof(long)         = 8
sizeof(long long)    = 8
sizeof(size_t)       = 8
sizeof(double)       = 8
sizeof(long double)  = 16
```

### 32bit
```clike=
sizeof(string)       = 4
sizeof(char)         = 1
sizeof(p)            = 4  //指標
sizeof(short)        = 2
sizeof(int)          = 4  //怕因環境影響程式,絕大多數64,32的編譯器是一樣大
sizeof(long)         = 4      
sizeof(long long)    = 8
sizeof(size_t)       = 4
sizeof(double)       = 8
sizeof(long double)  = 12    //看作long+double = 4 + 8 =12
```