[[TOC]] ,,'''Note''': This is not pretended to be a Howto, also not really ''public'', it is just a page that i have used to take some notes of a interesting book of C that im reading, you are allowed to edit and correct this document if you see anything wrong, also order it a bit or made it better, but this not pretends to be a ''big'' document so try to maintain it compact. Thanks,, ---- === Comments === The comments are very important for yourself basically, you need to comment all your functions and declarations, and specially you need to comment your variables in order to know *what* exactly they are, and also for know possible special things of these variables It is recommended to learn how works '''doxygen''' (5 minutes reading a howto in google, it is very basic) so that you can know special techniques to comment your source code that then you can build ''documentation'' of your API/source directly from these comments The special things that you need to have in mind when you code is: clarity of code, simplicity, and summary You can do a more understandable code in a lot of things, for example, who reads the code is not supposed to know in the perfection entirely the functions, so you can write code like this: {{{ #!C /* Wrong way: */ if (strcmp(string1, string2) ... /* Easy-to-understand way: */ if ((strcmp(string1, string2) == 0) ... }}} By separating the source code in multiple files, you have your code a lot more organized and there's a lot more easy to read and specially to search something between the code. === Basic Things === To declare a string in a variable, you need to use strcpy, so {{{ #!C name = "Me"; /* Illegal */ strcpy (name, "Me"); /* Legal */ }}} When you assign a single character you need to enclose it in single-quotes ', if you want to assign a string (with the end-of-string (NULL) char included), you need to use double-quotes ". A good way to remove the newline value from variables (when you use a input-line entry system) is by simply set the end-of-string (NULL) value to the newline place, like: {{{ #!C fgets(first, sizeof(first), stdin); first[strlen(first)-1] = '\0'; }}} Remember that a string contains first a newline (if the input has included a newline) and all the strings finishes by the '\0' (NULL) character The '''break''' statement is for exit from a ''loop'', and the '''continue''' statement is for (re)start the loop again (continue from the start) The '''if''' statement is ''true'' when the value is ''non-zero'', zero means ''no data'' or ''null'', so that means false. If you need to check if a value is zero you can simply do: {{{ #!C if (var == 0) }}} ,,Maybe this sounds strange by doing this on this way, but if ''var'' is equal to 0, then the result of the '''()''' is 1 (true), if you don't understand why is 1 or how this works, you need to start reading a new book of C again.,, === Arrays === A two dimensional matrix looks like: {{{ #!C mtrx_var[2][4]; }}} Notice that this form is illegal: {{{ #!C mtrx_var[2,4]; }}} This is also valid: {{{ #!C int mtrx_var[2][4] = { {1, 2, 3, 4}, {10, 20, 30, 40} }; }}} The ''counters'' of the arrays start by 0, so if you need to create an array of 4 elements you need to declare 4 and use them from 0 to 3, this maybe sound strange: * This maybe sound strange, like ''why i need to declare 4 then instead of 3 ?'': simple, because you are declaring 4, and you still having 4 (0 to 3 = 4) === Variables === Variables inside functions (or main) are not ''heritable'' between functions, if you want to call a function with a variable you can use the ''arguments'' on the function call (or a pointer for argument) If you need a ''Global variable''' in your entire code, you need to declare them out of any function Everytime you enclose a variable declaration inside a block '''{}''', it is limited to this section (not works out of it), if you have variables declared out of any function and/or out of main(), it is supported by all the entire application. Also, if you declare a variable inside a block that is already declared outside of it, then for inside the block it is used only the new declared one, not the one declared out of it, however, this practice is not good since may be very confusing. '''Static''': By declaring a '''static''' variable (or function) out of any function (global mode), it will be used only in the actual file (not a real file, but more like a ''compilation unit''), this is good for a better optimization but if you want to use it in other ''files'', you need to declare it by '''extern'''. By other side, if you declare it in a block or a loop something like ''static int foo = 5;'' you can do operations to this variable without worry about the declaration of the value 5, because when is in mode static, it is only declared to the selected value the first time, the next times that are called is ignored. '''signed''': means ''with sign'', so, values negative and positive, for example if the '''char''' variable has a limit of 255 values, using the '''sign''' mode we can use from '''-128''' (negative) to '''127''' (positive), and using '''unsigned''' we can use from '''0''' to '''255''' === Constants === The '''constant''' variables are constants, so they can't change, by convention they are in upper-case. You should use it where ever possible, it improves the robustness of the program, better readability, and also improves (just a bit) the optimization, it is a kind of ''rule'' and correct programming. When you are sure that a variable doesn't (or don't want to) change in a scope of the program, you can use it. {{{ #!C /* The variable answer_p is a constant and can't change, but the pointer address can be changed. */ const char *answer_p = "Forty-Two"; /* If we want to have the inverse to this, we need to put the const AFTER the *, so: */ char *const answer_p = "Forty-Two"; /* Now the pointer can't change the address value, but the data (Forty-Two) can be changed */ /* Finally, we can set both in constant with something like: */ const char *const answer_p = "Forty-Two"; }}} === Relational Operators === {{{ #!C ++total; /* is like */ total = total + 1; total++; /* is like */ newtotal = total; total + 1; /* Note that in 'newtotal' is assigned the value of 'total', and AFTER, total is incremented. First is asigned and after evaluated */ total += 2; /* is like */ total = total + 2; /* There is also: */ -=, *=, /=, %= }}} === Functions === A basic function: {{{ #!C float triangle (float width, float height) ... }}} This function means: it needs to return a ''float'' variable, it is called with two parameters of type float too, this function can't modify directly the variables (width or height), for that is needed to use pointers (because we have the address (of memory) to that data instead the data value, so we can modify its content (data)) This is a example of a function call and modification by using pointers: {{{ #!C void convert_to_42 ( int *input ) { *input = 42; } int value = 12; convert_to_42 ( &value ); }}} A function can be (re)called too, this is known as ''recursion'' === Structures === A structure can contains any variable types sections, and also arrays and sub-structures {{{ #!C /* Note: 'time' is a previously-defined structure' */ struct time lap[MAX_LAPS]; /* This call creates an array called 'lap' of MAX_LAPS elements that are structures of type 'time' */ /* You can also set values like */ lap[count].hour = hour; /* This set the value 'hour' on the 'hour' (structure element) of the 'count' (array element) of lap */ /* Initialization of an array of structures: */ struct time start_stop[2] = { { 10, 0 }, { 12, 0 } }; }}} ==== Packaged structures ==== Image an application that stupidly takes a lot of storage but very few 'cpu' usage and you will need to optimize it for data, you can set the value of the bits to use for the structure elements, like: {{{ #!C struct item { unsigned int seen:1; ... } /* Now the variable 'seen' (seen or not seen) only takes one BIT */ }}} The bad point of this usage is that it the access to this data is pretty more slow than in normal mode, so do this only when is really needed to save storage space. === Pointers === With pointers you can modify directly the data of a variable (see the '''functions''' section) You can access to a lot more fast way to structure elements and other big pieces that are inside big ones, so you can optimize your code with the correct usage of pointers, If you want to have a pointer to an array, you need to point to the first array of the variable, so: {{{ #!C /* array of 5 elements */ char arr[5]; /* pointer 'arr_p' to the array 'arr' char *arr_p = &arr[0]; *(array_p + 1) /* Equivalent */ (*array_p + 1 ) /* Not Equivalent */ }}} === Typedef === With typedef we can define our own variable types, for example: {{{ #!C typedef static long int mylongintstatic; /* example of declare a variable of this new type: */ mylongintstatic var1 = 5; }}} Note that ''typedef'' could be considered similar to the #define statement, but can define more complex objects like: {{{ #!C /* group is a type of 10-elements array */ typedef int group[10] }}} === Conversion === You can convert a variable type to other at any time by: {{{ #!C int value = 5; printf ("%f", (float)value ); }}} === Misc === The '''header''' files should be limited to have only types and definitions === Optimizations === An array do increments of the array level in order to search/find something, by using pointers is a lot faster than generate an index operation, for example: {{{ #!C while ((*array_p) != 0) ++array__p; }}} Imagine a structure that the total size of every structure are 226 bytes, that's a lot of data to move around all the time, so by declaring an array of pointers you will use now the pointers and browse them, instead of the arrays, on this case, you are moving 4 bytes around, instead of 226. {{{ #!C struct mailing { ... } list[MAX_ENTRIES]; struct mailing *list_p[MAX_ENTRIES]; for (current... list_p[current] = &list[current]; }}} === Compiler === If you want to see the preprocessor messages (values), you can see them when compiling by using the -E option (in gcc) If you want to pass something defined (to use with #ifdef, for example) in the moment of the compilation, you will add options to the compiler (gcc) like -DDEBUG or -DMAX=10 == Books == * The book of C by Kernighan & Ritchie * Practical C Programming (very good to understand correctly C and do good practices on it) in o'reilly * Mastering C Algorithms (advanced C) in o'reilly == References == * C FAQ: http://c-faq.com * ##C (freenode) wiki: http://www.iso-9899.info/