C Tips

From ComputingWiki

Jump to: navigation, search
  • Go Back
  • The inline keyword. Declaring a function as inline tells the compiler to not treat the function as a function, i.e. don't use a function call. Using inline is (almost) equivalent to cutting and pasting the function code wherever it is called. Function calls take time, so inlining small functions will often make your program run faster. However, you don't want to use inline for large functions since this will increase the executable size and may actually cause your program to run slower.
    • Example:
#include <stdio.h>

inline void print_num(int num) {
     printf("%d\n", num);
}

int main(int argc, char *argv[]) {

     int i;

     for(i = 0; i < 10; ++i)
          print_num(i);
          
     for(i = 9; i >= 0; --i)
          print_num(i);

     return 0;

}

    • This code is equivalent to:
#include <stdio.h>

int main(int argc, char *argv[]) {

     int i;

     for(i = 0; i < 10; ++i)
          printf("%d\n", i);
          
     for(i = 9; i >= 0; --i)
          printf("%d\n",i);

     return 0;

}

  • The register keyword. Using the keyword register before a variable type tells the compiler that you want to keep the variable in a cpu register for the life of the variable. Normally, variables are loading into and out of the register as needed. This option should be used for variables that are referenced very often.
    • The compiler treats register as a suggestion, not a demand. Sometimes it is inefficient or impossible to store the variable in a register for the entire life of the variable.
    • The variable will only be stored in the registry as the program runs. In a multitasking system like Linux, when another program is utilizing the cpu, the register variable will not stay in the register. It will be placed back in when it is time for the program to use the cpu again.
    • Example:
#include <stdio.h>

int main(int argc, char *argv[]) {

     register int i;

     for(i = 1; i < 100; ++i);
          printf("Number: %d.\n", i);

     return 0;

}

  • The prefix version of the --/++ operators. Most people don't know, but the prefix versions of the C increment/decrement operators are more efficient than the postfix versions. To understand why, let's look at how each version works:
    • i++:
  1. int temp = i;
  2. i = i + 1;
  3. return temp;
    • ++i:
  1. i = i + 1;
  2. return i;
    • Note that there is an important difference when performing assignments or passing the value as a parameter to a function. The prefix version assigns the new value of i to the left-hand side whereas the postfix version assigns the old value.
      • Example:
#include <stdio.h>

int main(int argc, char *argv[]) {

     int i, j;
     i = j = 0;

     printf("%d %d\n", ++i, j++);
     /* Prints: 1 0 */
   
     return 0;

}
  • Using constant pointers for call-by-value parameters. This improves performance. When you use a call-by-value parameter, a copy of the variable is created for use by the local function. When you pass a pointer (i.e. a memory address), the original data itself is used, so no copy is needed. To assure that the data you pass is not changed, you should declare the parameter as a constant.
    • Example using a call-by-value parameter:
#include <stdio.h>

void double_print(int num) {
   printf("%d%d", num, num);
}

int main(int argc, char *argv[]) {
     
     int i = 100;

     double_print(i);

     return 0;

}
    • Example using a constant call-by-reference parameter:
#include <stdio.h>

void double_print(const int *num) {
   printf("%d%d", num, num);
}

int main(int argc, char *argv[]) {

     int i = 100;

     double_print(&i);

     return 0;

}
  • The EXIT_SUCCESS and EXIT_FAILURE constants. For many programs, the exit code 0 is used to mean success and the exit code 1 is used to mean failure. To make the exit codes more meaningful to those reading the code, the constants EXIT_SUCCESS and EXIT_FAILURE should be used. They are defined in <stdlib.h>. They are merely defined as 1 and 0.
    • Example:
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[]) {

     printf("Well, this program worked fine.\nI guess that I'll exit with the code 0.\n");

     return EXIT_SUCCESS;

}

  • The MEMWATCH macro. This monitors your program for memory leaks. It will only work if your program exits cleanly.
    • Example:
gcc -DMEMWATCH myprog.c
  • Looking up a function's man page from vi or vim. When editing a c source file in vi, move the cursor over the function name and type K. This will bring up the man page for that function.
  • Commenting out code. Commenting out code that you don't want to run using c-style comments (e.g. /* this */) can cause problems. For instance, if there are comments within that block, the commented out portion will quit being considered a comment when it reaches a '*/'. 'If' statements in c syntax may be used, but it looks sloppy and they are hard to spot when you need to uncomment out the code. For this reason, you should use macros.
    • Example:
#if 0
  int i_do_not_want_this_to_run;
#endif
Personal tools