summaryrefslogtreecommitdiffhomepage
path: root/c.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'c.html.markdown')
-rw-r--r--c.html.markdown52
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. */