diff options
Diffstat (limited to 'c.html.markdown')
| -rw-r--r-- | c.html.markdown | 97 | 
1 files changed, 57 insertions, 40 deletions
| diff --git a/c.html.markdown b/c.html.markdown index c23e8d2c..78083ea5 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -27,7 +27,7 @@ void function_2();  // Your program's entry point is a function called  // main with an integer return type. -int main(){ +int main() {  // print output using printf, for "print formatted"  // %d is an integer, \n is a newline @@ -38,36 +38,49 @@ printf("%d\n", 0); // => Prints 0  // Types  /////////////////////////////////////// -// Variables must always be declared with a type. +// 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. -// 32-bit integer +// ints are usually 4 bytes   int x_int = 0; -// 16-bit integer +// shorts are usually 2 bytes  short x_short = 0; -// 8-bit integer, aka 1 byte +// chars are guaranteed to be 1 byte  char x_char = 0;  char y_char = 'y'; // Char literals are quoted with '' -long x_long = 0; // Still 32 bits for historical reasons -long long x_long_long = 0; // Guaranteed to be at least 64 bits +// 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;  -// 32-bit floating-point decimal +// floats are usually 32-bit floating point numbers  float x_float = 0.0; -// 64-bit floating-point decimal +// doubles are usually 64-bit floating-point numbers  double x_double = 0.0; -// Integer types may be unsigned +// 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.  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("%d\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: @@ -81,16 +94,20 @@ my_array[0]; // => 0  my_array[1] = 2;  printf("%d\n", my_array[1]); // => 2 -// Strings are just lists of chars terminated by a null (0x00) byte. +// 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 a null byte, 0x00 aka \0.  +Char #17 is the NUL byte.   Chars #18, 19 and 20 have undefined values.  */ -printf("%d\n", a_string[16]); +printf("%d\n", a_string[16]); => 0  ///////////////////////////////////////  // Operators @@ -112,7 +129,8 @@ f1 / f2; // => 0.5, plus or minus epsilon  // Comparison operators are probably familiar, but  // there is no boolean type in c. We use ints instead. -// 0 is false, anything else is true +// 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 @@ -140,33 +158,33 @@ f1 / f2; // => 0.5, plus or minus epsilon  // Control Structures  /////////////////////////////////////// -if(0){ +if (0) {    printf("I am never run\n"); -}else if(0){ +} else if (0) {    printf("I am also never run\n"); -}else{ +} else {    printf("I print\n");  }  // While loops exist  int ii = 0; -while(ii < 10){ +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{ +do {      printf("%d, ", kk); -}while(++kk < 10); // ++kk increments kk in-place, before using its value +} 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++){ +for (jj=0; jj < 10; jj++) {      printf("%d, ", jj);  } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " @@ -176,8 +194,8 @@ printf("\n");  // Typecasting  /////////////////////////////////////// -// Everything in C is stored somewhere in memory. You can change -// the type of a variable to choose how to read its data +// 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 @@ -188,7 +206,11 @@ printf("%d\n", (char) x_hex); // => Prints 1  // Types will overflow without warning  printf("%d\n", (char) 257); // => 1 (Max char = 255) -printf("%d\n", (short) 65537); // => 1 (Max short = 65535) + +// 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 @@ -221,13 +243,14 @@ 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++){ +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; -// This works because an array name is bound to the address of its first element +// 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 @@ -237,33 +260,27 @@ printf("%d\n", x_array[0]); // => Prints 20  printf("%d\n", *(x_ptr + 1)); // => Prints 19  printf("%d\n", x_array[1]); // => Prints 19 -// Array indexes are such a thin wrapper around pointer -// arithmetic that the following works: -printf("%d\n", 0[x_array]); // => Prints 20; -printf("%d\n", 2[x_array]); // => Prints 18; - -// The above is equivalent to: -printf("%d\n", *(0 + x_ptr)); -printf("%d\n", *(2 + x_ptr)); - -// You can give a pointer a block of memory to use with malloc +// 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; +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, 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  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("%d\n", *my_str); // 84 (The ascii value of 'T') +printf("%c\n", *my_str); // => 'T'  function_1();  } // end main function | 
