owned this note
owned this note
Published
Linked with GitHub
---
tags: note, book section, c/c++, concept
---
# C/C++ Concept
## argc/argv
```cpp
int main(int argc, char *argv[]) {...
or
int main(int argc, char **argv) {...
```
```cpp
int main(int argc, char * argv[]) {
if (argv[1] == "yes"); // Wrong, compares two pointers
if (strcmp(argv[1], "yes") == 0); // This compares what the pointers point to
if (std::string(argv[1]) == "yes"); // Works fine
if (argv[1] == std::string("yes")); // Works fine
// Easy-mode
std::vector<std::string> args(argv, argv+argc);
for (size_t i = 1; i < args.size(); ++i) {
if (args[i] == "yes") {
// do something
}
}
}
```
### Reference
- [C/C++ 程式設計教學:main 函數讀取命令列參數,argc 與 argv 用法](https://blog.gtwang.org/programming/c-cpp-tutorial-argc-argv-read-command-line-arguments/ "C/C++ 程式設計教學:main 函數讀取命令列參數,argc 與 argv 用法")
- [Checking argv\[\] against a string? (C++)](https://stackoverflow.com/questions/5183203/checking-argv-against-a-string-c)
## error
> - 要注意到 exception 要 include \<exception> ,但是 runtime_error 等其他的衍生 error 是要 include \<stdexcept>
> - errno 要 #include \<errno.h>
> - strerror 要 #include \<cstring>
- errno
- 是一個共用變數,存放錯誤代碼
- [errno.h](https://zh.wikipedia.org/wiki/Errno.h)
```c
printf("something went wrong with! (%d)\n", errno);
```
- strerror()
```c
printf("something went wrong with! %s\n", strerror(errno));
```
- [How to know what the 'errno' means?](https://stackoverflow.com/questions/503878/how-to-know-what-the-errno-means)
- %m
- 也可以直接用這個,不用帶參數
```c
printf("something went wrong with! %m\n");
```
- throw
- how to
```cpp
#include <stdexcept>
char const * configfile = "hardcode.cfg";
std::string const anotherfile = get_file();
throw std::runtime_error(std::string("Failed: ") + configfile);
throw std::runtime_error("Error: " + anotherfile);
```
```cpp
// 也可以直些丟 string
...
throw "Division by zero condition!";
...
// 但是 catch 就要對應
} catch (const char* msg) {
cerr << msg << endl;
}
```
```cpp
// 可以分別 catch
} catch( const std::invalid_argument& e ) {
// do stuff with exception...
} catch( const std::runtime_error& e ) {
// do stuff with exception...
}
// 也可以抓所有 exception 或 type
} catch (const std::exception& e) {
} catch( ... ) { };
```
- reference
- [How to throw std::exceptions with variable messages?](https://stackoverflow.com/questions/12261915/how-to-throw-stdexceptions-with-variable-messages)
- [C++ Exception Handling](https://www.tutorialspoint.com/cplusplus/cpp_exceptions_handling.htm)
- [How to throw a C++ exception](https://stackoverflow.com/questions/8480640/how-to-throw-a-c-exception)
- use e.what get message
```cpp
} catch (std::exception &e) {
cout << "exception: " << e.what() << "\n";
}
```
- 沒辦法直接丟 exception
```cpp
throw new exception("queue is empty");
// error: no matching function for call to 'std::exception:exception(const char[15])'
// solution
#include <stdexcept>
std::logic_error e("queue is empty");
throw std::exception(e);
```
- reference
- [error: no matching function for call to 'std::exception:exception(const char[15])'](https://www.programmersought.com/article/24443125477/)
- multiple catch
```cpp
try
{
// throws something
}
catch ( const MostSpecificException& e )
{
// handle custom exception
}
catch ( const LessSpecificException& e )
{
// handle custom exception
}
catch ( const std::exception& e )
{
// standard exceptions
}
catch ( ... )
{
// everything else
}
```
- reference
- [Multiple Catch Block Example](https://www.decodejava.com/cpp-multiple-catch.htm)
- [Catch Multiple Custom Exceptions? - C++](https://stackoverflow.com/questions/2512931/catch-multiple-custom-exceptions-c)
- 自己建立一個
- class
- struct
- 繼承 runtime_error,當然也可以是其他的,不過不建議直接寫 exception 因為這樣要自己實作比較多東西 (e.g. what())
- create constructor with 你想要的參數
- 並且這個 constructor 也繼承 parent constructor 同時去呼叫他
- errorCode 以 member 的方式取用
```cpp
struct CSVException : std::runtime_error {
CSVException(const std::string &msg, const WEBAPI_ERR &err) :
std::runtime_error{msg},
errorCode{err}
{
}
WEBAPI_ERR errorCode;
};
```
- reference
- [Custom C++ Exceptions for Beginners](http://peterforgacs.github.io/2017/06/25/Custom-C-Exceptions-For-Beginners/)
- [Custom exception](https://riptutorial.com/cplusplus/example/23640/custom-exception)
## header file
### "", <>
- In practice, the difference is in the location where the preprocessor searches for the included file.
- For `#include <filename>` the preprocessor searches in an implementation dependent manner, normally in search directories pre-designated by the compiler/IDE. This method is normally used to include standard library header files.
- For `#include "filename"` the preprocessor searches first in the same directory as the file containing the directive, and then follows the search path used for the `#include <filename>` form. This method is normally used to include programmer-defined header files.
### reference
- [(c + +) 的標頭檔](https://docs.microsoft.com/zh-tw/cpp/cpp/header-files-cpp?view=msvc-160)
- [c++ - What is the difference between #include \<filename> and #include "filename"? - Stack Overflow](https://stackoverflow.com/questions/21593/what-is-the-difference-between-include-filename-and-include-filename)
## initialize
### (), {}, =
- 它是統一的初始化,用標準術語來說是直接括號初始化。
- 除非存在接受`std::initializer_list`的建構函式,否則使用大括號構造物件等效於使用括號。
- 使用大括號的優點是語法不受[Most Vexing Parse](https://en.wikipedia.org/wiki/Most_vexing_parse)問題的影響:
```cpp
struct Y { };
struct X
{
X(Y) { }
};
// ...
X x1(Y()); // MVP: Declares a function called x1 which returns
// a value of type X and accepts a function that
// takes no argument and returns a value of type Y.
X x2{Y()}; // OK, constructs an object of type X called x2 and
// provides a default-constructed temporary object
// of type Y in input to X's constructor.
```
- 對於C++初學者來說,認為採用等號=的賦值初始化是調用賦值函數,其實不是這樣的。
```
Widget w1; // call default constructor
Widget w2 = w1; // not an assignment; calls copy ctor
w1 = w2; // an assignment; calls copy operator=
```
- 大括號{}禁止內置數據類型從高類型轉向低類型,而小括號()和等號=則不會做這種檢查。
```
double x, y, z;
int sum1{ x + y + z }; // error! sum of doubles may not be expressible as int
int sum2(x + y + z); // okay (value of expression truncated to an int)
int sum3 = x + y + z; // ditto
```
- 不允許拷貝的對象可以用大括號{}和小括號()來初始化,但是不能採用等號=初始化。
```
std::atomic<int> ai1{ 0 }; // fine
std::atomic<int> ai2(0); // fine
std::atomic<int> ai3 = 0; // error!
```
:::warning
C++匹配std::initializer_list的優先級太高,以至於只要有可能,編譯器寧願報錯,也不願繼續尋找更加精確的匹配。
:::
- 大括號{}初始化是應用場景最廣泛最通用的初始化方式,它阻止高類型向低類型轉換,並且可以解決C++優先把表達式語句解析為聲明的問題。
- 重載構造函數時,大括號{}初始化只要有可能就會被匹配到std::initializer_list構造函數,即使其它構造函數可以提供更加精確的匹配。
### constructor 後面的 ":"
> - 如果您使用衍生類別生成物件,則建構函式的執行順序會從基底類別的建構函式開始執行起,這是可以理解的,因為基底類別是衍生類別的基礎,一些基礎的參數或 初始狀態必須先完成,再來再完成衍生類別中的建構函式。
> - 而在物件被消滅時,解構函式的執行順序則正好相反,是從衍生類別的解構函式開始執行,再來才是基礎類別的建構函式,因為若基底類別的解構函式如果先執行, 則衍生類別相依於基底類別的一些狀態也會被解構(例如指標),則此時再行衍生類別的解構函式,將存在著相依問題而造成錯誤。
- constructor 的初始化列表
```cpp
class myClass
{
public :
myClass();// 構造函數,無返回類型,可以有參數列表,這裏省去
~myClass();// 析構函數
int a;
const int b;
}
myClass::myClass():a(1),b(1)// 初始化列表
{
}
```
- 上面的例子展示了冒號的這個用法,下面對這個用法進行幾點說明:
- 初始化列表的作用相當於在構造函數內進行相應成員變量的賦值,但兩者是有差別的。
- 在初始化列表中是對變量進行初始化,而在構造函數內是進行賦值操作。兩都的差別在對於像const類型數據的操作上表現得尤為明顯。
- const類型的變量必須在定義時進行初始化,而不能對const型的變量進行賦值,因此const類型的成員變量只能(而且必須)在初始化列表中進行初始化
- 這意味著您在建構函式主體中所做的分配將不是初始化,而是值的更改
```
myClass::myClass()
{
a = 1;// 沒錯,效果相當於在初始化列表中進行初始化
b = 1;// 出錯,const變量不能進行賦值操作;
}
2)初始化的順序與成員變量聲名的順序相同。
先看一下下面的程序:
myClass::myClass():b(1),a(b)
{
}
```
- 這樣的執行結果a,b各是多少呢?b=1,a=1?不是,b=1而a是個隨機數。這一點是相當重要的哦,一般在初始化列表中進行初始化時,初始化的順序應與聲明的順序保持一致,防止出現不必要的錯誤。
- reference
- [【C++】用大括號呼叫建構函式](https://www.796t.com/post/M2VsbmU=.html)
- [C++編程之路(4)-小括號()與大括號創建對象的區別](https://kknews.cc/zh-tw/code/xenypr8.html)
- [繼承後的建構函式與解構函式](https://openhome.cc/Gossip/CppGossip/ConDesAfterInheritance.html)
- [C++ 冒號(:) 雙冒號(::) 的定義與應用](http://chiustin.blogspot.com/2017/02/c.html)
## forward reference
- [潮.C++11 | Perfect Forwarding std::forward 完美轉發你的需求](https://tjsw.medium.com/%E6%BD%AE-c-11-perfect-forwarding-%E5%AE%8C%E7%BE%8E%E8%BD%89%E7%99%BC%E4%BD%A0%E7%9A%84%E9%9C%80%E6%B1%82-%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90-f991830bcd84)
- [潮.C++11 | Universal Reference, Rvalue Reference, Move Semantics](https://tjsw.medium.com/%E6%BD%AE-c-11-universal-reference-rvalue-reference-move-semantics-1ea29f8cabdc)
- [Reference declaration](https://en.cppreference.com/w/cpp/language/reference)
- [[C++] rvalue reference 初入門](https://shininglionking.blogspot.com/2013/06/c-rvalue-reference.html)
## CRPT (Curiously Recurring Template Pattern)
> - 一般地被稱作F-bound polymorphism
1. 一個衍生類別必須繼承一個樣版類別。
2. 該樣版類別必須使用該衍生類別做為其樣版參數。
- [潮.C++ | CRTP 和靜態多型](https://tjsw.medium.com/%E6%BD%AE-c-crtp-%E5%92%8C%E9%9D%9C%E6%85%8B%E5%A4%9A%E5%9E%8B-96a91b9e4db6)
## traits
- traits,又被叫做特性萃取技術,說得簡單點就是提取“被傳進的對象”對應的返回類型,**讓同一個接口實現對應的功能**。
- 因為STL的算法和容器是分離的,兩者通過叠代器鏈接。算法的實現並不知道自己被傳進來什麽。萃取器相當於在接口和實現之間加一層**封裝**,來隱藏一些細節並協助調用合適的方法,這需要一些技巧(例如,偏特化)。最後附帶一個小小的例子,應該能更好地理解 特性萃取。
- 在 STL 中,容器与算法是分开的,彼此独立设计,容器与算法之间通过迭代器联系在一起
### reference
- [C++ traits技術淺談 - IT閱讀](https://www.itread01.com/articles/1488168040.html)
- [细说 C++ Traits Classes_Leo的博客-CSDN博客_c++ traits](https://blog.csdn.net/lihao21/article/details/55043881)
## RAII, finally
- 資源取得即初始化(英語:Resource Acquisition Is Initialization)
- 直接的意思是:「資源獲得即初始化」。意即:一旦在程式中有「資源配置」的行為,也就是一旦有「配置、釋放」的動作,就讓「配置」成為一個初始化的動作,如此,釋放動作就變成自動的了(依物件的 scope 決定)。
- 簡單地說,RAII 就是善用 C++ class 的解構式(destroctor),來達成 資源自動管理的目的。簡單應用如下:
```cpp
void f() // 一、使用 auto\_ptr 避免手動 delete
{ // 假設由於某種原因,TMemoryStream 必須以 new 的方式建立
std::auto\_ptr<TMemoryStream> p(new TMemoryStream);
... if (...) { throw 1; }
...
} // OK, 沒問題,一旦碰到右大括號,即使發生異常,p 也會正確被釋放。
void g() // 二、使用 vector 取代手動配置 array
{
int N; std::cin >> N; std::vector<int> v(N);
...
if (...) { throw 1; }
...
} // OK, 沒問題,即使發生異常,也不必操心 v 內部的記憶體管理 std::string g2() // 三、以回傳物件的方式,取代回傳函式內部 new 的物件的指標 { std::string s; ... return s; } // OK, 外部模組不必擔心忘記釋放記憶體的問題。
```
### reference
- [RAII - 維基百科,自由的百科全書](https://zh.wikipedia.org/wiki/RAII)
- [[心得] The RAII Idiom - 精華區 C_and_CPP - 批踢踢實業坊](https://www.ptt.cc/man/C_and_CPP/D8D2/DA94/DDBB/M.1127480790.A.3B6.html)
- [exception - Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?) - Stack Overflow](https://stackoverflow.com/questions/161177/does-c-support-finally-blocks-and-whats-this-raii-i-keep-hearing-about)
## regex
- 在C++11中,要使用正規表達式之前必須要先引入正規表達式的函式庫,記得要先加入下面這行:
```
#include <regex>
```
- regex_match: 比對字串是否符合正規表達式所定義之格式
- regex_search: 搜尋字串中所有符合正規表達式所定義之格式的子字串
- regex_replace: 取代字串中所有符合正規表達式所定義之格式的子字串為別的字串
### reference
- [#C++11:正規表達式(Regular Expression)的使用 - 翼世界夢想領域](https://knightzone.studio/2015/05/10/2756/c11%EF%BC%9A%E6%AD%A3%E8%A6%8F%E8%A1%A8%E9%81%94%E5%BC%8Fregular-expression%E7%9A%84%E4%BD%BF%E7%94%A8/)
## chrono
- C++11 提供了 \<chrono> 作為時間的 library,除了能夠獲取時間,且可以在多個單位轉換。
- 這個 Library 是只有時間 e.g. 小時、分鐘、秒..等,如果要日期則要使用其他 Library e.g. [HowardHinnant/date](https://github.com/HowardHinnant/date) 或是 `ctime()`
- 所有的東西在 std::chrono 這個 namespace 底下。
### introduce
- `duration`
- 時間的長度,可自由決定儲存的單位
- `time_point`
- 時間點,相減會得到時間長度(`duration`)
- Clocks
- 根據物理時間回傳時間點(`time_point`)
- 提供不同精度的 clock
### duration
- `count()` 獲得 duration 的值(時間長度)
- `duration_cast<T>()` 轉換時間長度單位
- 轉換是透過一開始定義的 `ratio`
- `std::ratio<N, D>` 比例(用來表示分數的 class)
- `N` 是分子(numerator),`D` 是分母(denominator)
```cpp
typedef std::ratio<1,3> one_third;
// one_third::num == 1
// one_third::den == 3
```
### clock
* system_clock
* 系統時間
* steady_clock
* 單調:下一個時間點永遠不會小於上一個
* high_resolution_clock
* 更高精度
* 有些平台上就是 steady_clock
- `now()` 可以獲得現在時間,會回傳 `time_point`
```cpp
auto a = system_clock::now();
auto b = steady_clock::now();
auto c = high_resolution_clock::now();
```
### time_point
- 儲存著時間點(相對於時鐘的開始時間),內部會儲存著 duration。幾乎不會有需要自己 contruct time_point 的機會,通常都是使用 clock 的 alias,例如:
```cpp
// ignore std::chrono::
system_clock::time_point today = system_clock::now();
steady_clock::time_point t1 = steady_clock::now();
high_resolution_clock::time_point t1 = high_resolution_clock::now();
```
- `time_point` 運算後會得到 `duration`,time_point 可以跟 duration 做運算
```cpp
auto n = steady_clock::now();
auto fu = n + minutes(10);
```
- STL 的 chrono 並沒有定義 time_point 的輸出方式,所以我們並不能直接透過 output stream 來輸出 time_point 的資料,所以如果要把他輸出成字串的話,其實還有點麻煩…
- 如果想要輸出的話,一個方法是透過 clock 提供的 to_time_t() 這個函式,把 time_point 先把他轉換成 C-style 的 time_t,然後再透過 ctime() 這類的函式做輸出;下面是一個簡單的範例:
### reference
- [std::chrono::duration - cppreference.com](https://en.cppreference.com/w/cpp/chrono/duration)
- [C++ - chrono 計時 | r0yblog](http://blog.roy4801.tw/2020/07/20/c++/chrono/)
- [C++11 STL 的時間函式庫:chrono – Heresy's Space](https://kheresy.wordpress.com/2013/12/27/c-stl-chrono/)
## c/c++ true and false
- definition
- true evaluates to 1, false evaluates to 0
- but any int that is not 0 evaluates to true but is not equal to true since it isn't equal to 1.
- e.g.
```clike
if(0) // false
if(1) // true
if(2) // true
if(0 == false) // true
if(0 == true) // false
if(1 == false) // false
if(1 == true) // true
if(2 == false) // false
if(2 == true) // false
cout << false // 0
cout << true // 1
```
### reference
- [boolean - c++ bool question - Stack Overflow](https://stackoverflow.com/questions/5189072/c-bool-question)
## size_t
- According to the 1999 ISO C standard (C99), `size_t` is an unsigned integer type of at least 16 bit (see sections 7.17 and 7.18.3).
- `size_t`is an unsigned data type defined by several C/C++ standards, e.g. the C99 ISO/IEC 9899 standard, that is defined in `stddef.h`.[1](http://en.wikipedia.org/wiki/Size_t) It can be further imported by inclusion of `stdlib.h` as this file internally sub includes `stddef.h`.
- This type is used to represent the size of an object. Library functions that take or return sizes expect them to be of type or have the return type of `size_t`. Further, the most frequently used compiler-based operator sizeof should evaluate to a constant value that is compatible with `size_t`.
- others
- the return type of `sizeof()` is `size_t` and it is an _unsigned integer_
- `operator new()` takes the number of bytes to allocate as a `size_t` parameter
- `size_t` is defined in `<cstddef>`
- `SIZE_MAX` is defined in `<limits.h>` in C99 but not mentioned in C++98?!
- `size_t` is not included in the list of _fundamental integer types_ so I have always assumed that `size_t` is a type alias for one of the fundamental types: `char`, `short int`, `int`, and `long int`.
:::info
- Fortunately for us, the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#arithmetic "github.com") have a whole section on advising how to deal with arithmetic. The linked section will take you through programming examples that demonstrate where using signed types (like `int`) are preferred, and where unsigned types (like `size_t`) are acceptable.
:::
### reference
- [int - What is size_t in C? - Stack Overflow](https://stackoverflow.com/questions/2550774/what-is-size-t-in-c)
- [size_t vs int in C++ and/or C - Stack Overflow](https://stackoverflow.com/questions/994288/size-t-vs-int-in-c-and-or-c)
- [Why do some C++ programs use size_t instead of int? What are the advantages? - Quora](https://www.quora.com/Why-do-some-C-programs-use-size_t-instead-of-int-What-are-the-advantages)
## Use of (void) before a function call
- It prevents warning if some function are declared with attribute : "Warn if return value not used/checked"
### reference
- [c++ - Use of (void) before a function call - Stack Overflow](https://stackoverflow.com/questions/13954517/use-of-void-before-a-function-call)
- [c++ - Why cast unused return values to void? - Stack Overflow](https://stackoverflow.com/questions/689677/why-cast-unused-return-values-to-void)
- [c - Warning: ignoring return value of 'scanf', declared with attribute warn_unused_result - Stack Overflow](https://stackoverflow.com/questions/7271939/warning-ignoring-return-value-of-scanf-declared-with-attribute-warn-unused-r)
## NULL == nullptr
- In C++11 and beyond, a pointer that is == NULL will also == nullptr and vice versa.
- Uses of NULL other than comparing with a pointer (like using it to represent the null byte at the end of a string) won't work with nullptr
### reference
- [Is C NULL equal to C++11 nullptr - Stack Overflow](https://stackoverflow.com/questions/36484473/is-c-null-equal-to-c11-nullptr)
- [C++ nullptr 與 NULL 的差異 | ShengYu Talk](https://shengyu7697.github.io/cpp-nullptr/)
## C++ Reference Variables
- `int &var = <some-variable>;`
```clike
int main(void)
{
int a = 10;
int &var = a;
var = var + 1;
std::cout<< "\na = "<< a <<"\n";
return 0;
}
```
### reference
- [How to Use C++ Reference Variables (C++ Reference Vs Pointer Example)](https://www.thegeekstuff.com/2013/05/cpp-reference-variable/)
## 函式原型 (function prototype)
- 在撰寫函式原型時,參數不需加名稱,只要寫入型別標註 (annotation) 即可;有些 C 程式碼會在函式原型加參數名稱,基本上僅是為了閱讀方便,函式原型的參數名稱不需和函式實作的參數名稱相同。
- e.g.
```clike
/* Declare function prototype. */
char * hello(char []);
int main(void)
{
/* Implement main program here. */
}
char * hello(char name[])
{
/* Implement function `hello()` here. */
}
```
### reference
- [[C 語言] 程式設計教學:如何撰寫函式 (Function) | 開放原始碼技術文件網](https://opensourcedoc.com/c-programming/function/)
## c string
- ![](https://i.imgur.com/2DVfxlx.png)
### Declaration
- `char str_name[size];`
### Initializing
```clike
char str[] = "GeeksforGeeks";
char str[50] = "GeeksforGeeks";
char str[] = {'G','e','e','k','s','f','o','r','G','e','e','k','s','\0'};
char str[14] = {'G','e','e','k','s','f','o','r','G','e','e','k','s','\0'};
char first_name[15] = "ANTHONY";
char first_name[15] = {'A','N','T','H','O','N','Y','\0'}; // NULL character '\0' is required at end in this declaration
char string1 [6] = "hello";/* string size = 'h'+'e'+'l'+'l'+'o'+"NULL" = 6 */
char string2 [ ] = "world"; /* string size = 'w'+'o'+'r'+'l'+'d'+"NULL" = 6 */
char string3[6] = {'h', 'e', 'l', 'l', 'o', '\0'} ; /*Declaration as set of characters ,Size 6*/
```
### Passing strings to function
- As strings are character arrays, so we can pass strings to function in a same way we pass an array to a function
```clike
void printStr(char str[])
{
printf("String is : %s",str);
}
```
### string pointer
```c
char s[] = "string";
char* s = "string\0";
```
- No, those two lines do not achieve the same result.
* char s[] = "string" results in a modifiable array of 7 bytes, which is initially filled with the content 's' 't' 'r' 'i' 'n' 'g' '\0' (all copied over at runtime from the string-literal).
* char *s = "string" results in a pointer to some read-only memory containing the string-literal "string".
* If you want to modify the contents of your string, then the first is the only way to go.
* If you only need read-only access to a string, then the second one will be slightly faster because the string does not have to be copied.
* In both cases, there is no need to specify a null terminator in the string literal. The compiler will take care of that for you when it encounters the closing ".
### initialize for 0
- Global variables and static variables are automatically initialized to zero. If you have simply
```c
char ZEROARRAY[1024];
static int myArray[10];
```
- at global scope it will be all zeros at runtime. But actually there _is_ a shorthand syntax if you had a local array.
- If an array is partially initialized, elements that are not initialized receive the value 0 of the appropriate type. You could write:
```c
char ZEROARRAY[1024] = {0};
```
- The compiler would fill the unwritten entries with zeros.
- Alternatively you could use `memset` to initialize the array at program startup:
```c
memset(ZEROARRAY, 0, 1024);
```
- That would be useful if you had changed it and wanted to reset it back to all zeros.
### reference
- [Strings in C - GeeksforGeeks](https://www.geeksforgeeks.org/strings-in-c-2/)
- [Strings in C: How to Declare Variable, Initialize, Print, Example](https://www.guru99.com/c-strings.html)
- [In C, can I initialize a string in a pointer declaration the same way I can initialize a string in a char array declaration? - Stack Overflow](https://stackoverflow.com/questions/4051347/in-c-can-i-initialize-a-string-in-a-pointer-declaration-the-same-way-i-can-init)
- [在 C 語言中將陣列初始化為 0 | D棧 - Delft Stack](https://www.delftstack.com/zh-tw/howto/c/c-initialize-array-to-0/)
- [How to initialize array to 0 in C? - Stack Overflow](https://stackoverflow.com/questions/2589749/how-to-initialize-array-to-0-in-c/2589751)
## bzero vs memset
- I don't see any reason to prefer bzero over memset.
- memset is a standard C function while bzero has never been a C standard function. The rationale is probably because you can achieve exactly the same functionality using memset function.
- Now regarding efficiency, compilers like gcc use builtin implementations for memset which switch to a particular implementation when a constant 0 is detected. Same for glibc when builtins are disabled.
### reference
- [c - Why use bzero over memset? - Stack Overflow](https://stackoverflow.com/questions/17096990/why-use-bzero-over-memset/17097088)
- [In C, what is the difference between bzero() and memset()? - Quora](https://www.quora.com/In-C-what-is-the-difference-between-bzero-and-memset)