You are on page 1of 8

Differences Between Java and C/C++

#1
Apr 17th, 2005

Differences Between Java and C/C++

The Preprocessor

Pointers

Structures and Unions

Functions

Multiple Inheritance

Strings

The goto Statement

Operator Overloading

Automatic Coercions

Variable Arguments

Command-Line Arguments

It is no secret that the Java language is highly derived from the C and C++ languages.
Because C++ is currently considered the language of choice for professional software
developers, it's important to understand what aspects of C++ Java inherits. Of possibly
even more importance are what aspects of C++ Java doesn't support. Because Java is an
entirely new language, it was possible for the language architects to pick and choose which
features from C++ to implement in Java and how.

The focus of this appendix is to point out the differences between Java and C++. If you
are a C++ programmer, you will be able to appreciate the differences between Java and
C++. Even if you don't have any C++ experience, you can gain some insight into the Java
language by understanding what C++ discrepancies it clears up in its implementation.
Because C++ backwardly supports C, many of the differences pointed out in this appendix
refer to C++, but inherently apply to C as well.

The Preprocessor

All C/C++ compilers implement a stage of compilation known as the preprocessor. The C++
preprocessor basically performs an intelligent search and replace on identifiers that have
been declared using the #define or #typedef directives. Although most advocates of C++
discourage the use of the preprocessor, which was inherited from C, it is still widely used by
most C++ programmers. Most of the processor definitions in C++ are stored in header files,
which complement the actual source code files.

The problem with the preprocessor approach is that it provides an easy way for
programmers to inadvertently add unnecessary complexity to a program. What happens is
that many programmers using the #define and #typedef directives end up inventing their
own sublanguage within the confines of a particular project. This results in other
programmers having to go through the header files and sort out all the #define and
#typedef information to understand a program, which makes code maintenance and reuse
almost impossible. An additional problem with the preprocessor approach is that it is weak
when it comes to type checking and validation.

Java does not have a preprocessor. It provides similar functionality (#define, #typedef, and
so on) to that provided by the C++ preprocessor, but with far more control. Constant data
members are used in place of the #define directive, and class definitions are used in lieu of
the #typedef directive. The result is that Java source code is much more consistent and
easier to read than C++ source code. Additionally, Java programs don't use header files;
the Java compiler builds class definitions directly from the source code files, which contain
both class definitions and method implementations.

Pointers

Most developers agree that the misuse of pointers causes the majority of bugs in C/C++
programming. Put simply, when you have pointers, you have the ability to trash memory.
C++ programmers regularly use complex pointer arithmetic to create and maintain
dynamic data structures. In return, C++ programmers spend a lot of time hunting down
complex bugs caused by their complex pointer arithmetic.

The Java language does not support pointers. Java provides similar functionality by making
heavy use of references. Java passes all arrays and objects by reference. This approach
prevents common errors due to pointer mismanagement. It also makes programming easier
in a lot of ways simply because the correct usage of pointers is easily misunderstood by all
but the most seasoned programmers.

You may be thinking that the lack of pointers in Java will keep you from being able to
implement many data structures, such as dynamic arrays. The reality is that any pointer
task can be carried out just as easily and more reliably with objects and arrays of objects.
You then benefit from the security provided by the Java runtime system; it performs
boundary checking on all array indexing operations.
Structures and Unions

There are three types of complex data types in C++: classes, structures, and unions. Java
only implements one of these data types: classes. Java forces programmers to use classes
when the functionality of structures and unions is desired. Although this sounds like more
work for the programmer, it actually ends up being more consistent, because classes can
imitate structures and unions with ease. The Java designers really wanted to keep the
language simple, so it only made sense to eliminate aspects of the language that
overlapped.

Functions

In C, code is organized into functions, which are global subroutines accessible to a program.
C++ added classes and in doing so provided class methods, which are functions that are
connected to classes. C++ class methods are very similar to Java class methods. However,
because C++ still supports C, there is nothing discouraging C++ programmers from using
functions. This results in a mixture of function and method use that makes for confusing
programs.

Java has no functions. Being a purer object-oriented language than C++, Java forces
programmers to bundle all routines into class methods. There is no limitation imposed by
forcing programmers to use methods instead of functions. As a matter of fact, implementing
routines as methods encourages programmers to organize code better. Keep in mind that
strictly speaking there is nothing wrong with the procedural approach of using functions; it
just doesn't mix well with the object-oriented paradigm that defines the core of Java.

Multiple Inheritance

