[[TOC]] ,,'''Note''': This is not pretended to be a Howto, also not really ''public'', it is only a page that I have used to take some notes of an interesting book of C that I'm reading. You are allowed to edit and correct this document if you see anything wrong, also order it a bit or make it better, but this not pretended 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 especially your variables in order to know *what* exactly they are and to remember the special things about these variables. It is recommended to learn how '''doxygen''' works (5 minutes reading a howto in google, it is very basic) so that you know special techniques about commenting your source code. This will aid in build proper ''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)) printf("......"); /* Easy-to-understand way: */ if (strcmp(string1, string2) == 0) printf("Strings equal"); /* Wrong way: */ long *pTab[10]; // It creates an array with 10 pointers to the type long /* Easy-to-understand way: */ long (*pTab)[10]; // It creates a pointer to an array with 10 elements in type long }}} Why the first example is a more ''wrong way'' than the second? because the common sense makes the reader to think that the printf will be run when the sentences are equal, but what exactly happens is that will return 0 if they are equal so the printf will be not run, this is more clear to understand with the second example. '''Tip''': Apart of that is more easy to read and less error-prone the method of using parentheses, in order to made your code clear and/or if you don't know the order of on which order the things are called in a line, use parentheses. 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. == Variables and Data types == 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 Every time you enclose a variable declaration inside a block '''{}''', it is limited to this section (will not work outside 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. '''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''' === Extern === Since it is the default value out of any function (global mode), you should ignore it. You can use it too for say that a variable is declared from a different (outside) file === Static === You can use ''static'' inside a function or outside it, it has two different meanings: * Inside a function: You can ''pre'' set a value to a variable ''(static int foo = 5)'', then the first time you enter on the function it will be set to 5, but the next times it not set again, it just remember the last value used * Outside a function (global mode): You can only use your static named element on this file, use always static for your functions and variables except when you really need to call it from another file of your source code, the meant of this is to prevent duplicated elements and to have a better optimization. Also, you can use the static variable (out of any function) in order to avoid a double-declaration of the same variable, when you use static (globally) it is limited to the file so, in another file is a different variable without any relation. === Void === * In a function declaration means that the function returns no value * When used in a pointer declaration (called ''pointer to void''), void defines a generic pointer, so it returns an address, it is commonly used when a function is called with differents types of data, specially pointers of types differents, and also very used on these ways: {{{ #!C void *malloc( unsigned int ); /* function prototype for malloc */ string_ptr = malloc(80); /* We call malloc in order to allocate 80 bytes of memory, it returns the address obtained, that is copied to the string_ptr variable (so, the pointer to this address) */ }}} === 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"; }}} === Volatile === With '''volatile''' you can declare something that will be modified by an external program, on the same way, if you declare ''const volatile foo'', the variable ''foo'' its a constant that cannot be modified by the program itself, but can be modified by an external program === Restrict === It is used for pointers, it is used for optimization, using '''restrict''' on a pointer you are only allowed to access to the object with this pointer === 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] }}} === 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 may 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) === 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' */ struct time t1, t2, *pLap, lap[100]; /* Different methods to create structures */ /* 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 } }; }}} In order to reference an element of a structure we use the "'''.'''" (dot) symbol, but if the structure is a pointer, then we need to use '''->''' {{{ #!C /* Element of a structure */ point.horiz /* Same thing if the structure is a Pointer */ point->horiz /* that is equivalent to: */ (*point).horiz }}} ==== Packaged structures ==== Imagine an application that stupidly takes a lot of storage but very few 'cpu' usage and you will need to optimize it for data, imagine that it has 3 variables, ''seen'' is used to know if the element is seen, and ''list'' is used to know if the element is on the list, and ''number'' is the number of the element (the ''data''). Between ''number'' needs to be a full ''int'' that requires 16 bits (or a little less than it), you can set ''seen'' and ''list'' to use only 1 bit each one, and ''number'' to use 14 instead of 16, on that way, you will have the full size of the structure 3 times smaller than originally Normal structure, total: '''48''' bits || ||0 ||1 ||2 ||3 ||4 ||5 ||6 ||7 ||8 ||9 ||10 ||11 ||12 ||13 ||14 ||15 || ||seen ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. || ||list ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. || ||number ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. || Packaged structure, total '''16''' bits ||0 ||1 ||2 ||3 ||4 ||5 ||6 ||7 ||8 ||9 ||10 ||11 ||12 ||13 ||14 ||15 || ||[seen] ||[list] ||[number ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||. ||number] || {{{ #!C struct item { unsigned int seen:1; unsigned int list:1; unsigned int number:14; } }}} 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 pa = &a; // pa points to a pa = a; // pa points to a[0] /* 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 /* All these methods are equivalent: */ &a[i] , a+i , pa+i , &(pa[i]) // Pointers to the 'i' element of an array a[i] , *(a+i) , *(pa+i) , pa[i] // In the same method way, the 'i' element of an array (no-pointer) }}} The most common problem in programming is when you enter some data to a variable and doesn't fit on it, for example you have a char of 10 chars and you insert 15, your application can crash with these things, the solution is to use a ''dynamic allocation of memory'', for example with '''malloc''', malloc is also required for work with some special variables like object images etc... but remember that is very important to ''free'' the pointer when you have finished to use it, and the best way to do it is by having a correctly structured code, follow the ''rules'' of the ''art of unix programming'' by ESR (you must learn these rules like the 10 commandments) ==== Double pointers ==== The double pointer can be used for 2 different things: * A pointer that points to a pointer, so that you can change the value of the original pointer (address value) * ''To modify the value of a variable using pointers in a function, you need to pass the address of that variable'': Same thing when you try to modify the address of a pointer (pointer of a pointer) * A two-dimensional array: like in '''argv''', a matrix, or a list of char*, so (*char[]) {{{ #!C /* Pointer to a pointer */ void foo( char ** ptr) { *ptr = malloc(255); // allocate some memory, obtain a new address for ptr strcpy( *ptr, "Hello World"); // assign some data to our new addressed pointer } int main() { char *ptr = 0; // we set a new pointer to null foo( &ptr ); // we call the function with the address (null) of our pointer /* now (after to call the function to assign the pointer), we have 'ptr' with a new address and allocated memory */ } int main(int argc, char **argv) /* note that '*argv[]' is equivalent to '**argv' */ /* but since it doesn't means the pointer of a pointer, we should use *argv[] in preference because is more understandable to what really means */ }}} === Conversion === You can convert a variable type to other at any time by: {{{ #!C int value = 5; printf ("%f", (float)value ); }}} == Functions == A function can be (re)called too (inside himself), this is known as ''recursion'' Basic example: {{{ #!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)) === Prototype of Functions === Used for the header files, it contains the description of the function and how it should be used, the arguments after the variable type can be any name, used as a simple descriptive comment. When there's no arguments for the function, just put a ''void'' itself inside the (), so for the content of arguments. {{{ #!C double calc( double base, double exponent ); }}} === Structure of a function === {{{ #!C [class_of_memorization] [type] name( [arguments] ) // class: It will be static or extern (see Variables section) // type: It will be anything (void, int, char, a pointer...), except an array // arguments: Arguments to pass to a function, if any }}} === Modification of variables by pointers === 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 ); }}} === Inline === The functions can be defined as ''inline'', on such case the compilator will optimize the speed of call of the function. If the function contains too much instructions, the inline value will be ignored by the compilator. === Multiple arguments === If you need to pass multiple arguments to your function, you can use the special macros from ''stdarg.h'' called ''va_start'', ''va_arg'', and ''va_end''. These functions needs to have at least one argument passed. Steps needed for use it: 1. Declare an object of type '''va_list'''. ''(Example used: arglist)'' 1. Call the macro '''va_start''' with 2 parameters; the object ''arglist'' list, and the name of the obliged argument. 1. Call the macro '''va_arg''' with 2 parameters; the object ''arglist'' so for obtain every argument passed, and the type of the obliged argument. 1. Call the macro '''va_end''' before to continue with the instructions of the function, the only parameter to pass to it is ''arglist'' {{{ #!C #include /* In the prototype function you need to declare it with 3 dots */ int max( int prem, ... ) { int maxarg, arg; va_list arglist; // Object 'list' of extra arguments va_start( arglist, prem ); // We obtain the first argument arg = maxarg = prem; /* The last parameter passed to the function needs to be 0 */ /* so that when we reach it, the loop finshes */ while ( arg != 0 ) { arg = va_arg( arglist, int ); // obtain an argument to arg if ( arg > maxarg ) maxarg = arg; } va_end( arglist ); return maxarg; } }}} == Operators == === Relational Operators === {{{ #!C number = 5; result = number++; /* first is evaluated the expression, after is incremented, result is 5 */ number = 5; result = ++number; /* first is incremented, after is evaluated the expression, result is 6 */ total += 2; /* is like */ total = total + 2; /* There is also: */ -=, *=, /=, %= }}} === The , Operator === It can be used specially to include multiple operators, like in a for statement: {{{ #!C for (two = 0, three = 0 ; two < 10 ; two +=2, three += 3) }}} === Operators to access to memory === || '''Operator''' || '''Description''' || '''Example''' || '''Result''' || || & || Address of || &x || A constant pointer to '''x''' || || * || Indirection || *p || The value (or the function) pointed by the '''p''' address || || [ ] || Element of array || [x]i || *(x+i), the index element '''i''' in the array '''x''' || || . || Member of a structure or union || s.x || The member with name '''x''' in the structure or union '''s''' || || -> || Member of a structure or union || p->x || The member with name '''x''' in the structure or union pointed by '''p''' || == Misc == The '''header''' files should be limited to have only types and definitions. When you free some memory, remember to set the pointer to NULL after in order to avoid possible errors by using freed memory. 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 it 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...,, === The ?: Construct === It can be used like a replacement of ''if, else...'' but also specially to set values, like: {{{ #!C amount_owed = (balance < 0) ? 0 : balance; #define min(x,y) ((x) < (y) ? (x) : (y)) // This is also valid, scanf is only run if i < max i < max && scanf("%d", &x) == 1; return ( a>b ? a : b ); }}} === Macros & Preprocessor === Remember to put always the parameters between parentheses, so that maybe the parameter needs to be calculated before to use it, just like: {{{ #!C #define MAX(a,b) ((a) > (b) ? (a) : (b)) result = 2 * MAX( x, y & 0xFF ); }}} ==== The # Operator ==== When used inside a macro, it is replaced by the parameter given to the macro call, so: {{{ #!C #define impr(i) printf( "value " #i " = %d", i) int x = 18, y = 2; impr(x-y); // result: "value x-y = 16" }}} ==== The ## Operator ==== When used inside a macro, it is replaced by the parameters given to the macro and removing spaces, so: {{{ #!C #define impr(i) printf( #var " with " #num " = %d" var ## num ) // var ## num (x and 5) is replaced by x5 int x4 = 15, x5 = 16; impr( x, 5 ); // result: "x with 5 = 16" }}} ==== #include, #if, #else, #elif, #endif ==== {{{ #!C #if VERSION == 1 #define MY_PROJ "version1.h" #else #define MY_PROJ "version2.h" #endif #include MY_PROJ }}} ==== #ifdef, #ifndef, #undef ==== {{{ #!C #define MAX(a,b) ((a) > (b) ? (a) : (b)) #ifdef MAX #undef MAX #endif }}} ==== #line ==== It allow you to be moved to any line and also to another file, from your source code directly: {{{ #!C #line 500 "my_prog.c" }}} == 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 do ++array__p while ((*array_p) != 0); /* or */ // loop *matrix_ptr = -1 ; ++matrix_ptr ; }}} 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 { char name[60]; char address[120]; ... } list[MAX_ENTRIES]; struct mailing *list_ptrs[MAX_ENTRIES]; int current; for (current = 0; current = number_of_entries; ++current) list_ptrs[current] = &list[current]; /* Now we have in every list_prts[element], a pointer to the equivalent list[element] array of structures */ }}} * When you are coding, if you use optimizations in your cflags, the compilation timing is a lot slower, could be nice to have an ''--coding'' option in your autotools code, or just set your CFLAGS to -O0 * if you do a lot of calls to the same variable, set it as '''register''', but do not abuse of it or will not have any effect * if you use a for inside a for, try to use the smaller value ''(for less loop calls)'' for the parents and the bigger ones (more loops) for the childs * if we use a double for, we can resum them in a single one, since the counter loop needs the same number of loops than simply (for1 * for2) * use pointers instead of array's: since we can increment by one the place of the pointer under the matrix (array), we can use the pointer in order to set every value of the loop to it and increment it by one before to continue with the next loop * use functions that does all the job in a one time, like the '''memset''' function for this case that declares all the values of the matrix to a specified value * use macros === How to Optimize === * Loop Ordering: Nested loops should be ordered with the simplest loop outermost and the most complex loops innermost * Powers of 2: Use a power of 2 when doing integer multiply or divide. Most compilers substitute a shift for the operation. * Pointers: Using pointers is faster than indexing an array. * Macros: Using a macro eliminates the overhead associated with a function call. It also makes the code bigger and a little more difficult to debug. * Reduction in strength: Use cheap operations, there's a table of cost of common operations: || '''Operation''' || '''Relative cost''' || || printf and scanf || 1000 || || malloc and free || 800 || || trigonometric functions (sin, cos...) || 500 || || floating point (any operation) || 100 || || integer divide || 30 || || integer multiple || 20 || || function call || 10 || || simple array index || 6 || || shifts || 5 || || add/substract || 5 || || pointer dereference || 2 || || bitwise and, or, not || 1 || || logical and, or, not || 1 || === Good Practices === ==== Avoid Segfaults ==== * Always use ''else'' when you can * If you have a variable that is set to something in case of ''foo'', always set it to other thing when is not ''foo'', so if you check it in the future it will check the correct kind of data * Never forget to set a variable during the process of a program, even in ''else'' cases, you will have segfaults if you do anything with it like a check. * Use [http://lumiera.org/nobug_manual.html NoBug library] and/or EINA features == 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 == Debugging == === GDB === Basic Commands || '''Comand''' || '''Description''' || || l/list [file:]function/line/from,to || List/print the actual piece of code || || b/break [file:]function/line || set a breakpoint at function (in file) || || r/run [arglist] || run the programm, with arglist if specified || || bt || backtrace: display the program stack || || fr/frame number || we go to the selected frame number (like the ones resulting in a backtrace || || p/print expr || Show the value of the variables, if you want to see the pointed value use *pointer || || x || examine memory in different data formats/types (string, int, hex, etc), see: help x || || c || continue running the programm after a stop (like a breakpoint) || || n/next || execute next program line (after stopping); OVER any function call in the line || || s/step || execute next program line (after stopping); INTO any function call in the line || Extra Commands || '''Comand''' || '''Description''' || || help || show a list of extra help || || info || show things about your program || || help status || list of available status states of the program || || info source || display information about the current source file || || info locals || show values of local variables of actual function || || info args || show arguments of actual function || || set args [arguments] || set commandline arguments for the program || || set listsize number || set the default number of lines for the command list || || info breakpoints || show all the defined breakpoints || || tbreak line/function || set a temporal breakpoint; it is removed after to reach it || || delete [bp_number|range] || delete breakpoints; no parameters = delete all of them || || disable [bp_number|range] || disable breakpoints; use '''enable''' to enable them again || || watch || set a watchpoint to an expression, the program stops when the value of the expression changes, use '''rwatch''' to read it at any time || || start || ''run'' and ''stop'' in main || || jump || continue program at specified line or address || || edit || edit source code with EDITOR (env variable) at selected point || === Messages === * Segfault: The program has tried to dereference a pointer containing a bad value * Stack Overflow: The program has tried to use too many temporary variables. Common problem when there's a infinite loop recursiontes == == 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 * UNIX (unix/linux) programming FAQ: http://www.faqs.org/faqs/unix-faq/programmer/faq/ * GDB Tutorial: http://oreilly.com/catalog/9780596006976/preview.html (search section 20, final of the book), a nice [http://blogs.sun.com/dbx/entry/gdb_vs_dbx_commands_mapping reference for gdb] * ##C (freenode) wiki: http://www.iso-9899.info/ * [http://www.duckware.com/bugfreec/index.html Writing Bug-Free C Code]: A Programming Style That Automatically Detects Bugs in C Code * [http://www.faqs.org/docs/artu/ The Art of Unix Programming]: [http://www.faqs.org/docs/artu/ch01s06.html Rules] * [http://www.wlug.org.nz/MakefileHowto MakeFile Howto] | [http://developer.kde.org/documentation/other/makefile_am_howto/en/index.html MakeFile.am Howto] | [http://www.opussoftware.com/tutorial/TutMakefile.htm MakeFile Tutorial] | [http://trac.enlightenment.org/e/wiki/AutotoolsIntegration Autotools Integration] * [http://www.pldaniels.com/c-of-peril/c-of-peril.pdf C of Peril]: some wrong (buggy prone) things on C (or more exactly, functions) * [http://www.iso-9899.info/wiki/C_gotchas C Gotchas]: ''Why not...'' things on C, common questions from new users