summaryrefslogtreecommitdiffhomepage
path: root/c.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'c.html.markdown')
-rw-r--r--c.html.markdown120
1 files changed, 105 insertions, 15 deletions
diff --git a/c.html.markdown b/c.html.markdown
index 3339032f..d4ff529d 100644
--- a/c.html.markdown
+++ b/c.html.markdown
@@ -6,8 +6,8 @@ contributors:
- ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
- ["Jakub Trzebiatowski", "http://cbs.stgn.pl"]
- ["Marco Scannadinari", "https://marcoms.github.io"]
+ - ["Zachary Ferguson", "https://github.io/zfergus2"]
- ["himanshu", "https://github.com/himanshu81494"]
-
---
Ah, C. Still **the** language of modern high-performance computing.
@@ -54,6 +54,8 @@ int function_2(void);
// Must declare a 'function prototype' before main() when functions occur after
// your main() function.
int add_two_ints(int x1, int x2); // function prototype
+// although `int add_two_ints(int, int);` is also valid (no need to name the args),
+// it is recommended to name arguments in the prototype as well for easier inspection
// Your program's entry point is a function called
// main with an integer return type.
@@ -75,6 +77,9 @@ int main (int argc, char** argv)
// Types
///////////////////////////////////////
+ // All variables MUST be declared at the top of the current block scope
+ // we declare them dynamically along the code for the sake of the tutorial
+
// ints are usually 4 bytes
int x_int = 0;
@@ -143,15 +148,10 @@ int main (int argc, char** argv)
printf("Enter the array size: "); // ask the user for an array size
int size;
fscanf(stdin, "%d", &size);
- char buf[size];
- fgets(buf, sizeof buf, stdin);
-
- // strtoul parses a string to an unsigned integer
- size_t size2 = strtoul(buf, NULL, 10);
- int var_length_array[size2]; // declare the VLA
+ int var_length_array[size]; // declare the VLA
printf("sizeof array = %zu\n", sizeof var_length_array);
- // A possible outcome of this program may be:
+ // Example:
// > Enter the array size: 10
// > sizeof array = 40
@@ -232,14 +232,14 @@ int main (int argc, char** argv)
0 || 1; // => 1 (Logical or)
0 || 0; // => 0
- // Conditional expression ( ? : )
+ // Conditional ternary expression ( ? : )
int e = 5;
int f = 10;
int z;
z = (e > f) ? e : f; // => 10 "if e > f return e, else return f."
// Increment and decrement operators:
- char *s = "iLoveC";
+ char *s = "ILoveC";
int j = 0;
s[j++]; // => "i". Returns the j-th item of s THEN increments value of j.
j = 0;
@@ -302,6 +302,8 @@ int main (int argc, char** argv)
for (i = 0; i <= 5; i++) {
; // use semicolon to act as the body (null statement)
}
+ // Or
+ for (i = 0; i <= 5; i++);
// branching with multiple choices: switch()
switch (a) {
@@ -311,9 +313,15 @@ int main (int argc, char** argv)
case 1:
printf("Huh, 'a' equals 1!\n");
break;
+ // Be careful - without a "break", execution continues until the
+ // next "break" is reached.
+ case 3:
+ case 4:
+ printf("Look at that.. 'a' is either 3, or 4\n");
+ break;
default:
// if `some_integral_expression` didn't match any of the labels
- fputs("error!\n", stderr);
+ fputs("Error!\n", stderr);
exit(-1);
break;
}
@@ -338,8 +346,8 @@ int main (int argc, char** argv)
https://ideone.com/GuPhd6
this will print out "Error occured at i = 52 & j = 99."
*/
-
-
+
+
///////////////////////////////////////
// Typecasting
///////////////////////////////////////
@@ -439,6 +447,17 @@ int main (int argc, char** argv)
*(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx
} // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints)
+ // 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);
+ // Add an element to the array
+ my_arr = realloc(my_arr, ++size);
+ my_arr[10] = 5;
+
// Dereferencing memory that you haven't allocated gives
// "unpredictable results" - the program is said to invoke "undefined behavior"
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? It may even crash.
@@ -478,7 +497,7 @@ int add_two_ints(int x1, int x2)
/*
Functions are call by value. When a function is called, the arguments passed to
-≈the function are copies of the original arguments (except arrays). Anything you
+the function are copies of the original arguments (except arrays). Anything you
do to the arguments in the function do not change the value of the original
argument where the function was called.
@@ -523,6 +542,29 @@ swapTwoNumbers(&first, &second);
printf("first: %d\nsecond: %d\n", first, second);
// values will be swapped
*/
+
+/*
+With regards to arrays, they will always be passed to functions
+as pointers. Even if you statically allocate an array like `arr[10]`,
+it still gets passed as a pointer to the first element in any function calls.
+Again, there is no standard way to get the size of a dynamically allocated
+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) {
+ int i;
+ for (i = 0; i < size; i++) {
+ printf("arr[%d] is: %d\n", i, arr[i]);
+ }
+}
+/*
+int my_arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+int size = 10;
+printIntArray(my_arr, size);
+// will print "arr[0] is: 1" etc
+*/
+
// if referring to external variables outside function, must use extern keyword.
int i = 0;
void testFunc() {
@@ -678,8 +720,56 @@ typedef void (*my_fnp_type)(char *);
// , | left to right //
//---------------------------------------------------//
-```
+/******************************* Header Files **********************************
+Header files are an important part of c as they allow for the connection of c
+source files and can simplify code and definitions by separating them into
+separate files.
+
+Header files are syntactically similar to c source files but reside in ".h"
+files. They can be included in your c source file by using the precompiler
+command #include "example.h", given that example.h exists in the same directory
+as the c file.
+*/
+
+/* A safe guard to prevent the header from being defined too many times. This */
+/* happens in the case of circle dependency, the contents of the header is */
+/* already defined. */
+#ifndef EXAMPLE_H /* if EXAMPLE_H is not yet defined. */
+#define EXAMPLE_H /* Define the macro EXAMPLE_H. */
+
+/* Other headers can be included in headers and therefore transitively */
+/* included into files that include this header. */
+#include <string.h>
+
+/* 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)
+
+/* Structs and typedefs can be used for consistency between files. */
+typedef struct node
+{
+ int val;
+ struct node *next;
+} Node;
+
+/* So can enumerations. */
+enum traffic_light_state {GREEN, YELLOW, RED};
+
+/* Function prototypes can also be defined here for use in multiple files, */
+/* but it is bad practice to define the function in the header. Definitions */
+/* should instead be put in a c file. */
+Node createLinkedList(int *vals, int len);
+
+/* Beyond the above elements, other definitions should be left to a c source */
+/* file. Excessive includes or definitions should, also not be contained in */
+/* a header file but instead put into separate headers or a c file. */
+
+#endif /* End of the if precompiler directive. */
+
+```
## Further Reading
Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)