Multiple inheritance is a feature of C++ that allows you to derive a class from multiple
parent classes. Although multiple inheritance is indeed powerful, it is complicated to use
correctly and causes many problems otherwise. It is also very complicated to implement
from the compiler perspective.

Java takes the high road and provides no direct support for multiple inheritance. You can
implement functionality similar to multiple inheritance by using interfaces in Java. Java
interfaces provide object method descriptions but contain no implementations.

Strings
C and C++ have no built-in support for text strings. The standard technique adopted
among C and C++ programmers is that of using null-terminated arrays of characters to
represent strings.

In Java, strings are implemented as first class objects (String and StringBuffer), meaning
that they are at the core of the Java language. Java's implementation of strings as objects
provides several advantages:

The manner in which you create strings and access the elements of strings is
consistent across all strings on all systems

Because the Java string classes are defined as part of the Java language and not
part of some extraneous extension, Java strings function predictably every time

The Java string classes perform extensive runtime checking, which helps eliminate
troublesome runtime errors

The goto Statement

The dreaded goto statement is pretty much a relic these days even in C and C++, but it is
technically a legal part of the languages. The goto statement has historically been cited as
the cause for messy, impossible to understand, and sometimes even impossible to predict
code known as "spaghetti code." The primary usage of the goto statement has merely been
as a convenience to substitute not thinking through an alternative, more structured
branching technique.

For all these reasons and more, Java does not provide a goto statement. The Java
language specifies goto as a keyword, but its usage is not supported. I suppose the Java
designers wanted to eliminate the possibility of even using goto as an identifier! Not
including goto in the Java language simplifies the language and helps eliminate the option
of writing messy code.

Operator Overloading

Operator overloading, which is considered a prominent feature in C++, is not supported in


Java. Although roughly the same functionality can be implemented by classes in Java, the
convenience of operator overloading is still missing. However, in defense of Java, operator
overloading can sometimes get very tricky. No doubt the Java developers decided not to
support operator overloading to keep the Java language as simple as possible.

Automatic Coercions
Automatic coercion refers to the implicit casting of data types that sometimes occurs in C
and C++. For example, in C++ you can assign a float value to an int variable, which can
result in a loss of information. Java does not support C++ style automatic coercions. In
Java, if a coercion will result in a loss of data, you must always explicitly cast the data
element to the new type.

Variable Arguments

C and C++ let you declare functions, such as printf, that take a variable number of
arguments. Although this is a convenient feature, it is impossible for the compiler to
thoroughly type check the arguments, which means problems can arise at runtime without
you knowing. Again Java takes the high road and doesn't support variable arguments at
all.

Command-Line Arguments

The command-line arguments passed from the system into a Java program differ in a
couple of ways from the command-line arguments passed into a C++ program. First, the
number of parameters passed differs between the two languages. In C and C++, the
system passes two arguments to a program: argc and argv. argc specifies the number of
arguments stored in argv. argv is a pointer to an array of characters containing the actual
arguments. In Java, the system passes a single value to a program: args. args is an array
of Strings that contains the command-line arguments. In C and C++, the command-line
arguments passed into a program include the name used to invoke the program. This name
always appears as the first argument and is rarely ever used. In Java, you already know
the name of the program because it is the same name as the class, so there is no need to
pass this information as a command-line argument. Therefore, the Java runtime system
only passes the arguments following the name that invoked the program.

Java and C::


Java
Java is an object oriented programming language, it uses the concepts of Classes,
Objects, Inheritance, Polymorphism. And the execution of a program is non-linear.

Java's motto (so to speak) is "write once run anywhere".


When you compile a Java program, an intermediate bytecode is generated, which
itself is interpreted by the Java Virtual Machine.
This way you write a program once, and the virtual machine translates the bytecode
into instructions a specific processor can understand.
Execution of a Java program is by consequence a bit slow, because the intermediate
bytecode has to be interpreted.

Java uses a "Garbage Collector" which manages memory automatically so the


programmer doesn't have handle that.

Variables in Java can be declared anywhere in a program. (Although it is


recommended to declare/define them at the beginning of blocks).

C
C uses concept of structures (not object oriented).
In C we use the concept of pointers whereas there are no pointers used in JAVA
In C the programmer need to manage memory manually, lookup "malloc".
In C the declaration of variables should be on the beginning of the block.
C supports go to statement, struct and union unlike Java
C is compiled to the machines "native language" so it's execution is much faster
than Java's

Differences between C and Java.


