Syntax & Practical Differences between C and Java

In the next few chapters, we’ll cover syntactical and practical differences between C and Java. None of these are particularly difficult to master, but you will need to get used to them.

Comments

Comments work the same way they do in Java, using // for a single-line comment, or /* and */ for a multi-line comment. Since Javadoc is a Java tool, there is no need to make formal Javadoc comments. (However, it is always good practice to give your functions in-depth comments that explain their use.)

y = f(x);   // this is a comment
y = f(2);   /* this is also a comment */

/* I'm a mult-line
   comment */

Including Libraries in C

C’s equivalent to Java’s import statements are #include statements, that tell the compiler where to find standard C functions that you haven’t defined yourself.

For example, the first line of many C programs is:

#include <stdio.h> 

This indicates that the compiler should include C’s standard input/output library, including useful functions such as printf() (which is described below). Notice that the line starts with a hashmark, and has no semicolon at the end. This is because it is technically a preprocessor directive, or a step that should be followed before we begin the actual compilation. We will encounter this again when we define constants.

Preprocessor directives are a way of making text processing with your C program before they are actually compiled. Before the actual compilation of every C program it is passed through a Preprocessor. The Preprocessor looks through the program trying to find out specific instructions called Preprocessor directives that it can understand. All Preprocessor directives begin with the # (hash) symbol. C++ compilers use the same C preprocessor. The preprocessor is a part of the compiler which performs preliminary operations (conditionally compiling code, including files etc…) to your code before the compiler sees it. These transformations are lexical, meaning that the output of the preprocessor is still text.

Other common libraries that your program might include are shown in Table 1. These .h files are called “C header” files, and they are used to compile together source code from multiple files into one working executable program. Advanced C programmers often make their own .h files, allowing a program’s source code to be spread among multiple .c files.

Header File Use Example
stdio.h standard input/output printf(), scanf()
stdlib.h common “standard library” functions malloc()
string.h string manipulation functions strlen(), strcmp()
math.h common math sqrt(), sin(), log()
time.h system time & random numbers time(), rand()

Table 1: Common Header Files. These are some of the .h files commonly used in an #include directive at the beginning of a C file. There are many more, and advanced C programmers often make their own.

Functions & Prototypes

Like in Java, a function is a self-contained area of code to perform some task, and they are the basic building blocks of a program. Because C has no classes, there’s absolutely no need to make a class block to contain the functions, like one does in Java. Further, it is incorrect to refer to C functions as “methods”, because by definition a method is inside a class.

Instead, a C program consists mostly of the #include statements followed by prototypes (see below), and finally all of the individual functions.

Functions look very similar to they way they do in Java:

// this function takes 2 int arguments and returns an int int      
doSomeTask(int arg1, int arg2) {                                 
                                                                   
// internal code goes here                                         
                                                               
}      

However C has an important rule: a function must be defined prior to its being called. That is, one function cannot call another function that is below it in the source code, since it hasn’t been defined yet. Of course Java is different: the compiler does not care about the order in which a class’s methods are defined.

This probably seems ridiculous and frustrating to modern programmers. The reason is that it makes the compiler quicker—it allows it to read through the source code fewer times while compiling the program. Given that compiling in the old days could take a minute or even longer, this is not unreasonable!

To get around this rule, every C function should have a corresponding prototype near the top of the source code. This is a definition of how to call the function, before it is fully defined. A function’s prototype looks like its signature line, but it ends with a semicolon rather than an opening brace:

int doSomeTask(int arg1, int arg2); // prototype 

This prototype lets the compiler know how to call the function, even when it’s not defined until later in the source code. You can write a C program with no prototypes, but it’s not a good idea—a function without a prototype can only be called by functions that occur later in the source code. So, after your #include statements, there should be a master list of all your functions, one per line, followed by the function definitions themselves.

Unlike in Java, a function that takes no arguments must have the keyword void between its parentheses. This is because historically a function with nothing between its parentheses meant that the programmer wasn’t yet establishing whether or not the function took any arguments. Putting void in this position means that you are positively stating that the function has no arguments.

Variable Type Guaranteed Min Size Usual Size Usual Min Value Usual Max Value
char 1 byte 1 byte -128 127
unsigned char 1 byte 1 byte 0 255
short int 2 bytes 2 bytes -32,768 32,767
unsigned short int 2 bytes 2 bytes 0 65,535
int 2 bytes 4 bytes -2,147,483,648 2,147,483,647
unsigned int 2 bytes 4 bytes 0 4,294,967,295
long int 4 bytes 8 bytes ∼ \(−9.2 x 10^{18}\) ∼ \(9.2 × 10^{18}\)
unsigned long int 4 bytes 8 bytes 0 ∼ \(9.2 × 10^{19}\)
long long int 8 bytes 8 bytes ~ \(-9.2 × 10^{18}\) ∼ \(9.2 × 10^{18}\)
float none 4 bytes ∼ \(−3.4 × 10^{38}\) ∼ \(3.4 × 10^{38}\)
double none 8 bytes ∼ \(−3.4 × 10^{308}\) ∼ \(3.4 × 10^{308}\)
long double none 16 bytes ∼ \(−1.2 × 10^{4932}\) ∼ \(1.2 × 10^{4932}\)
void N/A N/A N/A N/A

Table 2: Basic variable types in C. Exact sizes may vary from system to system, but will be as least as big as indicated in the “Guaranteed Min Size” column.

The main() function should return an int. This int should be 0 if the program terminates normally, or nonzero (usually 1) if there was an error.

Therefore, a typical main() function might look like this:

// program starts here
int main(void) {      
   // code here          
   return 0;             
}                     

Because there are no classes in C, there are no public, private, or protected keywords. There is a static keyword, but it means something different. (It allows a local variable to persist even when it is out of scope.) C functions do not throw exceptions. The language predates their common use.

Next up, we’ll look at variables in C vs Java.


Licenses and Attributions


Speak Your Mind