* C++ 的部分移到 [[C Plus Plus|C++]]。
* 維護 [[wp>C++]] 中文版面。
* 盡可能只紀錄語言層面知識。
* [[wp>Evaluation strategy]]
* [[wp>Evaluation_strategy#Call_by_value|Call by value]]: C 只有此種方法。
* In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function (frequently by copying the value into a new memory region).
* [[wp>Evaluation_strategy#Call_by_reference|Call by reference]]: C++ 另外支援此種方法。C 可以用傳遞指針 (仍為 call by value,value 為位址) 模擬 call by reference 的效果。
* In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value.
* [[http://blog.tinlans.org/2009/11/29/%E5%82%B3-pointer-%E5%B0%B1%E6%98%AF-pass-by-value-%E9%80%99%E4%BB%B6%E4%BA%8B%E6%98%AF%E8%A6%81%E9%87%8D%E8%A4%87%E8%AC%9B%E5%B9%BE%E9%81%8D/|傳 pointer 就是 pass-by-value 這件事是要重複講幾遍]]
===== 前處理器 =====
* [[https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms|C Preprocessor tricks, tips, and idioms]]
* [[http://jhnet.co.uk/articles/cpp_magic|C Pre-Processor Magic]]
* What happens is that when RECURSIVE() is expanded, if RECURSIVE appears in its expansion it is 'painted blue' (macro language jargon) which prevents it ever being expanded as a macro.
* 在前處理器展開巨集的時候,如果該巨集的定義中又包含其自身,則後者不被視為巨集 ([[wp>painted blue]])。此種處理方式禁止遞迴巨集 (recursive macro)。是否支援遞迴巨集,端看前處理器是否支援。
* [[https://monoinfinito.wordpress.com/2013/08/20/c-preprocessor-just-a-simple-replacer/|C preprocessor internals]]
* [[http://stackoverflow.com/questions/5641836/c-preprocessor-recursive-macros|C preprocessor, recursive macros]]
* [[http://www.cakoose.com/wiki/c_preprocessor_abuse|C Preprocessor Abuse]]
* [[http://stackoverflow.com/questions/6080129/trick-filling-array-values-using-macros-code-generation|Trick : filling array values using macros (code generation)]]
* [[http://www.kchodorow.com/blog/2012/08/24/a-neat-c-preprocessor-trick/|A Neat C Preprocessor Trick]]
* The X Macro Trick 為常用技巧。
* [[http://stackoverflow.com/questions/2927245/looking-for-a-good-explanation-of-the-table-generation-macro-idiom|Looking for a good explanation of the table generation macro idiom]]
* [[http://www.keithschwarz.com/cs106l/spring2009/handouts/080_Preprocessor_2.pdf|Advanced Preprocessor Techniques]]
* [[http://stackoverflow.com/questions/650461/what-are-some-tricks-i-can-use-with-macros|What are some tricks I can use with macros?]]
* [[http://stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block|C multi-line macro: do/while(0) vs scope block [duplicate]]]
* [[http://www.geeksforgeeks.org/multiline-macros-in-c/|Multiline macros in C]]
====== 常見問題 ======
* [[http://stackoverflow.com/questions/15638105/accessing-specific-memory-locations-in-c|Accessing Specific Memory Locations in C]]
* [[https://paritycheck.wordpress.com/2009/03/27/what-does-this-mean-volatile-unsigned-char-0x22/|What Does This Mean? (*(Volatile Unsigned Char *)(0x22))]]
* [[http://stackoverflow.com/questions/3691835/why-uninitialized-global-variable-is-weak-symbol|Why uninitialized global variable is weak symbol?]]
* [[http://stackoverflow.com/questions/13596577/multiple-definition-of-value-when-compiling-c-program-with-uninitialized-globa|“multiple definition of value” when compiling C program with uninitialized global in g++ but not gcc]]
* [[http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka16744.html|How does the compiler handle multiple definitions of global variables?]]
* GCC 可以加上 ''-fno-common'' 選項,要求將多個且重名的未初始化全域變數產生至 .bss 段,最後交由鏈結器報錯。
$ gcc -fno-common main.c foo.c
/tmp/ccBPsu3u.o:(.bss+0x0): multiple definition of `g_val'
/tmp/ccf5NmfA.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
* [[https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html|3.18 Options for Code Generation Conventions]]
* Unix C compilers have traditionally permitted multiple definitions of such variables in different compilation units by placing the variables in a common block. This is the behavior specified by -fcommon, and is the default for GCC on most targets. On the other hand, this behavior is not required by ISO C, and on some targets may carry a speed or code size penalty on variable references.
* 注意,ISO C 只是不要求編譯器編譯多個且重名的未初始化全域變數,而非像 C++ 禁止。
* [[https://gcc.gnu.org/ml/gcc-help/2007-07/msg00097.html|Re: Automatically initialize all global variables/arrays in GCC.]]
* 可以選擇不將全域變數初始化為零。
* [[http://koopman.us/bess/chap19_globals.pdf|Chapter 19 Global Variables Are Evil]]
* [[http://electronics.stackexchange.com/questions/97241/use-of-global-variables-in-embedded-systems|Use of global variables in Embedded Systems]]
* [[http://www.geeksforgeeks.org/how-linkers-resolve-multiply-defined-global-symbols/|How Linkers Resolve Global Symbols Defined at Multiple Places?]]
* 避免使用全域變數。
* [[http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/|A tutorial on signed and unsigned integers]]
====== C ======
* [[http://c-faq.com/|comp.lang.c Frequently Asked Questions]]
* [[https://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298|Expert C Programming: Deep C Secrets]]
* Ch1. C Through the Mists of Time
* Ch2. It’s Not a Bug, It’s a Language Feature
* Ch3. Unscrambling Declarations in C
* typedef 閱讀方式和宣告一樣,為已有型別引入別名。
// 看到 string,就是 char *。
typedef char * string;
// 常應用於簡化函式指針。
void (*signal(int sig, void (*func)(int)))(int);
// sig_t 是一個指針,指向一個參數為 int,返回值為 void 的函式。
typedef void (*sig_t) (int);
// signal 接受一個 int 和一個 sig_t, 返回 sig_t。
sig_t signal(int sig, sig_t func);
* [[http://stackoverflow.com/questions/252780/why-should-we-typedef-a-struct-so-often-in-c|Why should we typedef a struct so often in C?]]
* 不建議。
* Ch 4. The Shocking Truth: C Arrays and Pointers Are NOT the Same!
* 定義 (definition) 確定對象 (object,鏈結器角度) 的型別並分配內存,創建對象。定義只能出現在一個地方。
* [[http://stackoverflow.com/questions/34986335/does-c-have-one-definition-rule-like-c|Does C have One Definition Rule like C++?]]
* C 沒有像 C++ 明確定義的 [[wp>One Definition Rule]]。
* 聲明 (declaration,或稱宣告) 描述對象的類型,引用定義在其它檔案的對象。聲明可以出現多次。
===== 常見問題 =====
* [[http://stackoverflow.com/questions/8106765/using-strtok-in-c|Using strtok in c]]
* [[http://stackoverflow.com/questions/6432384/strdup-dumping-core-on-passing-null|strdup dumping core on passing NULL]]
* 注意! strtok 會破壞被 tokenize 的字串,使用 strdup 拷貝一份備份供 strtok 使用。
* strdup 參數若為 NULL,其行為未定義。
* [[http://stackoverflow.com/questions/9627962/is-it-possible-to-convert-char-to-char-in-c|Is it possible to convert char[] to char* in C?]]
* array 和 pointer 不等價。只有在某些情況下,array 操作會被轉換成 pointer 操作。
* [[https://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/|Myth and reality about inline in C99]]
* [[http://stackoverflow.com/questions/25000497/whats-the-difference-between-static-inline-extern-inline-and-a-normal-inline-f|What's the difference between a static inline, extern inline and a normal inline function?]]
* [[https://clang.llvm.org/compatibility.html#inline|C99 inline functions]]
* [[https://gcc.gnu.org/gcc-5/porting_to.html|Porting to GCC 5]]
// lib.h
inline
double dabs(double x) {
return x < 0.0 ? -x : x;
}
// lib.c
#include "lib.h" // 告知編譯器 dabs 的函式定義為何。
// 指示編譯器在 lib.o 產生函式定義。
extern inline double dabs(double x);
* 為了讓編譯器能 inline 函式,inline 函式的定義一般都寫在 .h 檔。
* C89 沒有定義 inline,inline 是 GCC 擴展 (GNU89),用於指示編譯器 inline function。
* C99 以後對 inline 的解釋。
* inline: 該函式定義僅用於 inline,不會產生函式定義。如果該函式被引用 (調用),則在其它檔案必須有該函式的定義。No externally visible function is generated. If the function is referenced in this TU, an external definition has to exist in another TU; same as GNU89 extern inline with no redefinition.
// 此處的 add 定義只用於 inline function。
inline int add(int i, int j) { return i + j; }
int main() {
// 如果編譯器無法 inline add 函式 (亦即透過函數調用 add),會產生 undefined symbol 錯誤。
// 嘗試比較 -O0 和 -O2 的差別。
int i = add(4, 5);
return i;
}
* extern inline: 最終會產生函式定義。
* static inline: 不會產生函式定義。此函式只會在該定義所在的檔案被引用。
===== 語言相關 =====
#include
int main()
{
// 將整型 (int) -1,即 ffffffff,轉型成 size_t,進而得到 size_t 的最大值。
// (~(size_t)0)
size_t length = (size_t)-1;
printf("max value of size_t: %zu\n", length);
printf("sizeof(size_t): %lu\n", sizeof(size_t));
}
* [[http://bytes.com/topic/c/answers/614268-finding-max-value-size_t|finding max value of size_t]]
* [[http://stackoverflow.com/questions/3472311/what-is-a-portable-method-to-find-the-maximum-value-of-size-t|What is a portable method to find the maximum value of size_t?]]
* [[http://stackoverflow.com/questions/3168275/printf-format-specifiers-for-uint32-t-and-size-t|printf format specifiers for uint32_t and size_t]]
* [[http://stackoverflow.com/questions/3918384/declaring-the-largest-array-using-size-t|declaring the largest array using size_t]]
* [[http://linux.die.net/man/3/printf|printf]]
// $ cat /proc/`pidof mmap`/maps
// 00000000-100000000 rwxp 00000000 00:00 0
// 100000000-100001000 r-xp 00000000 00:0f 24080529 /nfs_home/chenwj/tmp/mmap
#include
#include
#include
#include
// 4 * 1024 * 1024 * 1024 的寫法,會因為 4 預設型別為 int 而導致 overflow。
#define DEFAULT_CODE_GEN_BUFFER_SIZE (4UL << 30)
int main()
{
void *ptr;
size_t code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
// gcc -Wl,-Ttext-segment=0x100000000 -fPIE -pie hello.c -o hello
// mmap 映射虛擬位址 4G 以下所有空間。
ptr = mmap(0, code_gen_buffer_size,
PROT_WRITE | PROT_READ | PROT_EXEC,
flags, -1, 0);
if (ptr == MAP_FAILED)
{
printf("mmap failed!\n");
abort();
}
printf("ptr: 0x%016lx\n", (unsigned long)ptr);
sleep(100);
}
* [[http://stackoverflow.com/questions/153890/printing-leading-0s-in-c|Printing leading 0's in C?]]
* [[http://tw.myblog.yahoo.com/chimei-015/|有關C語言的struct進階初始化]]
typedef struct _stu {
char name[12];
int id;
} stu;
stu jenny;
strutc _stu zakk;
* [[http://stackoverflow.com/questions/18221291/how-to-check-if-plain-chars-are-signed-or-unsigned|How to check if plain chars are signed or unsigned?]]
* [[http://stackoverflow.com/questions/1921539/using-boolean-values-in-c|Using boolean values in C]]
typedef enum { false, true } bool;
int main()
{
const bool char_is_signed = (char)-1 < 0;
if (char_is_signed)
{
printf("signed char\n");
}
else
{
printf("unsigned char\n");
}
}
* [[http://blog.3soh.flat1003.com/2013/07/readline-using-fscanf-in-c/|Readline using fscanf in C]]
* fscanf 讀取字串以空白為界,欲達到讀取一行的字串。
#include
FILE *my_file_ptr = fopen("some/path/file.txt", "r");
if (my_file_ptr != NULL) {
char line[300];
// Read anything that is not line end, until line end is encountered.
while (fscanf(my_file_ptr, "%[^\n]\n",line) != EOF) {
printf("%s", line);
}
}
* [[http://stackoverflow.com/questions/3784263/converting-an-int-into-a-4-byte-char-array-c|Converting an int into a 4 byte char array (C)]]
* 透過 shift 和 mask 達成。
unsigned char bytes[4];
unsigned long n = 175;
bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;
* [[http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/|Low Level Bit Hacks You Absolutely Must Know]]
===== 工作學習 =====
* [[http://stackoverflow.com/questions/4775437/read-unicode-file-into-wstring|read unicode file into wstring]]
* [[http://stackoverflow.com/questions/13612340/c-fread-into-a-stdstring|C++ fread() into a std::string]]
* [[http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring|Read whole ASCII file into C++ std::string]]
* [[http://stackoverflow.com/questions/4786292/converting-unicode-strings-and-vice-versa|Converting unicode strings and vice-versa]]
* [[http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring|Read whole ASCII file into C++ std::string]]
* [[http://stackoverflow.com/questions/11576846/convert-ascii-string-to-unicode-windows-pure-c|Convert ASCII string to Unicode? Windows, pure C]]
* [[http://stackoverflow.com/questions/215963/how-do-you-properly-use-widechartomultibyte|How do you properly use WideCharToMultiByte]]
* [[http://www.joelonsoftware.com/articles/Unicode.html|The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets]]
* [[http://www.abdullahyahya.com/2011/09/22/find-out-a-files-encoding-on-windows/|Find Out a File’s Encoding On Windows]]
* [[http://stackoverflow.com/questions/90838/how-can-i-detect-the-encoding-codepage-of-a-text-file|How can I detect the encoding/codepage of a text file]]
* [[http://encodingchecker.codeplex.com/|File Encoding Checker.]]
* [[http://code.google.com/p/ude/|C# port of Mozilla Universal Charset Detector]]
==== 轉換編碼 ====
* 如果看到轉碼之後,出現額外的亂碼。要確定拷貝的字串長度是正確的。strlen 是以 '\0'做為字串結尾,計算字串長度。因此,如果字串緩衝區中沒有 '\0',得到的長度不會是正確的。這可能是出現亂碼的原因。
* 不確定欲處理的字串緩衝區是否有 '\0',避免使用 strlen 和 strcpy。改以 memcpy,並在額外配置的結尾處補上 '\0'。
==== 其它 ====
* [[http://stackoverflow.com/questions/2462951/c-equivalent-of-stringbuffer-stringbuilder|C++ equivalent of StringBuffer/StringBuilder?]]
* [[http://www.dreamincode.net/forums/topic/95826-stringstream-tutorial/|Stringstream Tutorial: Using A Stringstream To Read Input From A Csv File]]
* [[http://stackoverflow.com/questions/368262/function-call-jumps-to-the-wrong-function|Function call jumps to the wrong function]]
* [[http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors|When to use virtual destructors?]]
* [[http://stackoverflow.com/questions/13448064/how-to-find-the-intersection-of-two-stdset-in-c|how to find the intersection of two std:set in C++?]]
* [[http://stackoverflow.com/questions/22395738/c-wrapping-a-wrapper-macro-with-variable-arguments|C++ Wrapping a wrapper macro with variable arguments?]]
* [[http://bytes.com/topic/c/answers/62216-stl-map-two-keys|STL