From 4ecd73fc9cd766557e10fc2fa0c3351c373ff1a0 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 1 Aug 2013 11:24:23 -0700 Subject: An assortment --- c.html.markdown | 2 ++ 1 file changed, 2 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 132f75dc..b5286f70 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,4 +1,6 @@ --- +name: c +category: language language: c filename: learnc.c contributors: -- cgit v1.2.3 From e037df9c91b303ce21847dd5e8fa3bf8b9376aed Mon Sep 17 00:00:00 2001 From: Trent Ogren Date: Mon, 5 Aug 2013 13:06:21 -0500 Subject: C: Signed/unsigned clarification --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index b5286f70..d243b19d 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -70,7 +70,7 @@ double x_double = 0.0; // Integral types may be unsigned. This means they can't be negative, but // the maximum value of an unsigned variable is greater than the maximum -// value of the same size. +// signed value of the same size. unsigned char ux_char; unsigned short ux_short; unsigned int ux_int; -- cgit v1.2.3 From 162b5bb60dea93dac591005a73956be663313761 Mon Sep 17 00:00:00 2001 From: Sergey Avseyev Date: Wed, 14 Aug 2013 23:15:17 +0300 Subject: Fix typo about how pointers are declared Of course it is completely valid that star can go right after type name, but it might be not that obvious that during declaration the star is associated to the variable, not with the type name. --- c.html.markdown | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index d243b19d..2b50efa0 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -230,10 +230,13 @@ printf("%p\n", &x); // Use & to retrieve the address of a variable // (%p formats a pointer) // => Prints some address in memory; -// Pointer types end with * in their declaration -int* px; // px is a pointer to an int + +// Pointers start with * in their declaration +int *px, not_a_pointer; // px is a pointer to an int px = &x; // Stores the address of x in px printf("%p\n", px); // => Prints some address in memory +printf("%d, %d\n", (int)sizeof(px), (int)sizeof(not_a_pointer)); +// => Prints "8, 4" on 64-bit system // To retreive the value at the address a pointer is pointing to, // put * in front to de-reference it. -- cgit v1.2.3 From 7cb78e94d24d7c768868fa4bd575a7572126cbe5 Mon Sep 17 00:00:00 2001 From: dacechavez Date: Thu, 15 Aug 2013 12:12:19 +0200 Subject: Fixed 2 typos around function pointers --- c.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 2b50efa0..e8a26056 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -373,7 +373,7 @@ int area(rect r){ /////////////////////////////////////// /* At runtime, functions are located at known memory addresses. Function pointers are -much likely any other pointer (they just store a memory address), but can be used +much like any other pointer (they just store a memory address), but can be used to invoke functions directly, and to pass handlers (or callback functions) around. However, definition syntax may be initially confusing. @@ -394,7 +394,7 @@ Function pointers are usually typedef'd for simplicity and readability, as follo typedef void (*my_fnp_type)(char *); -// The used when declaring the actual pointer variable: +// Then used when declaring the actual pointer variable: // ... // my_fnp_type f; -- cgit v1.2.3 From 24fd870589d863618e6ba2571b6a0c8339d35edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Thu, 15 Aug 2013 12:30:22 +0200 Subject: Update c.html.markdown --- c.html.markdown | 629 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 356 insertions(+), 273 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 2b50efa0..ac6c7ab4 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -5,19 +5,20 @@ language: c filename: learnc.c contributors: - ["Adam Bard", "http://adambard.com/"] + - ["Árpád Goretity", "http://twitter.com/h2co3_ios"] --- -Ah, C. Still the language of modern high-performance computing. +Ah, C. Still **the** language of modern high-performance computing. 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. ```c -// Single-line comments start with // +// Single-line comments start with // - only available in C99 and later. /* -Multi-line comments look like this. +Multi-line comments look like this. They work in C89 as well. */ // Import headers with #include @@ -25,6 +26,11 @@ Multi-line comments look like this. #include #include +// file names between are headers from the C standard library. +// They are searched for by the preprocessor in the system include paths +// (usually /usr/lib on Unices, can be controlled with the -I option if you are using GCC or clang.) +// For your + // Declare function signatures in advance in a .h file, or at the top of // your .c file. void function_1(); @@ -33,264 +39,317 @@ void function_2(); // Your program's entry point is a function called // main with an integer return type. int main() { - -// print output using printf, for "print formatted" -// %d is an integer, \n is a newline -printf("%d\n", 0); // => Prints 0 -// All statements must end with a semicolon - -/////////////////////////////////////// -// Types -/////////////////////////////////////// - -// You have to declare variables before using them. A variable declaration -// requires you to specify its type; a variable's type determines its size -// in bytes. - -// ints are usually 4 bytes -int x_int = 0; - -// shorts are usually 2 bytes -short x_short = 0; - -// chars are guaranteed to be 1 byte -char x_char = 0; -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 -long x_long = 0; -long long x_long_long = 0; - -// floats are usually 32-bit floating point numbers -float x_float = 0.0; - -// doubles are usually 64-bit floating-point numbers -double x_double = 0.0; - -// Integral types may be unsigned. This means they can't be negative, but -// the maximum value of an unsigned variable is greater than the maximum -// signed value of the same size. -unsigned char ux_char; -unsigned short ux_short; -unsigned int ux_int; -unsigned long long ux_long_long; - -// Other than char, which is always 1 byte, these types vary in size depending -// on your machine. sizeof(T) gives you the size of a variable with type T in -// bytes so you can express the size of these types in a portable way. -// For example, -printf("%lu\n", sizeof(int)); // => 4 (on machines with 4-byte words) - -// Arrays must be initialized with a concrete size. -char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes -int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes - // (assuming 4-byte words) - - -// You can initialize an array to 0 thusly: -char my_array[20] = {0}; - -// Indexing an array is like other languages -- or, -// rather, other languages are like C -my_array[0]; // => 0 - -// Arrays are mutable; it's just memory! -my_array[1] = 2; -printf("%d\n", my_array[1]); // => 2 - -// Strings are just arrays of chars terminated by a NUL (0x00) byte, -// represented in strings as the special character '\0'. -// (We don't have to include the NUL byte in string literals; the compiler -// inserts it at the end of the array for us.) -char a_string[20] = "This is a string"; -printf("%s\n", a_string); // %s formats a string - -/* -You may have noticed that a_string is only 16 chars long. -Char #17 is the NUL byte. -Chars #18, 19 and 20 have undefined values. -*/ - -printf("%d\n", a_string[16]); // => 0 - -/////////////////////////////////////// -// Operators -/////////////////////////////////////// - -int i1 = 1, i2 = 2; // Shorthand for multiple declaration -float f1 = 1.0, f2 = 2.0; - -// Arithmetic is straightforward -i1 + i2; // => 3 -i2 - i1; // => 1 -i2 * i1; // => 2 -i1 / i2; // => 0 (0.5, but truncated towards 0) - -f1 / f2; // => 0.5, plus or minus epsilon - -// Modulo is there as well -11 % 3; // => 2 - -// Comparison operators are probably familiar, but -// there is no boolean type in c. We use ints instead. -// 0 is false, anything else is true. (The comparison -// operators always return 0 or 1.) -3 == 2; // => 0 (false) -3 != 2; // => 1 (true) -3 > 2; // => 1 -3 < 2; // => 0 -2 <= 2; // => 1 -2 >= 2; // => 1 - -// Logic works on ints -!3; // => 0 (Logical not) -!0; // => 1 -1 && 1; // => 1 (Logical and) -0 && 1; // => 0 -0 || 1; // => 1 (Logical or) -0 || 0; // => 0 - -// Bitwise operators! -~0x0F; // => 0xF0 (bitwise negation) -0x0F & 0xF0; // => 0x00 (bitwise AND) -0x0F | 0xF0; // => 0xFF (bitwise OR) -0x04 ^ 0x0F; // => 0x0B (bitwise XOR) -0x01 << 1; // => 0x02 (bitwise left shift (by 1)) -0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) - -/////////////////////////////////////// -// Control Structures -/////////////////////////////////////// - -if (0) { - printf("I am never run\n"); -} else if (0) { - printf("I am also never run\n"); -} else { - printf("I print\n"); -} - -// While loops exist -int ii = 0; -while (ii < 10) { - printf("%d, ", ii++); // ii++ increments ii in-place, after using its value. -} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - -printf("\n"); - -int kk = 0; -do { - printf("%d, ", kk); -} while (++kk < 10); // ++kk increments kk in-place, before using its value -// => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - -printf("\n"); - -// For loops too -int jj; -for (jj=0; jj < 10; jj++) { - printf("%d, ", jj); -} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - -printf("\n"); - -/////////////////////////////////////// -// Typecasting -/////////////////////////////////////// - -// Every value in C has a type, but you can cast one value into another type -// if you want. - -int x_hex = 0x01; // You can assign vars with hex literals - -// Casting between types will attempt to preserve their numeric values -printf("%d\n", x_hex); // => Prints 1 -printf("%d\n", (short) x_hex); // => Prints 1 -printf("%d\n", (char) x_hex); // => Prints 1 - -// Types will overflow without warning -printf("%d\n", (char) 257); // => 1 (Max char = 255) - -// Integral types can be cast to floating-point types, and vice-versa. -printf("%f\n", (float)100); // %f formats a float -printf("%lf\n", (double)100); // %lf formats a double -printf("%d\n", (char)100.0); - -/////////////////////////////////////// -// Pointers -/////////////////////////////////////// - -// A pointer is a variable declared to store a memory address. Its declaration will -// also tell you the type of data it points to. You can retrieve the memory address -// of your variables, then mess with them. - -int x = 0; -printf("%p\n", &x); // Use & to retrieve the address of a variable -// (%p formats a pointer) -// => Prints some address in memory; - - -// Pointers start with * in their declaration -int *px, not_a_pointer; // px is a pointer to an int -px = &x; // Stores the address of x in px -printf("%p\n", px); // => Prints some address in memory -printf("%d, %d\n", (int)sizeof(px), (int)sizeof(not_a_pointer)); -// => Prints "8, 4" on 64-bit system - -// To retreive the value at the address a pointer is pointing to, -// put * in front to de-reference it. -printf("%d\n", *px); // => Prints 0, the value of x, which is what px is pointing to the address of - -// You can also change the value the pointer is pointing to. -// We'll have to wrap the de-reference in parenthesis because -// ++ has a higher precedence than *. -(*px)++; // Increment the value px is pointing to by 1 -printf("%d\n", *px); // => Prints 1 -printf("%d\n", x); // => Prints 1 - -int x_array[20]; // Arrays are a good way to allocate a contiguous block of memory -int xx; -for (xx=0; xx<20; xx++) { - x_array[xx] = 20 - xx; -} // Initialize x_array to 20, 19, 18,... 2, 1 - -// Declare a pointer of type int and initialize it to point to x_array -int* x_ptr = x_array; -// x_ptr now points to the first element in the array (the integer 20). -// This works because arrays are actually just pointers to their first element. - -// Arrays are pointers to their first element -printf("%d\n", *(x_ptr)); // => Prints 20 -printf("%d\n", x_array[0]); // => Prints 20 - -// Pointers are incremented and decremented based on their type -printf("%d\n", *(x_ptr + 1)); // => Prints 19 -printf("%d\n", x_array[1]); // => Prints 19 - -// You can also dynamically allocate contiguous blocks of memory with the -// standard library function malloc, which takes one integer argument -// representing the number of bytes to allocate from the heap. -int* my_ptr = (int*) malloc(sizeof(int) * 20); -for (xx=0; xx<20; xx++) { - *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx would also work here -} // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) - -// Dereferencing memory that you haven't allocated gives -// unpredictable results -printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? - -// When you're done with a malloc'd block of memory, you need to free it, -// or else no one else can use it until your program terminates -free(my_ptr); - -// Strings can be char arrays, but are usually represented as char -// pointers: -char* my_str = "This is my very own string"; - -printf("%c\n", *my_str); // => 'T' - -function_1(); + // print output using printf, for "print formatted" + // %d is an integer, \n is a newline + printf("%d\n", 0); // => Prints 0 + // All statements must end with a semicolon + + /////////////////////////////////////// + // Types + /////////////////////////////////////// + + // You have to declare variables before using them. A variable declaration + // requires you to specify its type; a variable's type determines its size + // in bytes. + + // ints are usually 4 bytes + int x_int = 0; + + // shorts are usually 2 bytes + short x_short = 0; + + // chars are guaranteed to be 1 byte + char x_char = 0; + 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 + long x_long = 0; + long long x_long_long = 0; + + // floats are usually 32-bit floating point numbers + float x_float = 0.0; + + // doubles are usually 64-bit floating-point numbers + double x_double = 0.0; + + // Integral types may be unsigned. This means they can't be negative, but + // the maximum value of an unsigned variable is greater than the maximum + // signed value of the same size. + unsigned char ux_char; + unsigned short ux_short; + unsigned int ux_int; + unsigned long long ux_long_long; + + // Other than char, which is always 1 byte (but not necessarily 8 bits!), + // these types vary in size depending on your machine and compiler. + // sizeof(T) gives you the size of a variable with type T in + // bytes so you can express the size of these types in a portable way. + // sizeof(obj) yields the size of an actual expression (variable, literal, etc.). + // For example, + printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) + + + // It's worth noting that if the argument of the `sizeof` operator is not a type but an expression, + // then its argument is not evaluated except VLAs (see below). Also, `sizeof()` is an operator, not a function, + // furthermore, the value it yields is a compile-time constant (except when used on VLAs, again.) + int a = 1; + size_t size = sizeof(a++); // a++ is not evaluated + printf("sizeof(a++) = %zu where a = %d\n", size, a); + // the above code prints "sizeof(a++) = 4 where a = 1" (on a usual 32-bit architecture) + + // Arrays must be initialized with a concrete size. + char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes + int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes + // (assuming 4-byte words) + + + // You can initialize an array to 0 thusly: + char my_array[20] = {0}; + + // Indexing an array is like other languages -- or, + // rather, other languages are like C + my_array[0]; // => 0 + + // Arrays are mutable; it's just memory! + my_array[1] = 2; + printf("%d\n", my_array[1]); // => 2 + + // In C99 (and as an optional feature in C11), variable-length arrays (VLAs) can be declared as well. + // The size of such an array need not be a compile time constant: + printf("Enter the array size: "); // ask the user for an array size + char buf[0x100]; + fgets(buf, sizeof buf, stdin); + size_t size = strtoul(buf, NULL, 10); // strtoul parses a string to an unsigned integer + 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: + Enter the array size: 10 + sizeof array = 40 + + // Strings are just arrays of chars terminated by a NUL (0x00) byte, + // represented in strings as the special character '\0'. + // (We don't have to include the NUL byte in string literals; the compiler + // inserts it at the end of the array for us.) + char a_string[20] = "This is a string"; + printf("%s\n", a_string); // %s formats a string + + /* + You may have noticed that a_string is only 16 chars long. + Char #17 is the NUL byte. + Chars #18, 19 and 20 are 0 as well - if an initializer list (in this case, the string literal) + has less elements than the array it is initializing, then excess array elements are implicitly + initialized to zero. This is why int ar[10] = { 0 } works as expected intuitively. + */ + + printf("%d\n", a_string[16]); // => 0 + + // So string literals are strings enclosed within double quotes, but if we have characters + // between single quotes, that's a character literal. + // It's of type `int`, and *not* `char` (for hystorical reasons). + int cha = 'a'; // fine + char chb = 'a'; // fine too (implicit conversion from int to char - truncation) + + /////////////////////////////////////// + // Operators + /////////////////////////////////////// + + int i1 = 1, i2 = 2; // Shorthand for multiple declaration + float f1 = 1.0, f2 = 2.0; + + // Arithmetic is straightforward + i1 + i2; // => 3 + i2 - i1; // => 1 + i2 * i1; // => 2 + i1 / i2; // => 0 (0.5, but truncated towards 0) + + f1 / f2; // => 0.5, plus or minus epsilon - floating-point numbers and calculations are not exact + + // Modulo is there as well + 11 % 3; // => 2 + + // Comparison operators are probably familiar, but + // there is no boolean type in c. We use ints instead. + // 0 is false, anything else is true. (The comparison + // operators always yield 0 or 1.) + 3 == 2; // => 0 (false) + 3 != 2; // => 1 (true) + 3 > 2; // => 1 + 3 < 2; // => 0 + 2 <= 2; // => 1 + 2 >= 2; // => 1 + + // Logic works on ints + !3; // => 0 (Logical not) + !0; // => 1 + 1 && 1; // => 1 (Logical and) + 0 && 1; // => 0 + 0 || 1; // => 1 (Logical or) + 0 || 0; // => 0 + + // Bitwise operators! + ~0x0F; // => 0xF0 (bitwise negation, "1's complement") + 0x0F & 0xF0; // => 0x00 (bitwise AND) + 0x0F | 0xF0; // => 0xFF (bitwise OR) + 0x04 ^ 0x0F; // => 0x0B (bitwise XOR) + 0x01 << 1; // => 0x02 (bitwise left shift (by 1)) + 0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) + + /////////////////////////////////////// + // Control Structures + /////////////////////////////////////// + + if (0) { + printf("I am never run\n"); + } else if (0) { + printf("I am also never run\n"); + } else { + printf("I print\n"); + } + + // While loops exist + int ii = 0; + while (ii < 10) { + printf("%d, ", ii++); // ii++ increments ii in-place, after yielding its value ("postincrement"). + } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + int kk = 0; + do { + printf("%d, ", kk); + } while (++kk < 10); // ++kk increments kk in-place, and yields the already incremented value ("preincrement") + // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // For loops too + int jj; + for (jj=0; jj < 10; jj++) { + printf("%d, ", jj); + } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + /////////////////////////////////////// + // Typecasting + /////////////////////////////////////// + + // Every value in C has a type, but you can cast one value into another type + // if you want (with some constraints). + + int x_hex = 0x01; // You can assign vars with hex literals + + // Casting between types will attempt to preserve their numeric values + printf("%d\n", x_hex); // => Prints 1 + printf("%d\n", (short) x_hex); // => Prints 1 + printf("%d\n", (char) x_hex); // => Prints 1 + + // Types will overflow without warning + printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) + // printf("%d\n", (unsigned char) 257); would be undefined behavior - `char' is usually signed + // on most modern systems, and signed integer overflow invokes UB. + // Also, for determining the maximal value of a `char`, a `signed char` and an `unisigned char`, + // respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from + + // Integral types can be cast to floating-point types, and vice-versa. + printf("%f\n", (float)100); // %f formats a float + printf("%lf\n", (double)100); // %lf formats a double + printf("%d\n", (char)100.0); + + /////////////////////////////////////// + // Pointers + /////////////////////////////////////// + + // A pointer is a variable declared to store a memory address. Its declaration will + // also tell you the type of data it points to. You can retrieve the memory address + // of your variables, then mess with them. + + int x = 0; + printf("%p\n", (void *)&x); // Use & to retrieve the address of a variable + // (%p formats an object pointer of type void *) + // => Prints some address in memory; + + + // Pointers start with * in their declaration + int *px, not_a_pointer; // px is a pointer to an int + px = &x; // Stores the address of x in px + printf("%p\n", (void *)px); // => Prints some address in memory + printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); + // => Prints "8, 4" on a typical 64-bit system + + // To retreive the value at the address a pointer is pointing to, + // put * in front to de-reference it. + // Note: yes, it may be confusing that '*' is used for _both_ declaring a pointer and dereferencing it. + printf("%d\n", *px); // => Prints 0, the value of x, which is what px is pointing to the address of + + // You can also change the value the pointer is pointing to. + // We'll have to wrap the de-reference in parenthesis because + // ++ has a higher precedence than *. + (*px)++; // Increment the value px is pointing to by 1 + printf("%d\n", *px); // => Prints 1 + printf("%d\n", x); // => Prints 1 + + int x_array[20]; // Arrays are a good way to allocate a contiguous block of memory + int xx; + for (xx = 0; xx < 20; xx++) { + x_array[xx] = 20 - xx; + } // Initialize x_array to 20, 19, 18,... 2, 1 + + // Declare a pointer of type int and initialize it to point to x_array + int* x_ptr = x_array; + // x_ptr now points to the first element in the array (the integer 20). + // This works because arrays often decay into pointers to their first element. + // For example, when an array is passed to a function or is assigned to a pointer, + // it decays into (implicitly converted to) a pointer. + // Exceptions: when the array is the argument of the `&` (address-od) operator: + int arr[10]; + int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! It's of type "pointer to array" (of ten `int`s). + // or when the array is a string literal used for initializing a char array: + char arr[] = "foobarbazquirk"; + // or when it's the argument of the `sizeof` or `alignof` operator: + int arr[10]; + int *ptr = arr; // equivalent with int *ptr = &arr[0]; + printf("%zu %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" + + + // Pointers are incremented and decremented based on their type + // (this is called pointer arithmetic) + printf("%d\n", *(x_ptr + 1)); // => Prints 19 + printf("%d\n", x_array[1]); // => Prints 19 + + // You can also dynamically allocate contiguous blocks of memory with the + // standard library function malloc, which takes one argument of type size_t + // representing the number of bytes to allocate (usually from the heap, although this + // may not be true on e. g. embedded systems - the C standard says nothing about it). + int *my_ptr = malloc(sizeof(*my_ptr) * 20); + for (xx = 0; xx < 20; xx++) { + *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx would also work here, and it's also more readable + } // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) + + // 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. + + // When you're done with a malloc'd block of memory, you need to free it, + // or else no one else can use it until your program terminates + // (this is called a "memory leak"): + free(my_ptr); + + // Strings are arrays of char, but they are usually represented as a + // pointer-to-char (which is a pointer to the first element of the array). + // It's good practice to use `const char *' when referring to a string literal, + // since string literals shall not be modified (i. e. "foo"[0] = 'a' is ILLEGAL.) + const char *my_str = "This is my very own string literal"; + printf("%c\n", *my_str); // => 'T' + + // This is not the case if the string is an array (potentially initialized with a string literal) + // that resides in writable memory, as in: + char foo[] = "foo"; + foo[0] = 'a'; // this is legal, foo now contains "aoo" + + function_1(); } // end main function /////////////////////////////////////// @@ -300,7 +359,8 @@ function_1(); // Function declaration syntax: // () -int add_two_ints(int x1, int x2){ +int add_two_ints(int x1, int x2) +{ return x1 + x2; // Use return to return a value } @@ -312,10 +372,12 @@ Example: in-place string reversal */ // A void function returns no value -void str_reverse(char* str_in){ +void str_reverse(char *str_in) +{ char tmp; - int ii=0, len = strlen(str_in); // Strlen is part of the c standard library - for(ii=0; ii ".tset a si sihT" typedef int my_type; my_type my_type_var = 0; -// Structs are just collections of data +// Structs are just collections of data, the members are allocated sequentially, in the order they are written: struct rectangle { int width; int height; }; +// it's generally not true that sizeof(struct rectangle) == sizeof(int) + sizeof(int) due to +// potential padding between the structure members (this is for alignment reasons. Probably won't +// happen if all members are of the same type, but watch out! +// See http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member +// for further information. -void function_1(){ - +void function_1() +{ struct rectangle my_rec; // Access struct members with . @@ -352,22 +419,29 @@ void function_1(){ my_rec.height = 20; // You can declare pointers to structs - struct rectangle* my_rec_ptr = &my_rec; + struct rectangle *my_rec_ptr = &my_rec; // Use dereferencing to set struct pointer members... (*my_rec_ptr).width = 30; - // ... or use the -> shorthand + // ... or even better: prefer the -> shorthand for the sake of readability my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10; } // You can apply a typedef to a struct for convenience typedef struct rectangle rect; -int area(rect r){ +int area(rect r) +{ return r.width * r.height; } +// if you have large structs, you can pass them "by pointer" to avoid copying the whole struct: +int area(const rect *r) +{ + return r->width * r->height; +} + /////////////////////////////////////// // Function pointers /////////////////////////////////////// @@ -379,10 +453,11 @@ However, definition syntax may be initially confusing. Example: use str_reverse from a pointer */ -void str_reverse_through_pointer(char * str_in) { +void str_reverse_through_pointer(char *str_in) { // Define a function pointer variable, named f. void (*f)(char *); // Signature should exactly match the target function. f = &str_reverse; // Assign the address for the actual function (determined at runtime) + // f = str_reverse; would work as well - functions decay into pointers, similar to arrays (*f)(str_in); // Just calling the function through the pointer // f(str_in); // That's an alternative but equally valid syntax for calling it. } @@ -403,7 +478,15 @@ typedef void (*my_fnp_type)(char *); ## 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) +It is *the* book about C, written by the creators of C. Be careful, though - it's ancient and it contains some +inaccuracies (well, ideas that are not considered good anymore) or now-changed practices. + +Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/). + +If you have a question, read the [compl.lang.c Frequently Asked Questions](http://c-faq.com). -Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/) +It's very important to use proper spacing, indentation and to be consistent with your coding style in general. +Readable code is better than clever code and fast code. For a good, sane coding style to adopt, see the +[Linux kernel coding stlye](https://www.kernel.org/doc/Documentation/CodingStyle). Other than that, Google is your friend. -- cgit v1.2.3 From f2c41a8a9915606ed801a87f153d91fd347069a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Thu, 15 Aug 2013 12:36:29 +0200 Subject: whoops, fixed typos and added missing info --- c.html.markdown | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ac6c7ab4..ec5c5e0d 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -5,7 +5,6 @@ language: c filename: learnc.c contributors: - ["Adam Bard", "http://adambard.com/"] - - ["Árpád Goretity", "http://twitter.com/h2co3_ios"] --- Ah, C. Still **the** language of modern high-performance computing. @@ -29,7 +28,13 @@ Multi-line comments look like this. They work in C89 as well. // file names between are headers from the C standard library. // They are searched for by the preprocessor in the system include paths // (usually /usr/lib on Unices, can be controlled with the -I option if you are using GCC or clang.) -// For your +// For your own headers, use double quotes instead of angle brackets: +#include "my_header.h" + +// The C preprocessor introduces an almost fully-featured macro language. It's useful, but +// it can be confusing (and what's even worse, it can be misused). Read the +// Wikipedia article on the C preprocessor for further information: +// http://en.wikipedia.org/wiki/C_preprocessor // Declare function signatures in advance in a .h file, or at the top of // your .c file. -- cgit v1.2.3 From 273c08d1fe2ebe362826fd0707d55b728538c33d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Thu, 15 Aug 2013 13:08:52 +0200 Subject: fixed header, added switch statement --- c.html.markdown | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ec5c5e0d..8e16837c 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,10 +1,12 @@ --- -name: c -category: language -language: c -filename: learnc.c -contributors: - - ["Adam Bard", "http://adambard.com/"] +- name: c +- category: language +- language: c +- filename: learnc.c +- contributors: + - [Adam Bard](http://adambard.com/) + - [Árpád Goretity](http://twitter.com/H2CO3_iOS) + --- Ah, C. Still **the** language of modern high-performance computing. @@ -152,7 +154,7 @@ int main() { // So string literals are strings enclosed within double quotes, but if we have characters // between single quotes, that's a character literal. - // It's of type `int`, and *not* `char` (for hystorical reasons). + // It's of type `int`, and *not* `char` (for historical reasons). int cha = 'a'; // fine char chb = 'a'; // fine too (implicit conversion from int to char - truncation) @@ -176,6 +178,7 @@ int main() { // Comparison operators are probably familiar, but // there is no boolean type in c. We use ints instead. + // (Or _Bool or bool in C99.) // 0 is false, anything else is true. (The comparison // operators always yield 0 or 1.) 3 == 2; // => 0 (false) @@ -185,6 +188,13 @@ int main() { 2 <= 2; // => 1 2 >= 2; // => 1 + // C is not Python - comparisons don't chain. + int a = 1; + // WRONG: + int between_0_and_2 = 0 < a < 2; + // Correct: + int between_0_and_2 = 0 < a && a < 2; + // Logic works on ints !3; // => 0 (Logical not) !0; // => 1 @@ -201,6 +211,12 @@ int main() { 0x01 << 1; // => 0x02 (bitwise left shift (by 1)) 0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) + // Be careful when shifting signed integers - the following are all undefined behavior: + // - shifting into the sign bit of a signed integer (int a = 1 << 32) + // - left-shifting a negative number (int a = -1 << 2) + // - shifting by an offset which is more than or equal to the width of the type of the LHS: + // int a = 1 << 32; // UB if int is 32 bits wide + /////////////////////////////////////// // Control Structures /////////////////////////////////////// @@ -237,6 +253,22 @@ int main() { printf("\n"); + // branching with multiple choices: switch() + switch (some_integral_expression) { + case 0: // labels need to be integral *constant* epxressions + do_stuff(); + break; // if you don't break, control flow falls over labels - you usually don't want that. + case 1: + do_something_else(); + break; + default: + // if `some_integral_expression` didn't match any of the labels + fputs("error!\n", stderr); + exit(-1); + break; + } + + /////////////////////////////////////// // Typecasting /////////////////////////////////////// -- cgit v1.2.3 From 8aa0ab6068a13491ec9cba59bce32911ab9f8061 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 16 Aug 2013 09:44:22 -0700 Subject: Edits --- c.html.markdown | 250 ++++++++++++++++++++++++++------------------------------ 1 file changed, 117 insertions(+), 133 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 00b13cb0..24a96463 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,11 +1,9 @@ --- -- name: c -- category: language -- language: c -- filename: learnc.c -- contributors: - - [Adam Bard](http://adambard.com/) - - [Árpád Goretity](http://twitter.com/H2CO3_iOS) +language: c +filename: learnc.c +contributors: + - ["Adam Bard", "http://adambard.com/"] + - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"] --- @@ -27,17 +25,10 @@ Multi-line comments look like this. They work in C89 as well. #include #include -// file names between are headers from the C standard library. -// They are searched for by the preprocessor in the system include paths -// (usually /usr/lib on Unices, can be controlled with the -I option if you are using GCC or clang.) +// (File names between are headers from the C standard library.) // For your own headers, use double quotes instead of angle brackets: #include "my_header.h" -// The C preprocessor introduces an almost fully-featured macro language. It's useful, but -// it can be confusing (and what's even worse, it can be misused). Read the -// Wikipedia article on the C preprocessor for further information: -// http://en.wikipedia.org/wiki/C_preprocessor - // Declare function signatures in advance in a .h file, or at the top of // your .c file. void function_1(); @@ -50,132 +41,117 @@ int main() { // %d is an integer, \n is a newline printf("%d\n", 0); // => Prints 0 // All statements must end with a semicolon - + /////////////////////////////////////// // Types /////////////////////////////////////// - - // You have to declare variables before using them. A variable declaration - // requires you to specify its type; a variable's type determines its size - // in bytes. - + // ints are usually 4 bytes int x_int = 0; - + // shorts are usually 2 bytes short x_short = 0; - + // chars are guaranteed to be 1 byte char x_char = 0; 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 long x_long = 0; long long x_long_long = 0; - + // floats are usually 32-bit floating point numbers float x_float = 0.0; - + // doubles are usually 64-bit floating-point numbers double x_double = 0.0; - - // Integral types may be unsigned. This means they can't be negative, but - // the maximum value of an unsigned variable is greater than the maximum - // signed value of the same size. - unsigned char ux_char; + + // Integral types may be unsigned. unsigned short ux_short; unsigned int ux_int; unsigned long long ux_long_long; - - // Other than char, which is always 1 byte (but not necessarily 8 bits!), - // these types vary in size depending on your machine and compiler. - // sizeof(T) gives you the size of a variable with type T in - // bytes so you can express the size of these types in a portable way. - // sizeof(obj) yields the size of an actual expression (variable, literal, etc.). - // For example, + + // sizeof(T) gives you the size of a variable with type T in bytes + // sizeof(obj) yields the size of the expression (variable, literal, etc.). printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) - - - // It's worth noting that if the argument of the `sizeof` operator is not a type but an expression, - // then its argument is not evaluated except VLAs (see below). Also, `sizeof()` is an operator, not a function, - // furthermore, the value it yields is a compile-time constant (except when used on VLAs, again.) + + + // If the argument of the `sizeof` operator an expression, then its argument + // is not evaluated (except VLAs (see below)). + // The value it yields in this case is a compile-time constant. int a = 1; size_t size = sizeof(a++); // a++ is not evaluated printf("sizeof(a++) = %zu where a = %d\n", size, a); - // the above code prints "sizeof(a++) = 4 where a = 1" (on a usual 32-bit architecture) - + // prints "sizeof(a++) = 4 where a = 1" (on a 32-bit architecture) + // Arrays must be initialized with a concrete size. char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes // (assuming 4-byte words) - - + + // You can initialize an array to 0 thusly: char my_array[20] = {0}; - + // Indexing an array is like other languages -- or, // rather, other languages are like C my_array[0]; // => 0 - + // Arrays are mutable; it's just memory! my_array[1] = 2; printf("%d\n", my_array[1]); // => 2 - - // In C99 (and as an optional feature in C11), variable-length arrays (VLAs) can be declared as well. - // The size of such an array need not be a compile time constant: + + // In C99 (and as an optional feature in C11), variable-length arrays (VLAs) + // can be declared as well. The size of such an array need not be a compile + // time constant: printf("Enter the array size: "); // ask the user for an array size char buf[0x100]; fgets(buf, sizeof buf, stdin); - size_t size = strtoul(buf, NULL, 10); // strtoul parses a string to an unsigned integer + + // strtoul parses a string to an unsigned integer + size_t size = strtoul(buf, NULL, 10); 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: - Enter the array size: 10 - sizeof array = 40 - + // > Enter the array size: 10 + // > sizeof array = 40 + // Strings are just arrays of chars terminated by a NUL (0x00) byte, // represented in strings as the special character '\0'. // (We don't have to include the NUL byte in string literals; the compiler // inserts it at the end of the array for us.) char a_string[20] = "This is a string"; printf("%s\n", a_string); // %s formats a string - - /* - You may have noticed that a_string is only 16 chars long. - Char #17 is the NUL byte. - Chars #18, 19 and 20 are 0 as well - if an initializer list (in this case, the string literal) - has less elements than the array it is initializing, then excess array elements are implicitly - initialized to zero. This is why int ar[10] = { 0 } works as expected intuitively. - */ - + printf("%d\n", a_string[16]); // => 0 - - // So string literals are strings enclosed within double quotes, but if we have characters - // between single quotes, that's a character literal. + // i.e., byte #17 is 0 (as are 18, 19, and 20) + + // If we have characters between single quotes, that's a character literal. // It's of type `int`, and *not* `char` (for historical reasons). int cha = 'a'; // fine - char chb = 'a'; // fine too (implicit conversion from int to char - truncation) - + char chb = 'a'; // fine too (implicit conversion from int to char) + /////////////////////////////////////// // Operators /////////////////////////////////////// - + int i1 = 1, i2 = 2; // Shorthand for multiple declaration float f1 = 1.0, f2 = 2.0; - + // Arithmetic is straightforward i1 + i2; // => 3 i2 - i1; // => 1 i2 * i1; // => 2 i1 / i2; // => 0 (0.5, but truncated towards 0) - - f1 / f2; // => 0.5, plus or minus epsilon - floating-point numbers and calculations are not exact - + + f1 / f2; // => 0.5, plus or minus epsilon + // Floating-point numbers and calculations are not exact + // Modulo is there as well 11 % 3; // => 2 - + // Comparison operators are probably familiar, but // there is no boolean type in c. We use ints instead. // (Or _Bool or bool in C99.) @@ -187,14 +163,14 @@ int main() { 3 < 2; // => 0 2 <= 2; // => 1 2 >= 2; // => 1 - + // C is not Python - comparisons don't chain. int a = 1; // WRONG: int between_0_and_2 = 0 < a < 2; // Correct: int between_0_and_2 = 0 < a && a < 2; - + // Logic works on ints !3; // => 0 (Logical not) !0; // => 1 @@ -202,7 +178,7 @@ int main() { 0 && 1; // => 0 0 || 1; // => 1 (Logical or) 0 || 0; // => 0 - + // Bitwise operators! ~0x0F; // => 0xF0 (bitwise negation, "1's complement") 0x0F & 0xF0; // => 0x00 (bitwise AND) @@ -210,17 +186,17 @@ int main() { 0x04 ^ 0x0F; // => 0x0B (bitwise XOR) 0x01 << 1; // => 0x02 (bitwise left shift (by 1)) 0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) - - // Be careful when shifting signed integers - the following are all undefined behavior: + + // Be careful when shifting signed integers - the following are undefined: // - shifting into the sign bit of a signed integer (int a = 1 << 32) // - left-shifting a negative number (int a = -1 << 2) - // - shifting by an offset which is more than or equal to the width of the type of the LHS: + // - shifting by an offset which is >= the width of the type of the LHS: // int a = 1 << 32; // UB if int is 32 bits wide - + /////////////////////////////////////// // Control Structures /////////////////////////////////////// - + if (0) { printf("I am never run\n"); } else if (0) { @@ -228,36 +204,38 @@ int main() { } else { printf("I print\n"); } - + // While loops exist int ii = 0; while (ii < 10) { - printf("%d, ", ii++); // ii++ increments ii in-place, after yielding its value ("postincrement"). + printf("%d, ", ii++); // ii++ increments ii in-place + // after yielding its value ("postincrement"). } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - + printf("\n"); - + int kk = 0; do { printf("%d, ", kk); - } while (++kk < 10); // ++kk increments kk in-place, and yields the already incremented value ("preincrement") + } while (++kk < 10); // ++kk increments kk in-place, and yields + // the already incremented value ("preincrement") // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - + printf("\n"); - + // For loops too int jj; for (jj=0; jj < 10; jj++) { printf("%d, ", jj); } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - + printf("\n"); - + // branching with multiple choices: switch() switch (some_integral_expression) { case 0: // labels need to be integral *constant* epxressions do_stuff(); - break; // if you don't break, control flow falls over labels - you usually don't want that. + break; // if you don't break, control flow falls over labels case 1: do_something_else(); break; @@ -267,73 +245,74 @@ int main() { exit(-1); break; } - + /////////////////////////////////////// // Typecasting /////////////////////////////////////// - + // Every value in C has a type, but you can cast one value into another type // if you want (with some constraints). - + int x_hex = 0x01; // You can assign vars with hex literals - + // Casting between types will attempt to preserve their numeric values printf("%d\n", x_hex); // => Prints 1 printf("%d\n", (short) x_hex); // => Prints 1 printf("%d\n", (char) x_hex); // => Prints 1 - + // Types will overflow without warning printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) - // printf("%d\n", (unsigned char) 257); would be undefined behavior - `char' is usually signed - // on most modern systems, and signed integer overflow invokes UB. - // Also, for determining the maximal value of a `char`, a `signed char` and an `unisigned char`, + + // For determining the max value of a `char`, a `signed char` and an `unisigned char`, // respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from - + // Integral types can be cast to floating-point types, and vice-versa. printf("%f\n", (float)100); // %f formats a float printf("%lf\n", (double)100); // %lf formats a double printf("%d\n", (char)100.0); - + /////////////////////////////////////// // Pointers /////////////////////////////////////// - + // A pointer is a variable declared to store a memory address. Its declaration will // also tell you the type of data it points to. You can retrieve the memory address // of your variables, then mess with them. - + int x = 0; printf("%p\n", (void *)&x); // Use & to retrieve the address of a variable // (%p formats an object pointer of type void *) // => Prints some address in memory; - - + + // Pointers start with * in their declaration int *px, not_a_pointer; // px is a pointer to an int px = &x; // Stores the address of x in px printf("%p\n", (void *)px); // => Prints some address in memory printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); // => Prints "8, 4" on a typical 64-bit system - + // To retreive the value at the address a pointer is pointing to, // put * in front to de-reference it. - // Note: yes, it may be confusing that '*' is used for _both_ declaring a pointer and dereferencing it. - printf("%d\n", *px); // => Prints 0, the value of x, which is what px is pointing to the address of - + // Note: yes, it may be confusing that '*' is used for _both_ declaring a + // pointer and dereferencing it. + printf("%d\n", *px); // => Prints 0, the value of x + // You can also change the value the pointer is pointing to. // We'll have to wrap the de-reference in parenthesis because // ++ has a higher precedence than *. (*px)++; // Increment the value px is pointing to by 1 printf("%d\n", *px); // => Prints 1 printf("%d\n", x); // => Prints 1 - - int x_array[20]; // Arrays are a good way to allocate a contiguous block of memory + + // Arrays are a good way to allocate a contiguous block of memory + int x_array[20]; int xx; for (xx = 0; xx < 20; xx++) { x_array[xx] = 20 - xx; } // Initialize x_array to 20, 19, 18,... 2, 1 - + // Declare a pointer of type int and initialize it to point to x_array int* x_ptr = x_array; // x_ptr now points to the first element in the array (the integer 20). @@ -342,50 +321,52 @@ int main() { // it decays into (implicitly converted to) a pointer. // Exceptions: when the array is the argument of the `&` (address-od) operator: int arr[10]; - int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! It's of type "pointer to array" (of ten `int`s). + int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! + // It's of type "pointer to array" (of ten `int`s). // or when the array is a string literal used for initializing a char array: char arr[] = "foobarbazquirk"; // or when it's the argument of the `sizeof` or `alignof` operator: int arr[10]; int *ptr = arr; // equivalent with int *ptr = &arr[0]; printf("%zu %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" - + // Pointers are incremented and decremented based on their type // (this is called pointer arithmetic) printf("%d\n", *(x_ptr + 1)); // => Prints 19 printf("%d\n", x_array[1]); // => Prints 19 - + // You can also dynamically allocate contiguous blocks of memory with the // standard library function malloc, which takes one argument of type size_t // representing the number of bytes to allocate (usually from the heap, although this // may not be true on e. g. embedded systems - the C standard says nothing about it). int *my_ptr = malloc(sizeof(*my_ptr) * 20); for (xx = 0; xx < 20; xx++) { - *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx would also work here, and it's also more readable + *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx } // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) - + // 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. - + // When you're done with a malloc'd block of memory, you need to free it, // or else no one else can use it until your program terminates // (this is called a "memory leak"): free(my_ptr); - + // Strings are arrays of char, but they are usually represented as a // pointer-to-char (which is a pointer to the first element of the array). // It's good practice to use `const char *' when referring to a string literal, // since string literals shall not be modified (i. e. "foo"[0] = 'a' is ILLEGAL.) const char *my_str = "This is my very own string literal"; printf("%c\n", *my_str); // => 'T' - - // This is not the case if the string is an array (potentially initialized with a string literal) + + // This is not the case if the string is an array + // (potentially initialized with a string literal) // that resides in writable memory, as in: char foo[] = "foo"; foo[0] = 'a'; // this is legal, foo now contains "aoo" - + function_1(); } // end main function @@ -435,17 +416,17 @@ printf("%s\n", c); // => ".tset a si sihT" typedef int my_type; my_type my_type_var = 0; -// Structs are just collections of data, the members are allocated sequentially, in the order they are written: +// Structs are just collections of data, the members are allocated sequentially, +// in the order they are written: struct rectangle { int width; int height; }; -// it's generally not true that sizeof(struct rectangle) == sizeof(int) + sizeof(int) due to -// potential padding between the structure members (this is for alignment reasons. Probably won't -// happen if all members are of the same type, but watch out! -// See http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member -// for further information. +// It's not generally true that +// sizeof(struct rectangle) == sizeof(int) + sizeof(int) +// due to potential padding between the structure members (this is for alignment +// reasons). [1] void function_1() { @@ -473,7 +454,8 @@ int area(rect r) return r.width * r.height; } -// if you have large structs, you can pass them "by pointer" to avoid copying the whole struct: +// if you have large structs, you can pass them "by pointer" to avoid copying +// the whole struct: int area(const rect *r) { return r->width * r->height; @@ -527,3 +509,5 @@ Readable code is better than clever code and fast code. For a good, sane coding [Linux kernel coding stlye](https://www.kernel.org/doc/Documentation/CodingStyle). Other than that, Google is your friend. + +[1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member -- cgit v1.2.3 From 07b5c4934ce98d9f3431c23d5e56a46faba77360 Mon Sep 17 00:00:00 2001 From: mhauserr Date: Tue, 20 Aug 2013 23:50:15 +0100 Subject: Update c.html.markdown Added explanation of size_t --- c.html.markdown | 1 + 1 file changed, 1 insertion(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 24a96463..ae66fa78 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -81,6 +81,7 @@ int main() { // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; + // size_t is an unsiged integer type of at least 2 bytes used to represent the size of an object size_t size = sizeof(a++); // a++ is not evaluated printf("sizeof(a++) = %zu where a = %d\n", size, a); // prints "sizeof(a++) = 4 where a = 1" (on a 32-bit architecture) -- cgit v1.2.3 From c4c8c02df970c028bd96f2e133a8bf76d5811fc5 Mon Sep 17 00:00:00 2001 From: mhauserr Date: Wed, 21 Aug 2013 00:02:33 +0100 Subject: Added explanation of size_t --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ae66fa78..3acf1a4d 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -81,7 +81,7 @@ int main() { // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; - // size_t is an unsiged integer type of at least 2 bytes used to represent the size of an object + // size_t is an unsiged integer type of at least 2 bytes used to represent the size of an object. size_t size = sizeof(a++); // a++ is not evaluated printf("sizeof(a++) = %zu where a = %d\n", size, a); // prints "sizeof(a++) = 4 where a = 1" (on a 32-bit architecture) -- cgit v1.2.3 From 58cd4b274f4ef6dce15bf30eccad4691aaf835ed Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 09:50:13 -0500 Subject: add special characters to c --- c.html.markdown | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 24a96463..c8c3e33b 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -20,6 +20,12 @@ memory management and C will take you as far as you need to go. Multi-line comments look like this. They work in C89 as well. */ +//Special characters: +'\n' // newline character +'\t' // tab character +'\b' // backspace character +'\0' // null character + // Import headers with #include #include #include -- cgit v1.2.3 From deaaf3412d01a69fdc4354564fba5506ef65f4c8 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 10:51:48 -0500 Subject: Add print formatting characters --- c.html.markdown | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index c8c3e33b..a9fd8e50 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -23,9 +23,22 @@ Multi-line comments look like this. They work in C89 as well. //Special characters: '\n' // newline character '\t' // tab character +'\v' // vertical tab +'\f' // new page +'\r' // carriage return '\b' // backspace character '\0' // null character +//print formatting: +"%d" // integer +"%3d" // minimum length of 3 digits for integer (right justifies text) +"%s" // string +"%f" // float +"%3.2f" // minimum 3 digits left and 2 digits right decimal float +"%7.4s" // (can do with strings too) +"%c" // char +"%p" // pointer + // Import headers with #include #include #include -- cgit v1.2.3 From e03cda583dd6127831a32fcc8bd8cd8b53399794 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 11:44:45 -0500 Subject: Add more to string formatting. --- c.html.markdown | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index a9fd8e50..4e1e1e56 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -22,7 +22,7 @@ Multi-line comments look like this. They work in C89 as well. //Special characters: '\n' // newline character -'\t' // tab character +'\t' // tab character (left justifies text) '\v' // vertical tab '\f' // new page '\r' // carriage return @@ -38,6 +38,12 @@ Multi-line comments look like this. They work in C89 as well. "%7.4s" // (can do with strings too) "%c" // char "%p" // pointer +"%x" // hexidecimal +"%o" // octal +"%%" // prints % + +// Constants: use #define keyword, no semicolon at end. +#define DAYS_IN_YEAR = 365 // Import headers with #include #include -- cgit v1.2.3 From dba7ec8b9643f693bdb023f9827999b2b14d008b Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 12:50:58 -0500 Subject: Add getchar(), putchar(), EOF to C --- c.html.markdown | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 4e1e1e56..7010b9d5 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -427,6 +427,16 @@ void str_reverse(char *str_in) } } +// Built in functions: +// from stdio.h: +int c = getchar(); //reads character from user. If user types hello, only h is read. +// getchar() can be stored into int or char. I am using int because char is not large +// enough to store EOF used below. +while (c != EOF) { // EOF is value for "end of file". Linux: CTRL+D, Windows: CTRL+X + putchar(c); //prints character (without newline at end) + char c = getchar(); +} + /* char c[] = "This is a test."; str_reverse(c); -- cgit v1.2.3 From f1b1fd8e2efd6c30e553aae1c4f6cc28a6554e8f Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 13:06:37 -0500 Subject: Add clarity to EOF. Add %ld for longs in C --- c.html.markdown | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 7010b9d5..869ab984 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -34,6 +34,7 @@ Multi-line comments look like this. They work in C89 as well. "%3d" // minimum length of 3 digits for integer (right justifies text) "%s" // string "%f" // float +"%ld" // long "%3.2f" // minimum 3 digits left and 2 digits right decimal float "%7.4s" // (can do with strings too) "%c" // char @@ -429,10 +430,12 @@ void str_reverse(char *str_in) // Built in functions: // from stdio.h: -int c = getchar(); //reads character from user. If user types hello, only h is read. -// getchar() can be stored into int or char. I am using int because char is not large -// enough to store EOF used below. -while (c != EOF) { // EOF is value for "end of file". Linux: CTRL+D, Windows: CTRL+X +int c = getchar(); //reads character from input. If input = hi, only h is read. +// getchar() can be stored into int or char. I am using int because +// char is not large enough to store EOF used below. +while ((c = getchar()) != EOF) { // EOF constant "end of file". + // Linux: CTRL+D, Windows: CTRL+X + // must have () around getchar() as != is run before =. putchar(c); //prints character (without newline at end) char c = getchar(); } -- cgit v1.2.3 From b0c5ca0a1cc5a62fc8569fffffcdf35bf44e8dc8 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 15:57:18 -0500 Subject: Add note about loops C --- c.html.markdown | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 869ab984..166c43e6 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -231,6 +231,12 @@ int main() { printf("I print\n"); } + // Notes: + // Loops MUST always have a body. If no body is needed, do this: + for (i = 0; i <= 5; i++) { + ; // use semicolon to act as the body (null statement) + } + // While loops exist int ii = 0; while (ii < 10) { -- cgit v1.2.3 From 5c711eb30fe8cd810627742a30c016f458bd773c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 16:24:56 -0500 Subject: Add more shorthand notes, array notes to C --- c.html.markdown | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 166c43e6..c6fee5d7 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -166,6 +166,10 @@ int main() { int i1 = 1, i2 = 2; // Shorthand for multiple declaration float f1 = 1.0, f2 = 2.0; + //more shorthands: + int a, b, c; + a = b = c = 0; + // Arithmetic is straightforward i1 + i2; // => 3 i2 - i1; // => 1 @@ -339,7 +343,7 @@ int main() { printf("%d\n", x); // => Prints 1 // Arrays are a good way to allocate a contiguous block of memory - int x_array[20]; + int x_array[20]; //declares array of size 20 (cannot change size) int xx; for (xx = 0; xx < 20; xx++) { x_array[xx] = 20 - xx; -- cgit v1.2.3 From dfd8afb4969c76b71a852e7bc8378b7e7f8f4bb3 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 16:36:16 -0500 Subject: Add ASCII chars to Types of C file. --- c.html.markdown | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index c6fee5d7..96f253b7 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -98,6 +98,10 @@ int main() { unsigned int ux_int; unsigned long long ux_long_long; + // chars inside single quotes '*' are ASCII versions of + '0' //==> 48 on the ASCII table. + 'A' //==> 65 on the ASCII table. + // sizeof(T) gives you the size of a variable with type T in bytes // sizeof(obj) yields the size of the expression (variable, literal, etc.). printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) -- cgit v1.2.3 From 79fdd62c6bcb13c550050efe02d6753d198a5a83 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 16:51:35 -0500 Subject: Add function prototype to C. --- c.html.markdown | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 96f253b7..75025b0c 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -422,6 +422,16 @@ int add_two_ints(int x1, int x2) return x1 + x2; // Use return to return a value } +// Must declare a 'funtion prototype' before main() when creating functions +// in file. +int getInt(char c); // function prototype +int main() { + return 0; +} +int getInt(char w) { //parameter name does not need to match function prototype + return 1; +} + /* Functions are pass-by-value, but you can make your own references with pointers so functions can mutate their values. -- cgit v1.2.3 From 41f65bb3415e7002ef171c351376c1c4d5336746 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 17:04:47 -0500 Subject: Clarified function call by value description. --- c.html.markdown | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 75025b0c..e6e2559e 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -433,8 +433,12 @@ int getInt(char w) { //parameter name does not need to match function prototype } /* -Functions are pass-by-value, but you can make your own references -with pointers so functions can mutate their values. +Functions are call by value. So when a function is called, the arguments passed +to the function are copies of original arguments (except arrays). Anything you +do to your arguments do not change the value of the actual argument where the +function was called. + +You can use pointers if you need to edit the original argument values. Example: in-place string reversal */ -- cgit v1.2.3 From 394ca958b3b61853b1fe8ec1063b3adb03239178 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 18:42:05 -0500 Subject: Add more notes to null character in C --- c.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index e6e2559e..90d0d358 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -27,7 +27,8 @@ Multi-line comments look like this. They work in C89 as well. '\f' // new page '\r' // carriage return '\b' // backspace character -'\0' // null character +'\0' // null character. Usually put at end of strings in C lang. + // hello\n\0. \0 used by convention to mark end of string. //print formatting: "%d" // integer -- cgit v1.2.3 From d632203255085171ce79a106a40797d1d5fa54a3 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 18:54:07 -0500 Subject: Add more notes to function prototype in C. --- c.html.markdown | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 90d0d358..ee60d168 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -425,13 +425,16 @@ int add_two_ints(int x1, int x2) // Must declare a 'funtion prototype' before main() when creating functions // in file. -int getInt(char c); // function prototype +void getInt(char c); // function prototype int main() { return 0; } -int getInt(char w) { //parameter name does not need to match function prototype - return 1; +void getInt(char w) { //parameter name does not need to match function prototype + ; } +//if function takes no parameters, do: int getInt(void); for function prototype +// and for the function declaration: int getInt(void) {} +// this is to keep compatibility with older versions of C. /* Functions are call by value. So when a function is called, the arguments passed -- cgit v1.2.3 From 8caf3768fb4a1f0fa14ca4765e7f168534c7cd8f Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 19:24:15 -0500 Subject: Add extern notes to C. --- c.html.markdown | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ee60d168..2a828ab7 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -99,7 +99,7 @@ int main() { unsigned int ux_int; unsigned long long ux_long_long; - // chars inside single quotes '*' are ASCII versions of + // chars inside single quotes '*' are character constants. '0' //==> 48 on the ASCII table. 'A' //==> 65 on the ASCII table. @@ -472,6 +472,12 @@ while ((c = getchar()) != EOF) { // EOF constant "end of file". char c = getchar(); } +//if referring to external variables outside function, must use extern keyword. +int i = 0; +void testFunc() { + extern int i; //i here is now using external variable i +} + /* char c[] = "This is a test."; str_reverse(c); -- cgit v1.2.3 From 411d9a9813e8c7174f35540198b6dadc8c0b665c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 19:29:25 -0500 Subject: Add more escape sequences to C. --- c.html.markdown | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 2a828ab7..4764c38e 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -21,14 +21,21 @@ Multi-line comments look like this. They work in C89 as well. */ //Special characters: +'\a' // alert (bell) character '\n' // newline character '\t' // tab character (left justifies text) '\v' // vertical tab -'\f' // new page +'\f' // new page (formfeed) '\r' // carriage return '\b' // backspace character '\0' // null character. Usually put at end of strings in C lang. // hello\n\0. \0 used by convention to mark end of string. +'\\' // backspace +'\?' // question mark +'\'' // single quote +'\"' // double quote +'\xhh' // hexadecimal number. Example: '\xb' = vertical tab character +'\ooo' // octal number. Example: '\013' = vertical tab character //print formatting: "%d" // integer -- cgit v1.2.3 From 2e8e2b5f3552bd9541a4eac6abba94a767dda8e4 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 20:51:11 -0500 Subject: Add enum to C. --- c.html.markdown | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 4764c38e..0ac603a7 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -54,6 +54,10 @@ Multi-line comments look like this. They work in C89 as well. // Constants: use #define keyword, no semicolon at end. #define DAYS_IN_YEAR = 365 +//enumeration constants are also ways to declare constants. +enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +// MON gets 2 automatically, TUE gets 3, etc. + // Import headers with #include #include #include -- cgit v1.2.3 From ca32d7a5f2edfe9dad2b43fc849b1495c2b5f889 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 21:16:32 -0500 Subject: Add clarity to characters in character set. --- c.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 0ac603a7..4e7dae5c 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -110,9 +110,9 @@ int main() { unsigned int ux_int; unsigned long long ux_long_long; - // chars inside single quotes '*' are character constants. - '0' //==> 48 on the ASCII table. - 'A' //==> 65 on the ASCII table. + // chars inside single quotes '*' are integers in your character set. + '0' //==> 48 on the ASCII character set. + 'A' //==> 65 on the ASCII character set. // sizeof(T) gives you the size of a variable with type T in bytes // sizeof(obj) yields the size of the expression (variable, literal, etc.). -- cgit v1.2.3 From e9c92321f4442ca4af75f6cce16d435287dad750 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 31 Aug 2013 21:18:59 -0500 Subject: Add include statement to popular C standar libraries. --- c.html.markdown | 1 + 1 file changed, 1 insertion(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 4e7dae5c..6d95f28b 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -62,6 +62,7 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; #include #include #include +#include // (File names between are headers from the C standard library.) // For your own headers, use double quotes instead of angle brackets: -- cgit v1.2.3 From 642e7c551e0f6292be403ed893a6695130cf350a Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 1 Sep 2013 10:44:55 -0500 Subject: Add note to while loop in C. --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 6d95f28b..f63adc05 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -260,7 +260,7 @@ int main() { // While loops exist int ii = 0; - while (ii < 10) { + while (ii < 10) { //ANY value not zero is true. printf("%d, ", ii++); // ii++ increments ii in-place // after yielding its value ("postincrement"). } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " -- cgit v1.2.3 From 977d226d26c056094a33f38da79d1d9395915f52 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 1 Sep 2013 10:59:30 -0500 Subject: Reworded incrementing operators in C. --- c.html.markdown | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index f63adc05..c5ac7708 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -261,8 +261,7 @@ int main() { // While loops exist int ii = 0; while (ii < 10) { //ANY value not zero is true. - printf("%d, ", ii++); // ii++ increments ii in-place - // after yielding its value ("postincrement"). + printf("%d, ", ii++); // ii++ increments ii AFTER using it's current value. } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); @@ -270,8 +269,7 @@ int main() { int kk = 0; do { printf("%d, ", kk); - } while (++kk < 10); // ++kk increments kk in-place, and yields - // the already incremented value ("preincrement") + } while (++kk < 10); // ++kk increments kk BEFORE using it's current value. // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); -- cgit v1.2.3 From 2fab4dc971e3c249dc8be7c365309afb8ab9c209 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 1 Sep 2013 11:10:04 -0500 Subject: Add specific examples of increment and decrement operators to C. --- c.html.markdown | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index c5ac7708..e6179ba6 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -226,6 +226,17 @@ int main() { 0 || 1; // => 1 (Logical or) 0 || 0; // => 0 + //Increment and decrement operators: + int j = 0; + char s[]; + int w = 0; + j++; //difference between postfix and prefix explained below + ++j; // in string example. + j--; + --j; + s[j++]; //returns value of j to s THEN increments value of j. + s[++j]; //increments value of j THEN returns value of j to s. + // Bitwise operators! ~0x0F; // => 0xF0 (bitwise negation, "1's complement") 0x0F & 0xF0; // => 0x00 (bitwise AND) -- cgit v1.2.3 From 0ab144ff976c7a701acef552cc8e33b38faa7dbc Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 1 Sep 2013 11:51:25 -0500 Subject: Add conditinal expression (?:) to C. --- c.html.markdown | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index e6179ba6..ea047ea0 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -226,6 +226,10 @@ int main() { 0 || 1; // => 1 (Logical or) 0 || 0; // => 0 + //Conditional expression ( ?: ) + int a, b, z; + z = (a > b) ? a : b; // z = max(a, b); + //Increment and decrement operators: int j = 0; char s[]; -- cgit v1.2.3 From c4f541dc92ae149947a49a885292d8ad7ead7aa6 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 1 Sep 2013 13:17:26 -0500 Subject: Add order of evaluation table to C. --- c.html.markdown | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ea047ea0..fd0b7964 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -593,6 +593,31 @@ typedef void (*my_fnp_type)(char *); // ... // my_fnp_type f; + +/////////////////////////////////////// +// Order of Evaluation +/////////////////////////////////////// + +//---------------------------------------------------// +// Operators | Associativity // +//---------------------------------------------------// +// () [] -> . | left to right // +// ! ~ ++ -- + = *(type)sizeof | right to left // +// * / % | left to right // +// + - | left to right // +// << >> | left to right // +// < <= > >= | left to right // +// == != | left to right // +// & | left to right // +// ^ | left to right // +// | | left to right // +// && | left to right // +// || | left to right // +// ?: | right to left // +// = += -= *= /= %= &= ^= |= <<= >>= | right to left // +// , | left to right // +//---------------------------------------------------// + ``` ## Further Reading -- cgit v1.2.3 From f6c800dd2aac61c69563a6d51b786928a1d6b329 Mon Sep 17 00:00:00 2001 From: Nathan Hoad Date: Thu, 5 Sep 2013 01:29:59 +1000 Subject: Fixed typo in c.html.markdown --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 3acf1a4d..3ec4aeef 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -294,7 +294,7 @@ int main() { printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); // => Prints "8, 4" on a typical 64-bit system - // To retreive the value at the address a pointer is pointing to, + // To retrievve the value at the address a pointer is pointing to, // put * in front to de-reference it. // Note: yes, it may be confusing that '*' is used for _both_ declaring a // pointer and dereferencing it. -- cgit v1.2.3 From 65d2460cd760812c0a0e7a08771d859f13eac3af Mon Sep 17 00:00:00 2001 From: Nathan Hoad Date: Thu, 5 Sep 2013 07:13:28 +1000 Subject: Fixed typo in c.html.markdown that I introduced --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 3ec4aeef..12f862bc 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -294,7 +294,7 @@ int main() { printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); // => Prints "8, 4" on a typical 64-bit system - // To retrievve the value at the address a pointer is pointing to, + // To retrieve the value at the address a pointer is pointing to, // put * in front to de-reference it. // Note: yes, it may be confusing that '*' is used for _both_ declaring a // pointer and dereferencing it. -- cgit v1.2.3 From 61dcca33407b75cb44ccc042ff213c1be0c2a5c8 Mon Sep 17 00:00:00 2001 From: Adrian Espinosa Date: Wed, 4 Sep 2013 23:32:18 +0200 Subject: Fix long line --- c.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 3acf1a4d..bc7bd37c 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -81,7 +81,8 @@ int main() { // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; - // size_t is an unsiged integer type of at least 2 bytes used to represent the size of an object. + // size_t is an unsiged integer type of at least 2 bytes used to represent + // the size of an object. size_t size = sizeof(a++); // a++ is not evaluated printf("sizeof(a++) = %zu where a = %d\n", size, a); // prints "sizeof(a++) = 4 where a = 1" (on a 32-bit architecture) -- cgit v1.2.3 From f28d33fb187bc834e6e2956117039f9abe3b6d9b Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Thu, 19 Sep 2013 17:10:53 -0500 Subject: Edit wording on in c changes. --- c.html.markdown | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index fd0b7964..89bfbe6d 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -39,7 +39,7 @@ Multi-line comments look like this. They work in C89 as well. //print formatting: "%d" // integer -"%3d" // minimum length of 3 digits for integer (right justifies text) +"%3d" // integer with minimum of length 3 digits (right justifies text) "%s" // string "%f" // float "%ld" // long @@ -51,7 +51,7 @@ Multi-line comments look like this. They work in C89 as well. "%o" // octal "%%" // prints % -// Constants: use #define keyword, no semicolon at end. +// Constants: #define (no semicolon at end) #define DAYS_IN_YEAR = 365 //enumeration constants are also ways to declare constants. @@ -62,7 +62,6 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; #include #include #include -#include // (File names between are headers from the C standard library.) // For your own headers, use double quotes instead of angle brackets: @@ -111,7 +110,7 @@ int main() { unsigned int ux_int; unsigned long long ux_long_long; - // chars inside single quotes '*' are integers in your character set. + // chars inside single quotes are integers in machine's character set. '0' //==> 48 on the ASCII character set. 'A' //==> 65 on the ASCII character set. @@ -226,20 +225,14 @@ int main() { 0 || 1; // => 1 (Logical or) 0 || 0; // => 0 - //Conditional expression ( ?: ) + //Conditional expression ( ? : ) int a, b, z; - z = (a > b) ? a : b; // z = max(a, b); + z = (a > b) ? a : b; // "if a > b return a, else return b." //Increment and decrement operators: - int j = 0; - char s[]; - int w = 0; - j++; //difference between postfix and prefix explained below - ++j; // in string example. - j--; - --j; s[j++]; //returns value of j to s THEN increments value of j. s[++j]; //increments value of j THEN returns value of j to s. + // same with j-- and --j // Bitwise operators! ~0x0F; // => 0xF0 (bitwise negation, "1's complement") @@ -267,12 +260,6 @@ int main() { printf("I print\n"); } - // Notes: - // Loops MUST always have a body. If no body is needed, do this: - for (i = 0; i <= 5; i++) { - ; // use semicolon to act as the body (null statement) - } - // While loops exist int ii = 0; while (ii < 10) { //ANY value not zero is true. @@ -297,6 +284,12 @@ int main() { printf("\n"); + // *****NOTES*****: + // Loops MUST always have a body. If no body is needed, do: + for (i = 0; i <= 5; i++) { + ; // use semicolon to act as the body (null statement) + } + // branching with multiple choices: switch() switch (some_integral_expression) { case 0: // labels need to be integral *constant* epxressions @@ -448,18 +441,20 @@ int add_two_ints(int x1, int x2) return x1 + x2; // Use return to return a value } -// Must declare a 'funtion prototype' before main() when creating functions -// in file. +// Must declare a 'funtion prototype' when creating functions before main() void getInt(char c); // function prototype -int main() { +int main() { // main function return 0; } void getInt(char w) { //parameter name does not need to match function prototype ; } -//if function takes no parameters, do: int getInt(void); for function prototype -// and for the function declaration: int getInt(void) {} -// this is to keep compatibility with older versions of C. + +//if function takes no parameters, do: +int getInt(void); for function prototype +// and for the function declaration: +int getInt(void) {} +// (this is to keep compatibility with older versions of C). /* Functions are call by value. So when a function is called, the arguments passed @@ -485,11 +480,13 @@ void str_reverse(char *str_in) } } +///////////////////////////////////// // Built in functions: +///////////////////////////////////// // from stdio.h: -int c = getchar(); //reads character from input. If input = hi, only h is read. -// getchar() can be stored into int or char. I am using int because -// char is not large enough to store EOF used below. +// getchar() +int c = getchar(); //reads character from input. +// If input = hi, 'h' is returned then next call, 'i' returned. while ((c = getchar()) != EOF) { // EOF constant "end of file". // Linux: CTRL+D, Windows: CTRL+X // must have () around getchar() as != is run before =. -- cgit v1.2.3 From 2ef41199266fefc868dd28c3e0ac5dc55daf9d8f Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 21:53:42 -0500 Subject: Fix typo for 'funtion prototype' --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index fd0b7964..68ef7f03 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -448,7 +448,7 @@ int add_two_ints(int x1, int x2) return x1 + x2; // Use return to return a value } -// Must declare a 'funtion prototype' before main() when creating functions +// Must declare a 'function prototype' before main() when creating functions // in file. void getInt(char c); // function prototype int main() { -- cgit v1.2.3 From 7c559d57a88143b0cbe7b16dbd071f0e07c83b32 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 22:05:08 -0500 Subject: Move special characters to end of file --- c.html.markdown | 61 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 31 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 2a65d82c..9745ed9a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -20,37 +20,6 @@ memory management and C will take you as far as you need to go. Multi-line comments look like this. They work in C89 as well. */ -//Special characters: -'\a' // alert (bell) character -'\n' // newline character -'\t' // tab character (left justifies text) -'\v' // vertical tab -'\f' // new page (formfeed) -'\r' // carriage return -'\b' // backspace character -'\0' // null character. Usually put at end of strings in C lang. - // hello\n\0. \0 used by convention to mark end of string. -'\\' // backspace -'\?' // question mark -'\'' // single quote -'\"' // double quote -'\xhh' // hexadecimal number. Example: '\xb' = vertical tab character -'\ooo' // octal number. Example: '\013' = vertical tab character - -//print formatting: -"%d" // integer -"%3d" // integer with minimum of length 3 digits (right justifies text) -"%s" // string -"%f" // float -"%ld" // long -"%3.2f" // minimum 3 digits left and 2 digits right decimal float -"%7.4s" // (can do with strings too) -"%c" // char -"%p" // pointer -"%x" // hexidecimal -"%o" // octal -"%%" // prints % - // Constants: #define (no semicolon at end) #define DAYS_IN_YEAR = 365 @@ -590,6 +559,36 @@ typedef void (*my_fnp_type)(char *); // ... // my_fnp_type f; +//Special characters: +'\a' // alert (bell) character +'\n' // newline character +'\t' // tab character (left justifies text) +'\v' // vertical tab +'\f' // new page (formfeed) +'\r' // carriage return +'\b' // backspace character +'\0' // null character. Usually put at end of strings in C lang. + // hello\n\0. \0 used by convention to mark end of string. +'\\' // backspace +'\?' // question mark +'\'' // single quote +'\"' // double quote +'\xhh' // hexadecimal number. Example: '\xb' = vertical tab character +'\ooo' // octal number. Example: '\013' = vertical tab character + +//print formatting: +"%d" // integer +"%3d" // integer with minimum of length 3 digits (right justifies text) +"%s" // string +"%f" // float +"%ld" // long +"%3.2f" // minimum 3 digits left and 2 digits right decimal float +"%7.4s" // (can do with strings too) +"%c" // char +"%p" // pointer +"%x" // hexidecimal +"%o" // octal +"%%" // prints % /////////////////////////////////////// // Order of Evaluation -- cgit v1.2.3 From 35909645f2dbfedc38b566ec9838c2202cd51e3c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 22:13:10 -0500 Subject: Edit note on function prototypes. --- c.html.markdown | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 9745ed9a..df6cd036 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -41,6 +41,10 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; void function_1(); void function_2(); +// Must declare a 'function prototype' before main() when functions occur after +// your main() function. +int add_two_ints(int x1, int x2); // function prototype + // Your program's entry point is a function called // main with an integer return type. int main() { @@ -410,15 +414,6 @@ int add_two_ints(int x1, int x2) return x1 + x2; // Use return to return a value } -// Must declare a 'function prototype' before main() when creating functions -void getInt(char c); // function prototype -int main() { // main function - return 0; -} -void getInt(char w) { //parameter name does not need to match function prototype - ; -} - //if function takes no parameters, do: int getInt(void); for function prototype // and for the function declaration: -- cgit v1.2.3 From ec7ee88698bf32bfe6e931865e94d2dac8f41c80 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 22:19:07 -0500 Subject: Add to ? : example in C. --- c.html.markdown | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index df6cd036..f1e328cf 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -199,8 +199,10 @@ int main() { 0 || 0; // => 0 //Conditional expression ( ? : ) - int a, b, z; - z = (a > b) ? a : b; // "if a > b return a, else return b." + int a = 5; + int b = 10; + int z; + z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." //Increment and decrement operators: s[j++]; //returns value of j to s THEN increments value of j. -- cgit v1.2.3 From 868be425a6602020f275404a8776d48f3d6d2715 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 22:31:04 -0500 Subject: Add to notes on increment and decrement operators. --- c.html.markdown | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index f1e328cf..f67f6c4a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -205,8 +205,11 @@ int main() { z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." //Increment and decrement operators: - s[j++]; //returns value of j to s THEN increments value of j. - s[++j]; //increments value of j THEN returns value of j to s. + char *s = "iLoveC" + int j = 0; + s[j++]; // => "i" Returns value of j to s THEN increments value of j. + j = 0; + s[++j]; // => "L" Increments value of j THEN returns value of j to s. // same with j-- and --j // Bitwise operators! -- cgit v1.2.3 From 67cd987efa06141e5dac74f07fa8f561265c835a Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 22:33:19 -0500 Subject: Declare variable before empty for loop. --- c.html.markdown | 1 + 1 file changed, 1 insertion(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index f67f6c4a..d075ea0e 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -264,6 +264,7 @@ int main() { // *****NOTES*****: // Loops MUST always have a body. If no body is needed, do: + int i; for (i = 0; i <= 5; i++) { ; // use semicolon to act as the body (null statement) } -- cgit v1.2.3 From 981cc871a4d4e5473e580dee8574a119ac8a9723 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 20 Sep 2013 22:37:40 -0500 Subject: Edit getchar() notes. --- c.html.markdown | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index d075ea0e..ee35cdd2 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -453,15 +453,14 @@ void str_reverse(char *str_in) ///////////////////////////////////// // Built in functions: ///////////////////////////////////// -// from stdio.h: -// getchar() -int c = getchar(); //reads character from input. +// from: #include +// ** getchar() ** +// int c = getchar(); //reads character from input. // If input = hi, 'h' is returned then next call, 'i' returned. while ((c = getchar()) != EOF) { // EOF constant "end of file". // Linux: CTRL+D, Windows: CTRL+X // must have () around getchar() as != is run before =. putchar(c); //prints character (without newline at end) - char c = getchar(); } //if referring to external variables outside function, must use extern keyword. -- cgit v1.2.3 From 38de481179484d597d44fa934f87a5f21ebfaa6c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sat, 23 Nov 2013 22:40:52 -0600 Subject: Add variety to function prototypes. --- c.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ee35cdd2..b4a874d3 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -38,8 +38,8 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // Declare function signatures in advance in a .h file, or at the top of // your .c file. -void function_1(); -void function_2(); +void function_1(char s[]); +int function_2(void); // Must declare a 'function prototype' before main() when functions occur after // your main() function. -- cgit v1.2.3 From e63232d2de1e2058dd381fe1094c7f775f2e3eb8 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 24 Nov 2013 14:17:32 -0600 Subject: Add static description to C. --- c.html.markdown | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index b4a874d3..7b95c969 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -469,6 +469,13 @@ void testFunc() { extern int i; //i here is now using external variable i } +//if external variable should only be visible to functions in the source file +// they are declared in, use static: +static int i = 0; //other source files using testFunc() cannot access variable i +void testFunc() { + extern int i; +} + /* char c[] = "This is a test."; str_reverse(c); -- cgit v1.2.3 From af9cc6e9b9748e43cb1c02013fe92465c3455503 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 24 Nov 2013 14:25:30 -0600 Subject: Edit static description wording. Add note about private functions. --- c.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 7b95c969..ab09a4a2 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -469,12 +469,12 @@ void testFunc() { extern int i; //i here is now using external variable i } -//if external variable should only be visible to functions in the source file -// they are declared in, use static: -static int i = 0; //other source files using testFunc() cannot access variable i +//make external variables private to source file with static: +static int i = 0; //other files using testFunc() cannot access variable i void testFunc() { extern int i; } +//**You may also declare functions as static to make them private** /* char c[] = "This is a test."; -- cgit v1.2.3 From bb4f644a19a086c3c6b32891a7240cc140b379f4 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 24 Nov 2013 15:01:24 -0600 Subject: Fix #define as it does not use = sign. --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ab09a4a2..d8eccd78 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -21,7 +21,7 @@ Multi-line comments look like this. They work in C89 as well. */ // Constants: #define (no semicolon at end) -#define DAYS_IN_YEAR = 365 +#define DAYS_IN_YEAR 365 //enumeration constants are also ways to declare constants. enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; -- cgit v1.2.3 From 5c7f6d70b9477fcd4fe64460704d7dcf48799f98 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 24 Nov 2013 16:58:21 -0600 Subject: Remove bad description of function prototypes. --- c.html.markdown | 6 ------ 1 file changed, 6 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index d8eccd78..d029a00f 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -420,12 +420,6 @@ int add_two_ints(int x1, int x2) return x1 + x2; // Use return to return a value } -//if function takes no parameters, do: -int getInt(void); for function prototype -// and for the function declaration: -int getInt(void) {} -// (this is to keep compatibility with older versions of C). - /* Functions are call by value. So when a function is called, the arguments passed to the function are copies of original arguments (except arrays). Anything you -- cgit v1.2.3 From 67a5236629b6c7748b609f23c0362925b5c4774d Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Sun, 24 Nov 2013 23:26:11 -0600 Subject: Add multi-dimensional array description. --- c.html.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index d029a00f..f4edfca5 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -148,6 +148,14 @@ int main() { int cha = 'a'; // fine char chb = 'a'; // fine too (implicit conversion from int to char) + //Multi-dimensional arrays: + int multi_array[2][5] = { + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 0} + } + //access elements: + int array_int = multi_array[0][2]; //=> 3 + /////////////////////////////////////// // Operators /////////////////////////////////////// -- cgit v1.2.3 From df3cc00f5233dac96c0e063d87d3552f493e25f6 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Mon, 25 Nov 2013 09:21:40 -0600 Subject: Remove bad examples, reword places. --- c.html.markdown | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index f4edfca5..4187d757 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -20,7 +20,7 @@ memory management and C will take you as far as you need to go. Multi-line comments look like this. They work in C89 as well. */ -// Constants: #define (no semicolon at end) +// Constants: #define #define DAYS_IN_YEAR 365 //enumeration constants are also ways to declare constants. @@ -38,7 +38,7 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // Declare function signatures in advance in a .h file, or at the top of // your .c file. -void function_1(char s[]); +void function_1(char c); int function_2(void); // Must declare a 'function prototype' before main() when functions occur after @@ -84,8 +84,8 @@ int main() { unsigned long long ux_long_long; // chars inside single quotes are integers in machine's character set. - '0' //==> 48 on the ASCII character set. - 'A' //==> 65 on the ASCII character set. + '0' // => 48 in the ASCII character set. + 'A' // => 65 in the ASCII character set. // sizeof(T) gives you the size of a variable with type T in bytes // sizeof(obj) yields the size of the expression (variable, literal, etc.). @@ -154,16 +154,16 @@ int main() { {6, 7, 8, 9, 0} } //access elements: - int array_int = multi_array[0][2]; //=> 3 + int array_int = multi_array[0][2]; // => 3 /////////////////////////////////////// // Operators /////////////////////////////////////// - int i1 = 1, i2 = 2; // Shorthand for multiple declaration + // Shorthands for multiple declarations: + int i1 = 1, i2 = 2; float f1 = 1.0, f2 = 2.0; - //more shorthands: int a, b, c; a = b = c = 0; @@ -215,9 +215,9 @@ int main() { //Increment and decrement operators: char *s = "iLoveC" int j = 0; - s[j++]; // => "i" Returns value of j to s THEN increments value of j. + s[j++]; // => "i". Returns the j-th item of s THEN increments value of j. j = 0; - s[++j]; // => "L" Increments value of j THEN returns value of j to s. + s[++j]; // => "L". Increments value of j THEN returns j-th value of s. // same with j-- and --j // Bitwise operators! @@ -271,7 +271,7 @@ int main() { printf("\n"); // *****NOTES*****: - // Loops MUST always have a body. If no body is needed, do: + // Loops and Functions MUST have a body. If no body is needed: int i; for (i = 0; i <= 5; i++) { ; // use semicolon to act as the body (null statement) @@ -429,12 +429,12 @@ int add_two_ints(int x1, int x2) } /* -Functions are call by value. So when a function is called, the arguments passed -to the function are copies of original arguments (except arrays). Anything you -do to your arguments do not change the value of the actual argument where the -function was called. +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 +do to the arguments in the function do not change the value of the original +argument where the function was called. -You can use pointers if you need to edit the original argument values. +Use pointers if you need to edit the original argument values. Example: in-place string reversal */ @@ -452,19 +452,6 @@ void str_reverse(char *str_in) } } -///////////////////////////////////// -// Built in functions: -///////////////////////////////////// -// from: #include -// ** getchar() ** -// int c = getchar(); //reads character from input. -// If input = hi, 'h' is returned then next call, 'i' returned. -while ((c = getchar()) != EOF) { // EOF constant "end of file". - // Linux: CTRL+D, Windows: CTRL+X - // must have () around getchar() as != is run before =. - putchar(c); //prints character (without newline at end) -} - //if referring to external variables outside function, must use extern keyword. int i = 0; void testFunc() { -- cgit v1.2.3 From c8b12bd824659879038d5d752b13d5c91fad8303 Mon Sep 17 00:00:00 2001 From: Joseph Adams Date: Fri, 10 Jan 2014 18:14:35 +0100 Subject: Added verb ("is") where it was missing --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 84856b32..99ff0d27 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -92,7 +92,7 @@ int main() { printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) - // If the argument of the `sizeof` operator an expression, then its argument + // If the argument of the `sizeof` operator is an expression, then its argument // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; -- cgit v1.2.3 From c9a32b08e72a4c219a549497e24675e700870f26 Mon Sep 17 00:00:00 2001 From: Joseph Adams Date: Fri, 10 Jan 2014 18:28:34 +0100 Subject: Added missing comma in printf --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 99ff0d27..e55ff148 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -376,7 +376,7 @@ int main() { // or when it's the argument of the `sizeof` or `alignof` operator: int arr[10]; int *ptr = arr; // equivalent with int *ptr = &arr[0]; - printf("%zu %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" + printf("%zu, %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" // Pointers are incremented and decremented based on their type -- cgit v1.2.3 From 4c25ac36c669ef0c65938d329a7d3baff6a756dd Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Fri, 14 Feb 2014 17:22:38 +0800 Subject: c: reorder paragraphs content about `static` are inserted into the wrong place. --- c.html.markdown | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index e55ff148..d7c682ad 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -454,6 +454,12 @@ void str_reverse(char *str_in) } } +/* +char c[] = "This is a test."; +str_reverse(c); +printf("%s\n", c); // => ".tset a si sihT" +*/ + //if referring to external variables outside function, must use extern keyword. int i = 0; void testFunc() { @@ -467,11 +473,7 @@ void testFunc() { } //**You may also declare functions as static to make them private** -/* -char c[] = "This is a test."; -str_reverse(c); -printf("%s\n", c); // => ".tset a si sihT" -*/ + /////////////////////////////////////// // User-defined types and structs -- cgit v1.2.3 From 2a9fb70f6d62e1cf3a0bc08fa6dc89bb53310624 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Fri, 14 Feb 2014 20:34:23 +0800 Subject: c: typo --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index d7c682ad..0190125b 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -569,7 +569,7 @@ typedef void (*my_fnp_type)(char *); '\b' // backspace character '\0' // null character. Usually put at end of strings in C lang. // hello\n\0. \0 used by convention to mark end of string. -'\\' // backspace +'\\' // backslash '\?' // question mark '\'' // single quote '\"' // double quote -- cgit v1.2.3 From e8910da685f1195dc597b428dddb05925fb54c23 Mon Sep 17 00:00:00 2001 From: Nattaphoom Ch Date: Wed, 28 May 2014 01:06:24 +0700 Subject: Added missing semicolons and correct some words. --- c.html.markdown | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 0190125b..c89f2b88 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -154,7 +154,7 @@ int main() { int multi_array[2][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 0} - } + }; //access elements: int array_int = multi_array[0][2]; // => 3 @@ -215,7 +215,7 @@ int main() { z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." //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; @@ -251,7 +251,7 @@ int main() { // While loops exist int ii = 0; while (ii < 10) { //ANY value not zero is true. - printf("%d, ", ii++); // ii++ increments ii AFTER using it's current value. + printf("%d, ", ii++); // ii++ increments ii AFTER using its current value. } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); @@ -259,7 +259,7 @@ int main() { int kk = 0; do { printf("%d, ", kk); - } while (++kk < 10); // ++kk increments kk BEFORE using it's current value. + } while (++kk < 10); // ++kk increments kk BEFORE using its current value. // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); @@ -367,7 +367,7 @@ int main() { // This works because arrays often decay into pointers to their first element. // For example, when an array is passed to a function or is assigned to a pointer, // it decays into (implicitly converted to) a pointer. - // Exceptions: when the array is the argument of the `&` (address-od) operator: + // Exceptions: when the array is the argument of the `&` (address-of) operator: int arr[10]; int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! // It's of type "pointer to array" (of ten `int`s). @@ -387,7 +387,7 @@ int main() { // You can also dynamically allocate contiguous blocks of memory with the // standard library function malloc, which takes one argument of type size_t // representing the number of bytes to allocate (usually from the heap, although this - // may not be true on e. g. embedded systems - the C standard says nothing about it). + // may not be true on e.g. embedded systems - the C standard says nothing about it). int *my_ptr = malloc(sizeof(*my_ptr) * 20); for (xx = 0; xx < 20; xx++) { *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx @@ -405,7 +405,7 @@ int main() { // Strings are arrays of char, but they are usually represented as a // pointer-to-char (which is a pointer to the first element of the array). // It's good practice to use `const char *' when referring to a string literal, - // since string literals shall not be modified (i. e. "foo"[0] = 'a' is ILLEGAL.) + // since string literals shall not be modified (i.e. "foo"[0] = 'a' is ILLEGAL.) const char *my_str = "This is my very own string literal"; printf("%c\n", *my_str); // => 'T' -- cgit v1.2.3 From 104b9add58ff808ac26dad9b315e00f6e9ac9bd2 Mon Sep 17 00:00:00 2001 From: Nick Ward Date: Sat, 28 Jun 2014 11:53:25 +1000 Subject: Fix spelling and other small issues --- c.html.markdown | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index c89f2b88..22f251f2 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -23,7 +23,7 @@ Multi-line comments look like this. They work in C89 as well. // Constants: #define #define DAYS_IN_YEAR 365 -//enumeration constants are also ways to declare constants. +// Enumeration constants are also ways to declare constants. enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // MON gets 2 automatically, TUE gets 3, etc. @@ -96,7 +96,7 @@ int main() { // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; - // size_t is an unsiged integer type of at least 2 bytes used to represent + // size_t is an unsigned integer type of at least 2 bytes used to represent // the size of an object. size_t size = sizeof(a++); // a++ is not evaluated printf("sizeof(a++) = %zu where a = %d\n", size, a); @@ -135,9 +135,9 @@ int main() { // > Enter the array size: 10 // > sizeof array = 40 - // Strings are just arrays of chars terminated by a NUL (0x00) byte, + // Strings are just arrays of chars terminated by a NULL (0x00) byte, // represented in strings as the special character '\0'. - // (We don't have to include the NUL byte in string literals; the compiler + // (We don't have to include the NULL byte in string literals; the compiler // inserts it at the end of the array for us.) char a_string[20] = "This is a string"; printf("%s\n", a_string); // %s formats a string @@ -182,7 +182,7 @@ int main() { 11 % 3; // => 2 // Comparison operators are probably familiar, but - // there is no boolean type in c. We use ints instead. + // there is no Boolean type in c. We use ints instead. // (Or _Bool or bool in C99.) // 0 is false, anything else is true. (The comparison // operators always yield 0 or 1.) @@ -281,7 +281,7 @@ int main() { // branching with multiple choices: switch() switch (some_integral_expression) { - case 0: // labels need to be integral *constant* epxressions + case 0: // labels need to be integral *constant* expressions do_stuff(); break; // if you don't break, control flow falls over labels case 1: @@ -312,7 +312,7 @@ int main() { // Types will overflow without warning printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) - // For determining the max value of a `char`, a `signed char` and an `unisigned char`, + // For determining the max value of a `char`, a `signed char` and an `unsigned char`, // respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from // Integral types can be cast to floating-point types, and vice-versa. @@ -342,13 +342,13 @@ int main() { // => Prints "8, 4" on a typical 64-bit system // To retrieve the value at the address a pointer is pointing to, - // put * in front to de-reference it. + // put * in front to dereference it. // Note: yes, it may be confusing that '*' is used for _both_ declaring a // pointer and dereferencing it. printf("%d\n", *px); // => Prints 0, the value of x // You can also change the value the pointer is pointing to. - // We'll have to wrap the de-reference in parenthesis because + // We'll have to wrap the dereference in parenthesis because // ++ has a higher precedence than *. (*px)++; // Increment the value px is pointing to by 1 printf("%d\n", *px); // => Prints 1 @@ -532,7 +532,7 @@ int area(const rect *r) // Function pointers /////////////////////////////////////// /* -At runtime, functions are located at known memory addresses. Function pointers are +At run time, functions are located at known memory addresses. Function pointers are much like any other pointer (they just store a memory address), but can be used to invoke functions directly, and to pass handlers (or callback functions) around. However, definition syntax may be initially confusing. @@ -542,7 +542,7 @@ Example: use str_reverse from a pointer void str_reverse_through_pointer(char *str_in) { // Define a function pointer variable, named f. void (*f)(char *); // Signature should exactly match the target function. - f = &str_reverse; // Assign the address for the actual function (determined at runtime) + f = &str_reverse; // Assign the address for the actual function (determined at run time) // f = str_reverse; would work as well - functions decay into pointers, similar to arrays (*f)(str_in); // Just calling the function through the pointer // f(str_in); // That's an alternative but equally valid syntax for calling it. @@ -564,10 +564,10 @@ typedef void (*my_fnp_type)(char *); '\n' // newline character '\t' // tab character (left justifies text) '\v' // vertical tab -'\f' // new page (formfeed) +'\f' // new page (form feed) '\r' // carriage return '\b' // backspace character -'\0' // null character. Usually put at end of strings in C lang. +'\0' // NULL character. Usually put at end of strings in C. // hello\n\0. \0 used by convention to mark end of string. '\\' // backslash '\?' // question mark @@ -586,7 +586,7 @@ typedef void (*my_fnp_type)(char *); "%7.4s" // (can do with strings too) "%c" // char "%p" // pointer -"%x" // hexidecimal +"%x" // hexadecimal "%o" // octal "%%" // prints % @@ -628,7 +628,7 @@ If you have a question, read the [compl.lang.c Frequently Asked Questions](http: It's very important to use proper spacing, indentation and to be consistent with your coding style in general. Readable code is better than clever code and fast code. For a good, sane coding style to adopt, see the -[Linux kernel coding stlye](https://www.kernel.org/doc/Documentation/CodingStyle). +[Linux kernel coding style](https://www.kernel.org/doc/Documentation/CodingStyle). Other than that, Google is your friend. -- cgit v1.2.3 From 15353d1938999fe419b4b46295dd4eec92191835 Mon Sep 17 00:00:00 2001 From: Nami-Doc Date: Thu, 17 Jul 2014 10:46:24 +0200 Subject: Fix c tutorial Fixes #678 Still missing symbols, though --- c.html.markdown | 834 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 417 insertions(+), 417 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 22f251f2..bc9a959a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -16,15 +16,15 @@ memory management and C will take you as far as you need to go. ```c // Single-line comments start with // - only available in C99 and later. -/* + /* Multi-line comments look like this. They work in C89 as well. -*/ + */ -// Constants: #define + // Constants: #define #define DAYS_IN_YEAR 365 -// Enumeration constants are also ways to declare constants. -enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; + // Enumeration constants are also ways to declare constants. + enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // MON gets 2 automatically, TUE gets 3, etc. // Import headers with #include @@ -34,11 +34,11 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // (File names between are headers from the C standard library.) // For your own headers, use double quotes instead of angle brackets: -#include "my_header.h" +//#include "my_header.h" // Declare function signatures in advance in a .h file, or at the top of // your .c file. -void function_1(char c); +void function_1(); int function_2(void); // Must declare a 'function prototype' before main() when functions occur after @@ -48,374 +48,373 @@ int add_two_ints(int x1, int x2); // function prototype // Your program's entry point is a function called // main with an integer return type. int main() { - // print output using printf, for "print formatted" - // %d is an integer, \n is a newline - printf("%d\n", 0); // => Prints 0 - // All statements must end with a semicolon - - /////////////////////////////////////// - // Types - /////////////////////////////////////// - - // ints are usually 4 bytes - int x_int = 0; - - // shorts are usually 2 bytes - short x_short = 0; - - // chars are guaranteed to be 1 byte - char x_char = 0; - 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 - long x_long = 0; - long long x_long_long = 0; - - // floats are usually 32-bit floating point numbers - float x_float = 0.0; - - // doubles are usually 64-bit floating-point numbers - double x_double = 0.0; - - // Integral types may be unsigned. - unsigned short ux_short; - unsigned int ux_int; - unsigned long long ux_long_long; - - // chars inside single quotes are integers in machine's character set. - '0' // => 48 in the ASCII character set. - 'A' // => 65 in the ASCII character set. - - // sizeof(T) gives you the size of a variable with type T in bytes - // sizeof(obj) yields the size of the expression (variable, literal, etc.). - printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) - - - // If the argument of the `sizeof` operator is an expression, then its argument - // is not evaluated (except VLAs (see below)). - // The value it yields in this case is a compile-time constant. - int a = 1; - // size_t is an unsigned integer type of at least 2 bytes used to represent - // the size of an object. - size_t size = sizeof(a++); // a++ is not evaluated - printf("sizeof(a++) = %zu where a = %d\n", size, a); - // prints "sizeof(a++) = 4 where a = 1" (on a 32-bit architecture) - - // Arrays must be initialized with a concrete size. - char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes - int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes - // (assuming 4-byte words) - - - // You can initialize an array to 0 thusly: - char my_array[20] = {0}; - - // Indexing an array is like other languages -- or, - // rather, other languages are like C - my_array[0]; // => 0 - - // Arrays are mutable; it's just memory! - my_array[1] = 2; - printf("%d\n", my_array[1]); // => 2 - - // In C99 (and as an optional feature in C11), variable-length arrays (VLAs) - // can be declared as well. The size of such an array need not be a compile - // time constant: - printf("Enter the array size: "); // ask the user for an array size - char buf[0x100]; - fgets(buf, sizeof buf, stdin); - - // strtoul parses a string to an unsigned integer - size_t size = strtoul(buf, NULL, 10); - 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: - // > Enter the array size: 10 - // > sizeof array = 40 - - // Strings are just arrays of chars terminated by a NULL (0x00) byte, - // represented in strings as the special character '\0'. - // (We don't have to include the NULL byte in string literals; the compiler - // inserts it at the end of the array for us.) - char a_string[20] = "This is a string"; - printf("%s\n", a_string); // %s formats a string - - printf("%d\n", a_string[16]); // => 0 - // i.e., byte #17 is 0 (as are 18, 19, and 20) - - // If we have characters between single quotes, that's a character literal. - // It's of type `int`, and *not* `char` (for historical reasons). - int cha = 'a'; // fine - char chb = 'a'; // fine too (implicit conversion from int to char) - - //Multi-dimensional arrays: - int multi_array[2][5] = { - {1, 2, 3, 4, 5}, - {6, 7, 8, 9, 0} - }; - //access elements: - int array_int = multi_array[0][2]; // => 3 - - /////////////////////////////////////// - // Operators - /////////////////////////////////////// - - // Shorthands for multiple declarations: - int i1 = 1, i2 = 2; - float f1 = 1.0, f2 = 2.0; - - int a, b, c; - a = b = c = 0; - - // Arithmetic is straightforward - i1 + i2; // => 3 - i2 - i1; // => 1 - i2 * i1; // => 2 - i1 / i2; // => 0 (0.5, but truncated towards 0) - - f1 / f2; // => 0.5, plus or minus epsilon - // Floating-point numbers and calculations are not exact - - // Modulo is there as well - 11 % 3; // => 2 - - // Comparison operators are probably familiar, but - // there is no Boolean type in c. We use ints instead. - // (Or _Bool or bool in C99.) - // 0 is false, anything else is true. (The comparison - // operators always yield 0 or 1.) - 3 == 2; // => 0 (false) - 3 != 2; // => 1 (true) - 3 > 2; // => 1 - 3 < 2; // => 0 - 2 <= 2; // => 1 - 2 >= 2; // => 1 - - // C is not Python - comparisons don't chain. - int a = 1; - // WRONG: - int between_0_and_2 = 0 < a < 2; - // Correct: - int between_0_and_2 = 0 < a && a < 2; - - // Logic works on ints - !3; // => 0 (Logical not) - !0; // => 1 - 1 && 1; // => 1 (Logical and) - 0 && 1; // => 0 - 0 || 1; // => 1 (Logical or) - 0 || 0; // => 0 - - //Conditional expression ( ? : ) - int a = 5; - int b = 10; - int z; - z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." - - //Increment and decrement operators: - char *s = "iLoveC"; - int j = 0; - s[j++]; // => "i". Returns the j-th item of s THEN increments value of j. - j = 0; - s[++j]; // => "L". Increments value of j THEN returns j-th value of s. - // same with j-- and --j - - // Bitwise operators! - ~0x0F; // => 0xF0 (bitwise negation, "1's complement") - 0x0F & 0xF0; // => 0x00 (bitwise AND) - 0x0F | 0xF0; // => 0xFF (bitwise OR) - 0x04 ^ 0x0F; // => 0x0B (bitwise XOR) - 0x01 << 1; // => 0x02 (bitwise left shift (by 1)) - 0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) - - // Be careful when shifting signed integers - the following are undefined: - // - shifting into the sign bit of a signed integer (int a = 1 << 32) - // - left-shifting a negative number (int a = -1 << 2) - // - shifting by an offset which is >= the width of the type of the LHS: - // int a = 1 << 32; // UB if int is 32 bits wide - - /////////////////////////////////////// - // Control Structures - /////////////////////////////////////// - - if (0) { - printf("I am never run\n"); - } else if (0) { - printf("I am also never run\n"); - } else { - printf("I print\n"); - } - - // While loops exist - int ii = 0; - while (ii < 10) { //ANY value not zero is true. - printf("%d, ", ii++); // ii++ increments ii AFTER using its current value. - } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - - printf("\n"); - - int kk = 0; - do { - printf("%d, ", kk); - } while (++kk < 10); // ++kk increments kk BEFORE using its current value. - // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - - printf("\n"); - - // For loops too - int jj; - for (jj=0; jj < 10; jj++) { - printf("%d, ", jj); - } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - - printf("\n"); - - // *****NOTES*****: - // Loops and Functions MUST have a body. If no body is needed: - int i; - for (i = 0; i <= 5; i++) { - ; // use semicolon to act as the body (null statement) - } - - // branching with multiple choices: switch() - switch (some_integral_expression) { - case 0: // labels need to be integral *constant* expressions - do_stuff(); - break; // if you don't break, control flow falls over labels - case 1: - do_something_else(); - break; - default: - // if `some_integral_expression` didn't match any of the labels - fputs("error!\n", stderr); - exit(-1); - break; - } + // print output using printf, for "print formatted" + // %d is an integer, \n is a newline + printf("%d\n", 0); // => Prints 0 + // All statements must end with a semicolon + + /////////////////////////////////////// + // Types + /////////////////////////////////////// + + // ints are usually 4 bytes + int x_int = 0; + + // shorts are usually 2 bytes + short x_short = 0; + + // chars are guaranteed to be 1 byte + char x_char = 0; + 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 + long x_long = 0; + long long x_long_long = 0; + + // floats are usually 32-bit floating point numbers + float x_float = 0.0; + + // doubles are usually 64-bit floating-point numbers + double x_double = 0.0; + + // Integral types may be unsigned. + unsigned short ux_short; + unsigned int ux_int; + unsigned long long ux_long_long; + + // chars inside single quotes are integers in machine's character set. + '0'; // => 48 in the ASCII character set. + 'A'; // => 65 in the ASCII character set. + + // sizeof(T) gives you the size of a variable with type T in bytes + // sizeof(obj) yields the size of the expression (variable, literal, etc.). + printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) + + + // If the argument of the `sizeof` operator is an expression, then its argument + // is not evaluated (except VLAs (see below)). + // The value it yields in this case is a compile-time constant. + int a = 1; + // size_t is an unsigned integer type of at least 2 bytes used to represent + // the size of an object. + size_t size = sizeof(a++); // a++ is not evaluated + printf("sizeof(a++) = %zu where a = %d\n", size, a); + // prints "sizeof(a++) = 4 where a = 1" (on a 32-bit architecture) + + // Arrays must be initialized with a concrete size. + char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes + int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes + // (assuming 4-byte words) + + + // You can initialize an array to 0 thusly: + char my_array[20] = {0}; + + // Indexing an array is like other languages -- or, + // rather, other languages are like C + my_array[0]; // => 0 + + // Arrays are mutable; it's just memory! + my_array[1] = 2; + printf("%d\n", my_array[1]); // => 2 + + // In C99 (and as an optional feature in C11), variable-length arrays (VLAs) + // can be declared as well. The size of such an array need not be a compile + // time constant: + printf("Enter the array size: "); // ask the user for an array size + char buf[0x100]; + 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 + printf("sizeof array = %zu\n", sizeof var_length_array); + + // A possible outcome of this program may be: + // > Enter the array size: 10 + // > sizeof array = 40 + + // Strings are just arrays of chars terminated by a NULL (0x00) byte, + // represented in strings as the special character '\0'. + // (We don't have to include the NULL byte in string literals; the compiler + // inserts it at the end of the array for us.) + char a_string[20] = "This is a string"; + printf("%s\n", a_string); // %s formats a string + + printf("%d\n", a_string[16]); // => 0 + // i.e., byte #17 is 0 (as are 18, 19, and 20) + + // If we have characters between single quotes, that's a character literal. + // It's of type `int`, and *not* `char` (for historical reasons). + int cha = 'a'; // fine + char chb = 'a'; // fine too (implicit conversion from int to char) + + //Multi-dimensional arrays: + int multi_array[2][5] = { + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 0} + }; + //access elements: + int array_int = multi_array[0][2]; // => 3 + + /////////////////////////////////////// + // Operators + /////////////////////////////////////// + + // Shorthands for multiple declarations: + int i1 = 1, i2 = 2; + float f1 = 1.0, f2 = 2.0; + + int b, c; + b = c = 0; + + // Arithmetic is straightforward + i1 + i2; // => 3 + i2 - i1; // => 1 + i2 * i1; // => 2 + i1 / i2; // => 0 (0.5, but truncated towards 0) + + f1 / f2; // => 0.5, plus or minus epsilon + // Floating-point numbers and calculations are not exact + + // Modulo is there as well + 11 % 3; // => 2 + + // Comparison operators are probably familiar, but + // there is no Boolean type in c. We use ints instead. + // (Or _Bool or bool in C99.) + // 0 is false, anything else is true. (The comparison + // operators always yield 0 or 1.) + 3 == 2; // => 0 (false) + 3 != 2; // => 1 (true) + 3 > 2; // => 1 + 3 < 2; // => 0 + 2 <= 2; // => 1 + 2 >= 2; // => 1 + + // C is not Python - comparisons don't chain. + // WRONG: + //int between_0_and_2 = 0 < a < 2; + // Correct: + int between_0_and_2 = 0 < a && a < 2; + + // Logic works on ints + !3; // => 0 (Logical not) + !0; // => 1 + 1 && 1; // => 1 (Logical and) + 0 && 1; // => 0 + 0 || 1; // => 1 (Logical or) + 0 || 0; // => 0 + + //Conditional expression ( ? : ) + int e = 5; + int f = 10; + int z; + z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." + + //Increment and decrement operators: + char *s = "iLoveC"; + int j = 0; + s[j++]; // => "i". Returns the j-th item of s THEN increments value of j. + j = 0; + s[++j]; // => "L". Increments value of j THEN returns j-th value of s. + // same with j-- and --j + + // Bitwise operators! + ~0x0F; // => 0xF0 (bitwise negation, "1's complement") + 0x0F & 0xF0; // => 0x00 (bitwise AND) + 0x0F | 0xF0; // => 0xFF (bitwise OR) + 0x04 ^ 0x0F; // => 0x0B (bitwise XOR) + 0x01 << 1; // => 0x02 (bitwise left shift (by 1)) + 0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) + + // Be careful when shifting signed integers - the following are undefined: + // - shifting into the sign bit of a signed integer (int a = 1 << 32) + // - left-shifting a negative number (int a = -1 << 2) + // - shifting by an offset which is >= the width of the type of the LHS: + // int a = 1 << 32; // UB if int is 32 bits wide + + /////////////////////////////////////// + // Control Structures + /////////////////////////////////////// + + if (0) { + printf("I am never run\n"); + } else if (0) { + printf("I am also never run\n"); + } else { + printf("I print\n"); + } + + // While loops exist + int ii = 0; + while (ii < 10) { //ANY value not zero is true. + printf("%d, ", ii++); // ii++ increments ii AFTER using its current value. + } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + int kk = 0; + do { + printf("%d, ", kk); + } while (++kk < 10); // ++kk increments kk BEFORE using its current value. + // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // For loops too + int jj; + for (jj=0; jj < 10; jj++) { + printf("%d, ", jj); + } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // *****NOTES*****: + // Loops and Functions MUST have a body. If no body is needed: + int i; + for (i = 0; i <= 5; i++) { + ; // use semicolon to act as the body (null statement) + } + + // branching with multiple choices: switch() + switch (a) { + case 0: // labels need to be integral *constant* expressions + do_stuff(); + break; // if you don't break, control flow falls over labels + case 1: + do_something_else(); + break; + default: + // if `some_integral_expression` didn't match any of the labels + fputs("error!\n", stderr); + exit(-1); + break; + } - /////////////////////////////////////// - // Typecasting - /////////////////////////////////////// + /////////////////////////////////////// + // Typecasting + /////////////////////////////////////// - // Every value in C has a type, but you can cast one value into another type - // if you want (with some constraints). + // Every value in C has a type, but you can cast one value into another type + // if you want (with some constraints). - int x_hex = 0x01; // You can assign vars with hex literals + int x_hex = 0x01; // You can assign vars with hex literals - // Casting between types will attempt to preserve their numeric values - printf("%d\n", x_hex); // => Prints 1 - printf("%d\n", (short) x_hex); // => Prints 1 - printf("%d\n", (char) x_hex); // => Prints 1 + // Casting between types will attempt to preserve their numeric values + printf("%d\n", x_hex); // => Prints 1 + printf("%d\n", (short) x_hex); // => Prints 1 + printf("%d\n", (char) x_hex); // => Prints 1 - // Types will overflow without warning - printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) + // Types will overflow without warning + printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) - // For determining the max value of a `char`, a `signed char` and an `unsigned char`, - // respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from + // For determining the max value of a `char`, a `signed char` and an `unsigned char`, + // respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from - // Integral types can be cast to floating-point types, and vice-versa. - printf("%f\n", (float)100); // %f formats a float - printf("%lf\n", (double)100); // %lf formats a double - printf("%d\n", (char)100.0); + // Integral types can be cast to floating-point types, and vice-versa. + printf("%f\n", (float)100); // %f formats a float + printf("%lf\n", (double)100); // %lf formats a double + printf("%d\n", (char)100.0); - /////////////////////////////////////// - // Pointers - /////////////////////////////////////// + /////////////////////////////////////// + // Pointers + /////////////////////////////////////// - // A pointer is a variable declared to store a memory address. Its declaration will - // also tell you the type of data it points to. You can retrieve the memory address - // of your variables, then mess with them. + // A pointer is a variable declared to store a memory address. Its declaration will + // also tell you the type of data it points to. You can retrieve the memory address + // of your variables, then mess with them. - int x = 0; - printf("%p\n", (void *)&x); // Use & to retrieve the address of a variable - // (%p formats an object pointer of type void *) - // => Prints some address in memory; + int x = 0; + printf("%p\n", (void *)&x); // Use & to retrieve the address of a variable + // (%p formats an object pointer of type void *) + // => Prints some address in memory; - // Pointers start with * in their declaration - int *px, not_a_pointer; // px is a pointer to an int - px = &x; // Stores the address of x in px - printf("%p\n", (void *)px); // => Prints some address in memory - printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); - // => Prints "8, 4" on a typical 64-bit system + // Pointers start with * in their declaration + int *px, not_a_pointer; // px is a pointer to an int + px = &x; // Stores the address of x in px + printf("%p\n", (void *)px); // => Prints some address in memory + printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); + // => Prints "8, 4" on a typical 64-bit system - // To retrieve the value at the address a pointer is pointing to, - // put * in front to dereference it. - // Note: yes, it may be confusing that '*' is used for _both_ declaring a - // pointer and dereferencing it. - printf("%d\n", *px); // => Prints 0, the value of x + // To retrieve the value at the address a pointer is pointing to, + // put * in front to dereference it. + // Note: yes, it may be confusing that '*' is used for _both_ declaring a + // pointer and dereferencing it. + printf("%d\n", *px); // => Prints 0, the value of x - // You can also change the value the pointer is pointing to. - // We'll have to wrap the dereference in parenthesis because - // ++ has a higher precedence than *. - (*px)++; // Increment the value px is pointing to by 1 - printf("%d\n", *px); // => Prints 1 - printf("%d\n", x); // => Prints 1 + // You can also change the value the pointer is pointing to. + // We'll have to wrap the dereference in parenthesis because + // ++ has a higher precedence than *. + (*px)++; // Increment the value px is pointing to by 1 + printf("%d\n", *px); // => Prints 1 + printf("%d\n", x); // => Prints 1 - // Arrays are a good way to allocate a contiguous block of memory - int x_array[20]; //declares array of size 20 (cannot change size) - int xx; - for (xx = 0; xx < 20; xx++) { - x_array[xx] = 20 - xx; - } // Initialize x_array to 20, 19, 18,... 2, 1 + // Arrays are a good way to allocate a contiguous block of memory + int x_array[20]; //declares array of size 20 (cannot change size) + int xx; + for (xx = 0; xx < 20; xx++) { + x_array[xx] = 20 - xx; + } // Initialize x_array to 20, 19, 18,... 2, 1 // Declare a pointer of type int and initialize it to point to x_array - int* x_ptr = x_array; - // x_ptr now points to the first element in the array (the integer 20). - // This works because arrays often decay into pointers to their first element. - // For example, when an array is passed to a function or is assigned to a pointer, - // it decays into (implicitly converted to) a pointer. - // Exceptions: when the array is the argument of the `&` (address-of) operator: - int arr[10]; - int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! - // It's of type "pointer to array" (of ten `int`s). - // or when the array is a string literal used for initializing a char array: - char arr[] = "foobarbazquirk"; - // or when it's the argument of the `sizeof` or `alignof` operator: - int arr[10]; - int *ptr = arr; // equivalent with int *ptr = &arr[0]; - printf("%zu, %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" - - - // Pointers are incremented and decremented based on their type - // (this is called pointer arithmetic) - printf("%d\n", *(x_ptr + 1)); // => Prints 19 - printf("%d\n", x_array[1]); // => Prints 19 - - // You can also dynamically allocate contiguous blocks of memory with the - // standard library function malloc, which takes one argument of type size_t - // representing the number of bytes to allocate (usually from the heap, although this - // may not be true on e.g. embedded systems - the C standard says nothing about it). - int *my_ptr = malloc(sizeof(*my_ptr) * 20); - 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) + int* x_ptr = x_array; + // x_ptr now points to the first element in the array (the integer 20). + // This works because arrays often decay into pointers to their first element. + // For example, when an array is passed to a function or is assigned to a pointer, + // it decays into (implicitly converted to) a pointer. + // Exceptions: when the array is the argument of the `&` (address-of) operator: + int arr[10]; + int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! + // It's of type "pointer to array" (of ten `int`s). + // or when the array is a string literal used for initializing a char array: + char otherarr[] = "foobarbazquirk"; + // or when it's the argument of the `sizeof` or `alignof` operator: + int arraythethird[10]; + int *ptr = arraythethird; // equivalent with int *ptr = &arr[0]; + printf("%zu, %zu\n", sizeof arraythethird, sizeof ptr); // probably prints "40, 4" or "40, 8" + + + // Pointers are incremented and decremented based on their type + // (this is called pointer arithmetic) + printf("%d\n", *(x_ptr + 1)); // => Prints 19 + printf("%d\n", x_array[1]); // => Prints 19 + + // You can also dynamically allocate contiguous blocks of memory with the + // standard library function malloc, which takes one argument of type size_t + // representing the number of bytes to allocate (usually from the heap, although this + // may not be true on e.g. embedded systems - the C standard says nothing about it). + int *my_ptr = malloc(sizeof(*my_ptr) * 20); + 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) // 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. - - // When you're done with a malloc'd block of memory, you need to free it, - // or else no one else can use it until your program terminates - // (this is called a "memory leak"): - free(my_ptr); - - // Strings are arrays of char, but they are usually represented as a - // pointer-to-char (which is a pointer to the first element of the array). - // It's good practice to use `const char *' when referring to a string literal, - // since string literals shall not be modified (i.e. "foo"[0] = 'a' is ILLEGAL.) - const char *my_str = "This is my very own string literal"; - printf("%c\n", *my_str); // => 'T' - - // This is not the case if the string is an array - // (potentially initialized with a string literal) - // that resides in writable memory, as in: - char foo[] = "foo"; - foo[0] = 'a'; // this is legal, foo now contains "aoo" - - function_1(); + printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? It may even crash. + + // When you're done with a malloc'd block of memory, you need to free it, + // or else no one else can use it until your program terminates + // (this is called a "memory leak"): + free(my_ptr); + + // Strings are arrays of char, but they are usually represented as a + // pointer-to-char (which is a pointer to the first element of the array). + // It's good practice to use `const char *' when referring to a string literal, + // since string literals shall not be modified (i.e. "foo"[0] = 'a' is ILLEGAL.) + const char *my_str = "This is my very own string literal"; + printf("%c\n", *my_str); // => 'T' + + // This is not the case if the string is an array + // (potentially initialized with a string literal) + // that resides in writable memory, as in: + char foo[] = "foo"; + foo[0] = 'a'; // this is legal, foo now contains "aoo" + + function_1(); } // end main function /////////////////////////////////////// @@ -427,12 +426,12 @@ int main() { int add_two_ints(int x1, int x2) { - return x1 + x2; // Use return to return a value + return x1 + x2; // Use return to return a value } /* 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. @@ -444,14 +443,14 @@ Example: in-place string reversal // A void function returns no value void str_reverse(char *str_in) { - char tmp; - int ii = 0; - size_t len = strlen(str_in); // `strlen()` is part of the c standard library - for (ii = 0; ii < len / 2; ii++) { - tmp = str_in[ii]; - str_in[ii] = str_in[len - ii - 1]; // ii-th char from end - str_in[len - ii - 1] = tmp; - } + char tmp; + int ii = 0; + size_t len = strlen(str_in); // `strlen()` is part of the c standard library + for (ii = 0; ii < len / 2; ii++) { + tmp = str_in[ii]; + str_in[ii] = str_in[len - ii - 1]; // ii-th char from end + str_in[len - ii - 1] = tmp; + } } /* @@ -463,13 +462,13 @@ printf("%s\n", c); // => ".tset a si sihT" //if referring to external variables outside function, must use extern keyword. int i = 0; void testFunc() { - extern int i; //i here is now using external variable i + extern int i; //i here is now using external variable i } //make external variables private to source file with static: -static int i = 0; //other files using testFunc() cannot access variable i -void testFunc() { - extern int i; +static int j = 0; //other files using testFunc() cannot access variable i +void testFunc2() { + extern int j; } //**You may also declare functions as static to make them private** @@ -486,8 +485,8 @@ my_type my_type_var = 0; // Structs are just collections of data, the members are allocated sequentially, // in the order they are written: struct rectangle { - int width; - int height; + int width; + int height; }; // It's not generally true that @@ -497,20 +496,20 @@ struct rectangle { void function_1() { - struct rectangle my_rec; + struct rectangle my_rec; - // Access struct members with . - my_rec.width = 10; - my_rec.height = 20; + // Access struct members with . + my_rec.width = 10; + my_rec.height = 20; - // You can declare pointers to structs - struct rectangle *my_rec_ptr = &my_rec; + // You can declare pointers to structs + struct rectangle *my_rec_ptr = &my_rec; - // Use dereferencing to set struct pointer members... - (*my_rec_ptr).width = 30; + // Use dereferencing to set struct pointer members... + (*my_rec_ptr).width = 30; - // ... or even better: prefer the -> shorthand for the sake of readability - my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10; + // ... or even better: prefer the -> shorthand for the sake of readability + my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10; } // You can apply a typedef to a struct for convenience @@ -518,14 +517,14 @@ typedef struct rectangle rect; int area(rect r) { - return r.width * r.height; + return r.width * r.height; } // if you have large structs, you can pass them "by pointer" to avoid copying // the whole struct: -int area(const rect *r) +int areaptr(const rect *r) { - return r->width * r->height; + return r->width * r->height; } /////////////////////////////////////// @@ -540,12 +539,12 @@ However, definition syntax may be initially confusing. Example: use str_reverse from a pointer */ void str_reverse_through_pointer(char *str_in) { - // Define a function pointer variable, named f. - void (*f)(char *); // Signature should exactly match the target function. - f = &str_reverse; // Assign the address for the actual function (determined at run time) - // f = str_reverse; would work as well - functions decay into pointers, similar to arrays - (*f)(str_in); // Just calling the function through the pointer - // f(str_in); // That's an alternative but equally valid syntax for calling it. + // Define a function pointer variable, named f. + void (*f)(char *); // Signature should exactly match the target function. + f = &str_reverse; // Assign the address for the actual function (determined at run time) + // f = str_reverse; would work as well - functions decay into pointers, similar to arrays + (*f)(str_in); // Just calling the function through the pointer + // f(str_in); // That's an alternative but equally valid syntax for calling it. } /* @@ -560,36 +559,37 @@ typedef void (*my_fnp_type)(char *); // my_fnp_type f; //Special characters: -'\a' // alert (bell) character -'\n' // newline character -'\t' // tab character (left justifies text) -'\v' // vertical tab -'\f' // new page (form feed) -'\r' // carriage return -'\b' // backspace character -'\0' // NULL character. Usually put at end of strings in C. - // hello\n\0. \0 used by convention to mark end of string. -'\\' // backslash -'\?' // question mark -'\'' // single quote -'\"' // double quote -'\xhh' // hexadecimal number. Example: '\xb' = vertical tab character -'\ooo' // octal number. Example: '\013' = vertical tab character +/* +'\a'; // alert (bell) character +'\n'; // newline character +'\t'; // tab character (left justifies text) +'\v'; // vertical tab +'\f'; // new page (form feed) +'\r'; // carriage return +'\b'; // backspace character +'\0'; // NULL character. Usually put at end of strings in C. +// hello\n\0. \0 used by convention to mark end of string. +'\\'; // backslash +'\?'; // question mark +'\''; // single quote +'\"'; // double quote +'\xhh'; // hexadecimal number. Example: '\xb' = vertical tab character +'\ooo'; // octal number. Example: '\013' = vertical tab character //print formatting: -"%d" // integer -"%3d" // integer with minimum of length 3 digits (right justifies text) -"%s" // string -"%f" // float -"%ld" // long -"%3.2f" // minimum 3 digits left and 2 digits right decimal float -"%7.4s" // (can do with strings too) -"%c" // char -"%p" // pointer -"%x" // hexadecimal -"%o" // octal -"%%" // prints % - +"%d"; // integer +"%3d"; // integer with minimum of length 3 digits (right justifies text) +"%s"; // string +"%f"; // float +"%ld"; // long +"%3.2f"; // minimum 3 digits left and 2 digits right decimal float +"%7.4s"; // (can do with strings too) +"%c"; // char +"%p"; // pointer +"%x"; // hexadecimal +"%o"; // octal +"%%"; // prints % +*/ /////////////////////////////////////// // Order of Evaluation /////////////////////////////////////// -- cgit v1.2.3 From 50fe4d985952e6fd978df7a97e491cb0456fe11c Mon Sep 17 00:00:00 2001 From: iirelu Date: Thu, 17 Jul 2014 17:08:30 +0100 Subject: Commented out two broken lines in learnc.c --- c.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index bc9a959a..b0c77e16 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -281,10 +281,10 @@ int main() { // branching with multiple choices: switch() switch (a) { case 0: // labels need to be integral *constant* expressions - do_stuff(); + //do_stuff(); break; // if you don't break, control flow falls over labels case 1: - do_something_else(); + //do_something_else(); break; default: // if `some_integral_expression` didn't match any of the labels -- cgit v1.2.3 From a9f51d5bbf977859093d26823f327c0d6003352c Mon Sep 17 00:00:00 2001 From: iirelu Date: Thu, 17 Jul 2014 20:37:52 +0100 Subject: Made learnc's switch statement clearer Also cleaned up trailing whitespace. --- c.html.markdown | 67 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index b0c77e16..8e170300 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -23,9 +23,9 @@ Multi-line comments look like this. They work in C89 as well. // Constants: #define #define DAYS_IN_YEAR 365 - // Enumeration constants are also ways to declare constants. + // Enumeration constants are also ways to declare constants. enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; -// MON gets 2 automatically, TUE gets 3, etc. +// MON gets 2 automatically, TUE gets 3, etc. // Import headers with #include #include @@ -43,7 +43,7 @@ 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 +int add_two_ints(int x1, int x2); // function prototype // Your program's entry point is a function called // main with an integer return type. @@ -57,7 +57,7 @@ int main() { // Types /////////////////////////////////////// - // ints are usually 4 bytes + // ints are usually 4 bytes int x_int = 0; // shorts are usually 2 bytes @@ -70,7 +70,7 @@ int main() { // longs are often 4 to 8 bytes; long longs are guaranteed to be at least // 64 bits long x_long = 0; - long long x_long_long = 0; + long long x_long_long = 0; // floats are usually 32-bit floating point numbers float x_float = 0.0; @@ -83,9 +83,9 @@ int main() { unsigned int ux_int; unsigned long long ux_long_long; - // chars inside single quotes are integers in machine's character set. - '0'; // => 48 in the ASCII character set. - 'A'; // => 65 in the ASCII character set. + // chars inside single quotes are integers in machine's character set. + '0'; // => 48 in the ASCII character set. + 'A'; // => 65 in the ASCII character set. // sizeof(T) gives you the size of a variable with type T in bytes // sizeof(obj) yields the size of the expression (variable, literal, etc.). @@ -96,7 +96,7 @@ int main() { // is not evaluated (except VLAs (see below)). // The value it yields in this case is a compile-time constant. int a = 1; - // size_t is an unsigned integer type of at least 2 bytes used to represent + // size_t is an unsigned integer type of at least 2 bytes used to represent // the size of an object. size_t size = sizeof(a++); // a++ is not evaluated printf("sizeof(a++) = %zu where a = %d\n", size, a); @@ -163,7 +163,7 @@ int main() { /////////////////////////////////////// // Shorthands for multiple declarations: - int i1 = 1, i2 = 2; + int i1 = 1, i2 = 2; float f1 = 1.0, f2 = 2.0; int b, c; @@ -184,7 +184,7 @@ int main() { // Comparison operators are probably familiar, but // there is no Boolean type in c. We use ints instead. // (Or _Bool or bool in C99.) - // 0 is false, anything else is true. (The comparison + // 0 is false, anything else is true. (The comparison // operators always yield 0 or 1.) 3 == 2; // => 0 (false) 3 != 2; // => 1 (true) @@ -211,14 +211,14 @@ int main() { int e = 5; int f = 10; int z; - z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." + z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." //Increment and decrement operators: char *s = "iLoveC"; int j = 0; s[j++]; // => "i". Returns the j-th item of s THEN increments value of j. - j = 0; - s[++j]; // => "L". Increments value of j THEN returns j-th value of s. + j = 0; + s[++j]; // => "L". Increments value of j THEN returns j-th value of s. // same with j-- and --j // Bitwise operators! @@ -249,7 +249,7 @@ int main() { // While loops exist int ii = 0; - while (ii < 10) { //ANY value not zero is true. + while (ii < 10) { //ANY value not zero is true. printf("%d, ", ii++); // ii++ increments ii AFTER using its current value. } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " @@ -281,10 +281,10 @@ int main() { // branching with multiple choices: switch() switch (a) { case 0: // labels need to be integral *constant* expressions - //do_stuff(); + printf("Hey, 'a' equals 0!\n"); break; // if you don't break, control flow falls over labels case 1: - //do_something_else(); + printf("Huh, 'a' equals 1!\n"); break; default: // if `some_integral_expression` didn't match any of the labels @@ -292,7 +292,6 @@ int main() { exit(-1); break; } - /////////////////////////////////////// // Typecasting @@ -324,7 +323,7 @@ int main() { /////////////////////////////////////// // A pointer is a variable declared to store a memory address. Its declaration will - // also tell you the type of data it points to. You can retrieve the memory address + // also tell you the type of data it points to. You can retrieve the memory address // of your variables, then mess with them. int x = 0; @@ -362,7 +361,7 @@ int main() { // Declare a pointer of type int and initialize it to point to x_array int* x_ptr = x_array; - // x_ptr now points to the first element in the array (the integer 20). + // x_ptr now points to the first element in the array (the integer 20). // This works because arrays often decay into pointers to their first element. // For example, when an array is passed to a function or is assigned to a pointer, // it decays into (implicitly converted to) a pointer. @@ -396,7 +395,7 @@ int main() { // "unpredictable results" - the program is said to invoke "undefined behavior" printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? It may even crash. - // When you're done with a malloc'd block of memory, you need to free it, + // When you're done with a malloc'd block of memory, you need to free it, // or else no one else can use it until your program terminates // (this is called a "memory leak"): free(my_ptr); @@ -430,12 +429,12 @@ 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 -do to the arguments in the function do not change the value of the original -argument where the function was called. +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 +do to the arguments in the function do not change the value of the original +argument where the function was called. -Use pointers if you need to edit the original argument values. +Use pointers if you need to edit the original argument values. Example: in-place string reversal */ @@ -528,18 +527,18 @@ int areaptr(const rect *r) } /////////////////////////////////////// -// Function pointers +// Function pointers /////////////////////////////////////// /* At run time, functions are located at known memory addresses. Function pointers are -much like any other pointer (they just store a memory address), but can be used +much like any other pointer (they just store a memory address), but can be used to invoke functions directly, and to pass handlers (or callback functions) around. However, definition syntax may be initially confusing. Example: use str_reverse from a pointer */ void str_reverse_through_pointer(char *str_in) { - // Define a function pointer variable, named f. + // Define a function pointer variable, named f. void (*f)(char *); // Signature should exactly match the target function. f = &str_reverse; // Assign the address for the actual function (determined at run time) // f = str_reverse; would work as well - functions decay into pointers, similar to arrays @@ -556,7 +555,7 @@ typedef void (*my_fnp_type)(char *); // Then used when declaring the actual pointer variable: // ... -// my_fnp_type f; +// my_fnp_type f; //Special characters: /* @@ -567,8 +566,8 @@ typedef void (*my_fnp_type)(char *); '\f'; // new page (form feed) '\r'; // carriage return '\b'; // backspace character -'\0'; // NULL character. Usually put at end of strings in C. -// hello\n\0. \0 used by convention to mark end of string. +'\0'; // NULL character. Usually put at end of strings in C. +// hello\n\0. \0 used by convention to mark end of string. '\\'; // backslash '\?'; // question mark '\''; // single quote @@ -582,13 +581,13 @@ typedef void (*my_fnp_type)(char *); "%s"; // string "%f"; // float "%ld"; // long -"%3.2f"; // minimum 3 digits left and 2 digits right decimal float +"%3.2f"; // minimum 3 digits left and 2 digits right decimal float "%7.4s"; // (can do with strings too) "%c"; // char "%p"; // pointer "%x"; // hexadecimal "%o"; // octal -"%%"; // prints % +"%%"; // prints % */ /////////////////////////////////////// // Order of Evaluation -- cgit v1.2.3 From c0c77e850c051a28afafcd1e71710c4eebebcccc Mon Sep 17 00:00:00 2001 From: Ben Eysenbach Date: Wed, 3 Sep 2014 22:46:50 -0400 Subject: Clarified C Octal Character This fixes issue #658 --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 8e170300..79b7aec7 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -573,7 +573,7 @@ typedef void (*my_fnp_type)(char *); '\''; // single quote '\"'; // double quote '\xhh'; // hexadecimal number. Example: '\xb' = vertical tab character -'\ooo'; // octal number. Example: '\013' = vertical tab character +'\0oo'; // octal number. Example: '\013' = vertical tab character //print formatting: "%d"; // integer -- cgit v1.2.3 From cd7ed4f9f9590f82acf953bba8d6032e1f62fa0c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 5 Sep 2014 20:47:18 -0500 Subject: Couple changes to C to close https://github.com/adambard/learnxinyminutes-docs/pull/594 --- c.html.markdown | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 79b7aec7..cbb6d289 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -4,6 +4,7 @@ filename: learnc.c contributors: - ["Adam Bard", "http://adambard.com/"] - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"] + - ["Jakub Trzebiatowski", "http://cbs.stgn.pl"] --- @@ -175,6 +176,9 @@ int main() { i2 * i1; // => 2 i1 / i2; // => 0 (0.5, but truncated towards 0) + // You need to cast at least one integer to float to get a floating-point result + (float)i1 / i2 // => 0.5f + i1 / (double)i2 // => 0.5 // Same with double f1 / f2; // => 0.5, plus or minus epsilon // Floating-point numbers and calculations are not exact @@ -194,9 +198,11 @@ int main() { 2 >= 2; // => 1 // C is not Python - comparisons don't chain. - // WRONG: - //int between_0_and_2 = 0 < a < 2; - // Correct: + // Warning: The line below will compile, but it means `(0 < a) < 2`. + // This expression is always true, because (0 < a) could be either 1 or 0. + // In this case it's 1, because (0 < 1). + int between_0_and_2 = 0 < a < 2; + // Instead use: int between_0_and_2 = 0 < a && a < 2; // Logic works on ints -- cgit v1.2.3 From a5b7319eac940cd81693fd590f3df01b5a70816b Mon Sep 17 00:00:00 2001 From: adventuretc Date: Sat, 27 Sep 2014 21:38:30 +0200 Subject: Correction to use the intended variables. --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index cbb6d289..10e6fa45 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -217,7 +217,7 @@ int main() { int e = 5; int f = 10; int z; - z = (a > b) ? a : b; // => 10 "if a > b return a, else return b." + z = (e > f) ? e : f; // => 10 "if e > f return e, else return f." //Increment and decrement operators: char *s = "iLoveC"; -- cgit v1.2.3 From 0ec14c6914ae9a0c968b8f2e70e31b43f3aaaf73 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 17 Oct 2014 20:57:18 -0500 Subject: Add fixes from @marcom's PR https://github.com/adambard/learnxinyminutes-docs/pull/765 --- c.html.markdown | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 10e6fa45..6daabe94 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -5,6 +5,7 @@ contributors: - ["Adam Bard", "http://adambard.com/"] - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"] - ["Jakub Trzebiatowski", "http://cbs.stgn.pl"] + - ["Marco Scannadinari", "https://marcoms.github.io"] --- @@ -21,6 +22,10 @@ memory management and C will take you as far as you need to go. Multi-line comments look like this. They work in C89 as well. */ +/* +Multi-line comments don't nest /* Be careful */ // comment ends on this line... +*/ // ...not this one! + // Constants: #define #define DAYS_IN_YEAR 365 @@ -74,10 +79,10 @@ int main() { long long x_long_long = 0; // floats are usually 32-bit floating point numbers - float x_float = 0.0; + float x_float = 0.0f; // 'f' suffix here denotes floating point literal // doubles are usually 64-bit floating-point numbers - double x_double = 0.0; + double x_double = 0.0; // real numbers without any suffix are doubles // Integral types may be unsigned. unsigned short ux_short; -- cgit v1.2.3 From 56d86a244e93741535d6c5212f0378c105179745 Mon Sep 17 00:00:00 2001 From: Wes Turner Date: Sun, 2 Nov 2014 04:52:31 -0600 Subject: [c/en] Typo: integral -> integer --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 6daabe94..874197d3 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -84,7 +84,7 @@ int main() { // doubles are usually 64-bit floating-point numbers double x_double = 0.0; // real numbers without any suffix are doubles - // Integral types may be unsigned. + // integer types may be unsigned (only positive) unsigned short ux_short; unsigned int ux_int; unsigned long long ux_long_long; -- cgit v1.2.3 From d179669f3985f8cab479778a1a32f7e02ea3f182 Mon Sep 17 00:00:00 2001 From: Martin Thoresen Date: Mon, 24 Nov 2014 17:37:55 +0100 Subject: fix #873 --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 874197d3..f44da38e 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -629,7 +629,7 @@ typedef void (*my_fnp_type)(char *); ## 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) -It is *the* book about C, written by the creators of C. Be careful, though - it's ancient and it contains some +It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some inaccuracies (well, ideas that are not considered good anymore) or now-changed practices. Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/). -- cgit v1.2.3 From 8291fb2d7d376186a19e643e92aacb9ed9412395 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 8 Dec 2014 13:27:06 +0100 Subject: Update c.html.markdown --- c.html.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index f44da38e..b5b804af 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -26,13 +26,15 @@ Multi-line comments look like this. They work in C89 as well. Multi-line comments don't nest /* Be careful */ // comment ends on this line... */ // ...not this one! - // Constants: #define +// Constants: #define #define DAYS_IN_YEAR 365 - // Enumeration constants are also ways to declare constants. - enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +// Enumeration constants are also ways to declare constants. +// All statements must end with a semicolon +enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; // MON gets 2 automatically, TUE gets 3, etc. + // Import headers with #include #include #include @@ -57,7 +59,6 @@ int main() { // print output using printf, for "print formatted" // %d is an integer, \n is a newline printf("%d\n", 0); // => Prints 0 - // All statements must end with a semicolon /////////////////////////////////////// // Types -- cgit v1.2.3 From d1171443ddc0eda7cbabfc41d110a76a67e494ab Mon Sep 17 00:00:00 2001 From: mordner Date: Thu, 8 Jan 2015 23:21:39 +0100 Subject: Fixed one line being cut off and a comment about the export attribute was referring to the wrong function and variable. --- c.html.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index b5b804af..7670824a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -386,7 +386,8 @@ int main() { // or when it's the argument of the `sizeof` or `alignof` operator: int arraythethird[10]; int *ptr = arraythethird; // equivalent with int *ptr = &arr[0]; - printf("%zu, %zu\n", sizeof arraythethird, sizeof ptr); // probably prints "40, 4" or "40, 8" + printf("%zu, %zu\n", sizeof arraythethird, sizeof ptr); + // probably prints "40, 4" or "40, 8" // Pointers are incremented and decremented based on their type @@ -477,7 +478,7 @@ void testFunc() { } //make external variables private to source file with static: -static int j = 0; //other files using testFunc() cannot access variable i +static int j = 0; //other files using testFunc2() cannot access variable j void testFunc2() { extern int j; } -- cgit v1.2.3 From 21fa7d7e391f4d03d5f527043fec73fd7260334a Mon Sep 17 00:00:00 2001 From: Devin McGinty Date: Fri, 30 Jan 2015 16:42:35 -0500 Subject: Change explanation of unsigned types --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 7670824a..1696d28f 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -85,7 +85,7 @@ int main() { // doubles are usually 64-bit floating-point numbers double x_double = 0.0; // real numbers without any suffix are doubles - // integer types may be unsigned (only positive) + // integer types may be unsigned (greater than or equal to zero) unsigned short ux_short; unsigned int ux_int; unsigned long long ux_long_long; -- cgit v1.2.3 From e267eed62caf49d6d2b0d91c60d30b700d08729f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 30 Mar 2015 10:08:30 +0300 Subject: c.html: fix #1021 (bitwise negation and shifting into the sign bit) 0x0f is of type int, for 32-bit int the result is 0xfffffff0. 31'st bit is the sign bit of a 32-bit wide int. --- c.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 1696d28f..d3f20eda 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -234,7 +234,7 @@ int main() { // same with j-- and --j // Bitwise operators! - ~0x0F; // => 0xF0 (bitwise negation, "1's complement") + ~0x0F; // => 0xFFFFFFF0 (bitwise negation, "1's complement", example result for 32-bit int) 0x0F & 0xF0; // => 0x00 (bitwise AND) 0x0F | 0xF0; // => 0xFF (bitwise OR) 0x04 ^ 0x0F; // => 0x0B (bitwise XOR) @@ -242,7 +242,7 @@ int main() { 0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) // Be careful when shifting signed integers - the following are undefined: - // - shifting into the sign bit of a signed integer (int a = 1 << 32) + // - shifting into the sign bit of a signed integer (int a = 1 << 31) // - left-shifting a negative number (int a = -1 << 2) // - shifting by an offset which is >= the width of the type of the LHS: // int a = 1 << 32; // UB if int is 32 bits wide -- cgit v1.2.3 From 3d0687027a450d1778e6f7336f96962fa385ec53 Mon Sep 17 00:00:00 2001 From: Joe Savage Date: Sat, 29 Aug 2015 11:44:41 +0100 Subject: add missing semicolons in c.html.markdown --- c.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index d3f20eda..e2e15620 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -183,8 +183,8 @@ int main() { i1 / i2; // => 0 (0.5, but truncated towards 0) // You need to cast at least one integer to float to get a floating-point result - (float)i1 / i2 // => 0.5f - i1 / (double)i2 // => 0.5 // Same with double + (float)i1 / i2; // => 0.5f + i1 / (double)i2; // => 0.5 // Same with double f1 / f2; // => 0.5, plus or minus epsilon // Floating-point numbers and calculations are not exact -- cgit v1.2.3 From 85d80b9e5d8a124d00322f5228e5be64cd97c8ea Mon Sep 17 00:00:00 2001 From: Joe Savage Date: Sat, 29 Aug 2015 11:47:09 +0100 Subject: fix resource capitalisation and add resource to c.html.markdown --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index e2e15620..09806d93 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -634,7 +634,7 @@ Best to find yourself a copy of [K&R, aka "The C Programming Language"](https:// It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some inaccuracies (well, ideas that are not considered good anymore) or now-changed practices. -Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/). +Other good resources include [Learn C The Hard Way](http://c.learncodethehardway.org/book/) and [SourceCrunch](https://www.sourcecrunch.com/courses/foundations-of-c). If you have a question, read the [compl.lang.c Frequently Asked Questions](http://c-faq.com). -- cgit v1.2.3 From 7cb94b3b85608a73a0200469a8fa897e68f7c991 Mon Sep 17 00:00:00 2001 From: Joe Savage Date: Sat, 29 Aug 2015 11:58:03 +0100 Subject: main() -> main(void) & fix spacing in c.html.markdown --- c.html.markdown | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 09806d93..2b087688 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -18,9 +18,9 @@ memory management and C will take you as far as you need to go. ```c // Single-line comments start with // - only available in C99 and later. - /* +/* Multi-line comments look like this. They work in C89 as well. - */ +*/ /* Multi-line comments don't nest /* Be careful */ // comment ends on this line... @@ -55,7 +55,7 @@ int add_two_ints(int x1, int x2); // function prototype // Your program's entry point is a function called // main with an integer return type. -int main() { +int main(void) { // print output using printf, for "print formatted" // %d is an integer, \n is a newline printf("%d\n", 0); // => Prints 0 @@ -157,12 +157,12 @@ int main() { int cha = 'a'; // fine char chb = 'a'; // fine too (implicit conversion from int to char) - //Multi-dimensional arrays: + // Multi-dimensional arrays: int multi_array[2][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 0} }; - //access elements: + // access elements: int array_int = multi_array[0][2]; // => 3 /////////////////////////////////////// @@ -219,13 +219,13 @@ int main() { 0 || 1; // => 1 (Logical or) 0 || 0; // => 0 - //Conditional expression ( ? : ) + // Conditional 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: + // Increment and decrement operators: char *s = "iLoveC"; int j = 0; s[j++]; // => "i". Returns the j-th item of s THEN increments value of j. @@ -371,7 +371,7 @@ int main() { x_array[xx] = 20 - xx; } // Initialize x_array to 20, 19, 18,... 2, 1 - // Declare a pointer of type int and initialize it to point to x_array + // Declare a pointer of type int and initialize it to point to x_array int* x_ptr = x_array; // x_ptr now points to the first element in the array (the integer 20). // This works because arrays often decay into pointers to their first element. @@ -404,8 +404,8 @@ int main() { *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx } // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) - // Dereferencing memory that you haven't allocated gives - // "unpredictable results" - the program is said to invoke "undefined behavior" + // 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. // When you're done with a malloc'd block of memory, you need to free it, @@ -471,13 +471,13 @@ str_reverse(c); printf("%s\n", c); // => ".tset a si sihT" */ -//if referring to external variables outside function, must use extern keyword. +// if referring to external variables outside function, must use extern keyword. int i = 0; void testFunc() { extern int i; //i here is now using external variable i } -//make external variables private to source file with static: +// make external variables private to source file with static: static int j = 0; //other files using testFunc2() cannot access variable j void testFunc2() { extern int j; -- cgit v1.2.3 From e0d0e9189bb6e0af14a21e0c315922bc16fc2e14 Mon Sep 17 00:00:00 2001 From: Joe Savage Date: Sun, 30 Aug 2015 20:51:23 +0100 Subject: revert additional resource suggestion in c.html.markdown --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 2b087688..8e631de4 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -634,7 +634,7 @@ Best to find yourself a copy of [K&R, aka "The C Programming Language"](https:// It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some inaccuracies (well, ideas that are not considered good anymore) or now-changed practices. -Other good resources include [Learn C The Hard Way](http://c.learncodethehardway.org/book/) and [SourceCrunch](https://www.sourcecrunch.com/courses/foundations-of-c). +Another good resource is [Learn C The Hard Way](http://c.learncodethehardway.org/book/). If you have a question, read the [compl.lang.c Frequently Asked Questions](http://c-faq.com). -- cgit v1.2.3 From c7e552c448c5a562a3ff5f442a7ed834aec04d9e Mon Sep 17 00:00:00 2001 From: Pushkar Sharma Date: Sun, 4 Oct 2015 10:34:31 +0530 Subject: Variable size array, user size input added. #1170 Fixed Issue #1170 Variable size array, user size input added. --- c.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 8e631de4..36621a9e 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -130,7 +130,9 @@ int main(void) { // can be declared as well. The size of such an array need not be a compile // time constant: printf("Enter the array size: "); // ask the user for an array size - char buf[0x100]; + int size; + scanf("%d", &size); + char buf[size]; fgets(buf, sizeof buf, stdin); // strtoul parses a string to an unsigned integer -- cgit v1.2.3 From 2e987df42225e6bdf824584058467aaffc73fb49 Mon Sep 17 00:00:00 2001 From: Pushkar Sharma Date: Mon, 5 Oct 2015 00:52:47 +0530 Subject: replaced scanf with fscanf. --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 36621a9e..db2ac930 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -131,7 +131,7 @@ int main(void) { // time constant: printf("Enter the array size: "); // ask the user for an array size int size; - scanf("%d", &size); + fscanf(stdin, "%d", &size); char buf[size]; fgets(buf, sizeof buf, stdin); -- cgit v1.2.3