C++ was built on C, and C remains as a subset of C++. The designers of Java wanted it to be
easily learned and used by experienced programmers, so they made it like C++--if you have had
five years experience writing C++ programs, using Java is a just no problem, although there are
new ideas and differences. So, there is a great deal in common between C and Java. Most of the
material in the first four chapters of Kernighan and Ritchie differs only in small details from
Java. The purpose of this note is to outline and explain the similarities and differences.
When you program, you use two things. There is the language, and there is the library of
functions. You need the library. All the input and output, including printing, is in the library.
Math functions are in the library. If you use windows and gui, the supporting functions are in the
library. C, C++, and Java languages are very similar. The libraries are quite different. C has a
standard library, and it is available in C++, but the C++ standard library is not available in C, of
course. The Java library is very different from both the C and the C++ standard libraries. Thus, in
particular, the statements for displaying things on the screen are very different for C and C++ and
Java. In C you will use printf() most commonly. However, you won't really need to know about
that function until Assignment 3.
Program and function format:
In C there are no classes, and no public and private. The keyword "static" is in C, but not so often
used--for now, don't use it. Later we will see where it comes in. You can see the basic form of a
program from the "Hello, World" program and the prime number example below. Functions are
declared pretty much in the same way as in Java. Put the function definitions in before where the
functions are used--I will explain later how to get around that if you want to. Recursion is OK in
C and C++, and Java.
Data types:
See the notes on "Binary, Decimal, Hex, and Ascii". Data types are pretty much the same in C as
in Java. However, a char in C is treated like a small integer--you can use it in arithmetic
expressions. There is no separate string data type in C. Strings are put in arrays of characters,
with a zero byte (0 or '\0') after the last character to mark the end. There is detail on this in
Chapter 5, and we will go over it very carefully. The escape characters (like \n for new line) on
pages 37-39 are in Java, just as they are in C and C++. There isn't any Boolean data in C. Usually
you use integers. In logical expressions, zero is false and anything non-zero is true. Logical
expressions (made with && and || and !) have the value 0 if false, 1 if true.
Comments:
C uses /* comments */. // Comments are added in C++. Some C compilers will accept them.
# Statements:
Statements starting with a # are instructions to the preprocessor. There is some material on the
preprocessor at the end of Chapter 4 of K&R. #include <file.h> simply inserts the file "file.h"
into the program. It is used to include information about functions and data that are not in this
file, e. g. library functions, and thus it plays a role similar to but not the same as the import
statement in Java. Use #include <file.h> for library includes and #include "file.h" for include
files that you make (i. e. include files that are in your own directory). I will give more detail on
using #include in the second lecture. #define defines constants and macros. I often put #define T
1 and #define F 0 in my programs, and then I can use T to mean true and F to mean false. The
preprocessor makes the substitution. You should read about more complicated defines but in
general it is better not to use them unless you really enjoy debugging programs with difficult
bugs--they are error prone. They are frowned upon by devout C++ programmers. Read about the
other preprocessor statements, but I don't recommend using them in general.
Bitwise operators:
These operators, &, |, ^, and ~, are the same as in Java, but it is likely that you haven't seen them.
I will give you some notes on masking which show some common uses of these, and we will use
them in a couple of the assignments.
go to statements:
They don't exist in Java. In current good programming style, they aren't used. I recommend that
you simply don't use them until you have had at least 5 years experience working as a
programmer--you never need them.
An Example: Prime Numbers
/* This C program will find the first 1000 prime numbers. */
/* WP 9/97 */
#include <stdio.h>
int p[1000]; /* The list of primes */

/* This function returns true if n is prime, false


if not. It checks whether n is divisible by any
prime number less than or equal to the square
rootof n. If not, n is prime.
This algorithm can test any 32-bit number in a
small fraction of a second, if all the 16-bit or
smallerprimes are in the table. */
int primetest(int n)
{
int i = 0;
while(p[i]*p[i]<n && n%p[i] != 0) i++;
return (n%p[i] != 0); /*this is true if n is prime
andfalse if not */
}

/* The main program simply tests all integers, starting


with 3, and puts the primes into an array until there
are 1000 numbers in the array. Then it prints them.
The tricky part about this program is that when it
starts, there is only one prime in the table, 2.
However, when you get to n, all the primes less
thann will be in the table, so it works OK. */
void main()
{
intn = 3; /*next number to test */
int np= 1; /*the number of primes so far */
p[0] = 2; /*the first prime */
printf("Table of Prime Numbers\n");
while(np<1000) {
if(primetest(n)) {
p[np] = n;
np++;
}
n += 2; /*next odd number */
}
for(n = 0; n<np; n++) {
printf("%d", p[n]);
if(n%10==9) printf("\n");
else printf("\t");
}
}

You might also like