diff options
Diffstat (limited to 'c.html.markdown')
-rw-r--r-- | c.html.markdown | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/c.html.markdown b/c.html.markdown index 18503eab..684d330a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -8,6 +8,7 @@ contributors: - ["Marco Scannadinari", "https://marcoms.github.io"] - ["Zachary Ferguson", "https://github.io/zfergus2"] - ["himanshu", "https://github.com/himanshu81494"] + - ["Joshua Li", "https://github.com/JoshuaRLi"] --- Ah, C. Still **the** language of modern high-performance computing. @@ -16,6 +17,16 @@ C is the lowest-level language most programmers will ever use, but it more than makes up for it with raw speed. Just be aware of its manual memory management and C will take you as far as you need to go. +> **About compiler flags** +> +> By default, gcc and clang are pretty quiet about compilation warnings and +> errors, which can be very useful information. Explicitly using stricter +> compiler flags is recommended. Here are some recommended defaults: +> +> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic` +> +> For information on what these flags do as well as other flags, consult the man page for your C compiler (e.g. `man 1 gcc`) or just search online. + ```c // Single-line comments start with // - only available in C99 and later. @@ -90,7 +101,7 @@ int main (int argc, char** argv) char y_char = 'y'; // Char literals are quoted with '' // longs are often 4 to 8 bytes; long longs are guaranteed to be at least - // 64 bits + // 8 bytes long x_long = 0; long long x_long_long = 0; @@ -302,7 +313,7 @@ int main (int argc, char** argv) // branching with multiple choices: switch() switch (a) { - case 0: // labels need to be integral *constant* expressions + case 0: // labels need to be integral *constant* expressions (such as enums) printf("Hey, 'a' equals 0!\n"); break; // if you don't break, control flow falls over labels case 1: @@ -324,7 +335,7 @@ int main (int argc, char** argv) using "goto" in C */ typedef enum { false, true } bool; - // for C don't have bool as data type :( + // for C don't have bool as data type before C99 :( bool disaster = false; int i, j; for(i=0;i<100;++i) @@ -336,10 +347,10 @@ int main (int argc, char** argv) goto error; } error : - printf("Error occured at i = %d & j = %d.\n", i, j); + printf("Error occurred at i = %d & j = %d.\n", i, j); /* https://ideone.com/GuPhd6 - this will print out "Error occured at i = 52 & j = 99." + this will print out "Error occurred at i = 51 & j = 99." */ /////////////////////////////////////// @@ -438,17 +449,25 @@ int main (int argc, char** argv) for (xx = 0; xx < 20; xx++) { *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx } // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) + + // Be careful passing user-provided values to malloc! If you want + // to be safe, you can use calloc instead (which, unlike malloc, also zeros out the memory) + int* my_other_ptr = calloc(20, sizeof(int)); // Note that there is no standard way to get the length of a // dynamically allocated array in C. Because of this, if your arrays are // going to be passed around your program a lot, you need another variable // to keep track of the number of elements (size) of an array. See the // functions section for more info. - int size = 10; - int *my_arr = malloc(sizeof(int) * size); + size_t size = 10; + int *my_arr = calloc(size, sizeof(int)); // Add an element to the array size++; my_arr = realloc(my_arr, sizeof(int) * size); + if (my_arr == NULL) { + //Remember to check for realloc failure! + return + } my_arr[10] = 5; // Dereferencing memory that you haven't allocated gives @@ -546,7 +565,7 @@ array in C. */ // Size must be passed! // Otherwise, this function has no way of knowing how big the array is. -void printIntArray(int *arr, int size) { +void printIntArray(int *arr, size_t size) { int i; for (i = 0; i < size; i++) { printf("arr[%d] is: %d\n", i, arr[i]); @@ -559,7 +578,7 @@ printIntArray(my_arr, size); // will print "arr[0] is: 1" etc */ -// if referring to external variables outside function, must use extern keyword. +// if referring to external variables outside function, you should use the extern keyword. int i = 0; void testFunc() { extern int i; //i here is now using external variable i @@ -656,6 +675,7 @@ typedef void (*my_fnp_type)(char *); // ... // my_fnp_type f; + //Special characters: /* '\a'; // alert (bell) character @@ -738,14 +758,20 @@ as the C file. /* Like c source files macros can be defined in headers and used in files */ /* that include this header file. */ #define EXAMPLE_NAME "Dennis Ritchie" -/* Function macros can also be defined. */ -#define ADD(a, b) (a + b) + +/* Function macros can also be defined. */ +#define ADD(a, b) ((a) + (b)) + +/* Notice the parenthesis surrounding the arguments -- this is important to */ +/* ensure that a and b don't get expanded in an unexpected way (e.g. consider */ +/* MUL(x, y) (x * y); MUL(1 + 2, 3) would expand to (1 + 2 * 3), yielding an */ +/* incorrect result) */ /* Structs and typedefs can be used for consistency between files. */ -typedef struct node +typedef struct Node { int val; - struct node *next; + struct Node *next; } Node; /* So can enumerations. */ |