Originally published by Robert Beisert at fortcollinsprogram.robert-beisert.com

Linux + C – Formatting

At this point, we’ve written and compiled a few C programs, and I’m sure you’re already noticing the patterns. Still, it sometimes helps to have these patterns clearly defined.

One Line

When we talk about a line of code, we don’t necessarily mean one physical line on the page. A line of code is one logical block, which performs one task. As such, a line of code can span a lot of white space. For example, this is legal:

char
            *
    pandas 


                        =
'a'
    
    
    ;

Every logical block ends with one of two things:

  • a semicolon (;) which indicates that the action is done
  • an open bracket ({), which indicates that a block of code follows

The following examples are the most common uses of semicolons and brackets:

int x = y + z;
for (x=0; x < 3; x++);
for (x=0; x < 3; x++) {}
for (x=0; x < 3; x++) { BLOCK OF CODE }
struct apple { BLOCK OF DATA ELEMENTS };
struct pear { BLOCK OF DATA ELEMENTS } pear;
int cut_apple(struct apple, int slices);
int cut_apple(struct apple, int slices) { BLOCK OF CODE }
{ BLOCK OF CODE}
;;

It is CRITICAL that you close all of your braces properly. This means that:

For every (, there must be a )
For every {, there must be a }
For every [, there must be a ]

Otherwise, in the best case scenario, the program won’t compile. In the worse case scenario, the program will compile, but it won’t work right at all.

NOTE: If you don’t end a line properly, the program will not compile, and you WILL have a bad time. Make sure you understand this stuff.

FUNCTIONS

Every program which does something (read: all programs) is built on functions. In our previous code examples, we have used functions like printf() and rand(), which perform pre-defined tasks.

However, we have also defined a function of our own: main(). This function performs the primary operations of the program, and EVERY PROGRAM compiled in C MUST contain one main() function.

Functions have three primary components:

A name
A set of arguments
A return type

The name of the function distinguishes it from other functions or variables. For example, the name of printf() is…printf.
Every program requires a set of arguments – data elements which act as input to a function. These arguments go inside the parentheses (), and are the only outside data that the function can access. For example, the pow() function takes two doubles (the base and the exponent) as arguments. It is essential that we fill every argument to a function, though we can define a function such that it doesn’t need arguments (like rand()).
Finally, every function has a return type – a data type which describes the element that a function generates at the end. This data type can be anything we’ve defined – a structure, a char, an int, a double, or even a void (empty element with no size or value).

The format for a function is one of the following:

RETURN_TYPE NAME (ARGUMENT 1, ARGUMENT 2, …, ARGUMENT N) { BLOCK OF CODE }
RETURN_TYPE NAME (ARGUMENT) { BLOCK OF CODE }
RETURN_TYPE NAME () { BLOCK OF CODE }

The format for an argument is:

ARGUMENT_DATA_TYPE ARGUMENT_NAME

where the data type can be a structure or a simple data type and the name is unique within the function.

FILES

There are two kinds of files we concern ourselves with in C: headers and code. Header files end in *.h, and code files end in *.c. (Note: the * is a UNIX symbol which can replace any amount of text.)

Code files contain the meat of our programs. We define all the functions here, after all. Every program we’ve written up to this point has been composed of a simple .c file.

Header files contain references which other code files can use. For example, we often put structures, global variables, and constants in header files, so that multiple code files can work together. More importantly, we put function prototypes – the name of a function with its arguments and return type, but no code – into the header files. Without these function prototypes, you can’t build code which calls the functions you defined in another code file.

Excellent example: the header file <stdio.h> contains the function prototype for printf(). The actual code for printf() exists in stdio.c, which has been compiled into a library. Since we can’t (and don’t want to) copy all the code for printf() into every program we write, we simply #include <stdio.h>, and the compiler does the hard work for us.

NOTE: It is extremely important that the function prototypes in a header file are IDENTICAL to the functions in the code file. Otherwise, you are telling the user of the header the WRONG way to use the function, which is always a bad thing.

 

 

That’s all the formatting we’ve covered up to this point. If you want to create programs of your own, instead of just tweaking the ones other people have written, these are the things you need to understand.