The good news is that C syntax is almost identical to that of C++. However, there are many things you're used to that aren't available in C:
new
and delete
<< >>
//
comment character
/* this is a comment */ /* This is a multiline comment */You cannot nest comments.
/* This is /*nested */ comment. And is illegal. */
#include <stdio.h> int main() { printf("Hello World"); }printf() has a variable number of arguments, the first of which is a format string. The format string can contain both ordinary characters (what you want to appear on the screen like 'Hello World' above) and conversion character sequences. You can think of conversion characters as placeholders for a specific type formatted in a particular way. Conversion character sequences begin with % and end with a conversion character. An example will perhaps make this clearer. Here we're printing out the integers from 0 to 9.
int i; for (i = 0; i < 10; i++) { printf("the variable 'i' is: %d", i); }The conversion sequence is %d, which you can think of as a placeholder for an integer. Since this is the first conversion character sequence, the value of the first argument after the format string--in this case the value of 'i'-- will be placed in the held spot. Conversion characters can specify type, precision, and all sorts of other formatting information. See K&R or the man pages for all the gory details, but here are essential ones cribbed from K&R:
sequence type : produces %d or %i - int : signed decimal notation %s - char * : prints characters until the null character is reached %x - int : hexidecimal notation %p - void * : prints as a pointer
printf() always prints to standard out. If you want to print to another place, such as standard error, use fprintf() which takes as its first argument the stream you're printing on:
fprintf(stderr, "Fatal Error #2212. We're hosed"); /* or with values */ fprintf(stderr, "Fatal Error in foo(): value of bar is %p\n", bar);Note that we're calling standard in, out, and error slightly different names than we do in C++:
C++ C cin stdin cout stdout cerr stderrFinally, fputs() will also allow us to write to a stream.
int fputs(const char *str, FILE *stream);fputs() takes a null-terminated string 'str' and writes it to 'stream'. It omits the null character when it does this. It returns a non-negative integer if okay and EOF on error. An example:
if ( (fputs("Hello world", stdout)) == EOF) { fprint(stderr, "Whoops, something went wrong"); }fputs() functions similarly to printf() when it writes to stdout, but it doesn't do any conversion which probably means it's quite a bit faster.
char *fgets(char *buffer, int size, FILE *stream);fgets() reads up to size-1 characters from stream and stores them in buffer. fgets() stores the null character ('\0') after the last character read into the buffer and returns 'buffer' if everything works fine, or NULL on error or end of file. Here's an example:
char *cptr; char buffer[256]; printf("Enter some stuff:\n"); cptr = fgets(buffer, 256, stdin); if(cptr != NULL) { printf("You typed : %s\n", cptr); }Here's a more complicated example. Readline() uses fgets() to read up to MAX_LINE - 1 characters into the buffer 'in'. It strips preceding whitespace and returns a pointer to the first non-whitespace character.
char *Readline(char *in) { char *cptr; if (cptr = fgets(in, MAX_LINE, stdin)) { /* kill preceding whitespace but leave \n so we're guaranteed to have something*/ while(*cptr == ' ' || *cptr == '\t') { cptr++; } return cptr; } else { return 0; } }
new
and
delete
in C. All memory allocation is done with the
function malloc(). Here's its prototype:
void * malloc(int nbytes)malloc() takes an int indicating the number of bytes you want allocated and it returns a void pointer to the start of the allocated memory.
/* We're going to allocate enough space for an integer and assign 5 to that memory location */ int *foo; /* malloc call: note the cast of the return value from a void * to the appropriate pointer type */ foo = (int *) malloc(sizeof(int)); *foo = 5;Even more complicated structures like arrays are allocated through malloc():
/* Here we're allocating space for 5 integers */ int *foo; foo = (int *) malloc(sizeof(int) * 5); foo[0] = 17; foo[4] = 22;Freeing memory is done with the function free(). The prototype:
void free(void *);Here's an example of it being used:
free(foo);Pretty simple. However, note that it's disastrous to free a piece of memory that's already been freed.
More information is available in the man pages.
for(int i = 0; i < 200; i++) {Forgetting that you can't declare variables just anywhere is one of the most frequent causes of 'it won't compile' problems for programmers moving from C++ to C.
#define MAX_LEN 1024 #define NUM_CALLS 20This is also valid C++ code, though the use of #define is usually discouraged in C++. Like all preprocessor directives, #defines usually appear at the top of the source file.
struct
:
struct point { int x; int y; };You would then use it like so:
struct point p; p.x = 0; p.y = 0;While this is acceptable, the preferred approach is to use pointers when using structures:
struct point *p; p = (struct point *) malloc(sizeof(struct point)); p->x = 0; p->y = 0;The struct qualifier is required any time you're referring to a struct. You can see this above in the cast of the return value from malloc() and in the sizeof expression. In other words, having declared the struct point, we can't simply write:
/* this code won't work */ point p; p.x = 0;as we would with a C++ class. We can get rid of this repetition of the struct qualifier by using typedefs. The
typedef
keyword essentially creates an alias. Thus we can typedef struct
point to Point (or to lowercase 'point', but we're using uppercase to
remind ourselves it's a struct).
typdef struct point Point; Point *p; p = (Point *) malloc(sizeof(Point); p->x = 0;
bool
keyword in C. Instead booleans in C are
the same as integers with a value of 0 for false or 1 for true. Thus
the following is an infinite loop:
while(1) { ; /* do nothing */ }
#include <stdlib.h> #include <string.h>This is similar to C++ but the .h is required.
Here are some of the most useful C libraries:
int *(*foo[20]) (char *c);It also has a pretty good description of program memory.
gcc -o llist llist.cor:
g++ -o llist llist.ccI've also written a makefile that will compile both programs. Just save it to the same directory as the source files and type 'make' at the command prompt.