The C and C++ Programming Language Interoperability: Extra Slides
The C and C++ Programming Language Interoperability: Extra Slides
The C and C++ Programming Language Interoperability: Extra Slides
2013
Abstract
This lecture gives you the briefest introduction to C from a C++ point of view. If you need to use this language, read an introductory book (e.g. K&R). This lecture gives you a hint what to look for. C is C++s closest relative, and compatible in many areas, so much of your C++ knowledge carries over.
Overview
C and C++ Function prototypes printf()/scanf() Arrays and strings Memory management Macros const C/C++ interoperability
C and C++
In this lecture C means ISO C89
That is by far the most commonly used definition of C
Classic C has mostly been replaced (though amazingly not completely) C99 is not yet widely used
C and C++
Both defined/controlled by ISO standards committees
Separate committees
Unfortunately, leading to incompatibilities
Source compatibility
C is (almost) a subset of C++
Example of excepion: int f(int new, int class, int bool); /* ok in C */
(Almost) all constructs that are both C and C++ have the same meaning (semantics) in both languages
Example of exception: sizeof('a') /* 4 in C and 1 in C++ */
Many supported implementations in use Available on more platforms than any other languages
Link compatibility
C and C++ program fragments can be linked together in a single program
And very often are
Both primarily aimed at and are heavily used for hard system programming tasks, such as
Operating systems kernels Device drivers Embedded systems Compilers Communications systems
05.02.2013
C and C++
Here we
assume you know C++ and how to use it describe the differences between C and C++ describe how to program using the facilities offered by C
Our ideal of programming and our techniques remain the same, but the tool available to express our ideas change
C and C++
C++ is a general-purpose programming language with a bias towards systems programming that
is a better C supports data abstraction supports object-oriented programming supports generic programming
describe a few C traps and pitfalls do not go into all the details from the book
Compatibility details are important, but rarely interesting
C:
Functions and structs Machine model (basic types and operations) Compilation and linkage model
Exceptions
Use error-codes, error-return values, etc.
STL algorithms
sort(), find(), copy(), Not many alternatives use qsort() where you can Write your own, use 3rd party libraries
Function overloading
Give each function a separate name
new/delete
Use malloc()/free()
Iostreams
Use stdio: printf(), getch(), etc.
References
Use pointers
Regular expression
Use a 3rd party library
C and C++
Lots of useful code is written in C
Very few language features are essential
In principle, you dont need a high-level language, you could write everything in assembler (but why would you want to do that?)
Functions
There can be only one function of a given name Function argument type checking is optional There are no references (and therefore no pass-by-reference) There are no member functions There are no inline functions (except in C99) There is an alternative function definition syntax
Use high compiler warning levels to catch type errors Use lint for large programs
A lint is a consistency checking program
05.02.2013
Function prototypes
(function argument checking is optional)
/* avoid these mistakes use a compiler option that enforces C++ rules */ int g(int); int h(); /* prototype like C++ function declaration */ /* not a prototype the argument types are unspecified */
int f(p,b) char* p; char b; /* old style definition not a prototype */ { /* */ } int my_fct(int a, double d, char* p) /* new style definition a prototype */ { f(); /* ok by the compiler! But gives wrong/unexpected results */ f(d,p); /* ok by the compiler! But gives wrong/unexpected results */ h(d); /* ok by the compiler! But may give wrong/unexpected results */ ff(d); /* ok by the compiler! But may give wrong/unexpected results */ g(p); g(); } /* error: wrong type */ /* error: argument missing */
Arguments to be formatted
void f(double d, char* s, int i, char ch) { printf("double %g string %s int %i char %c\n", d, s, i, ch); printf("goof %s\n", i); /* uncaught error */ } Formatting characters
Format strings
Though error-prone, printf() is convenient for built-in types printf() formats are not extensible to user-defined types E.g. no %M for My_type values Beware: a printf () with a user-supplied format string is a cracker tool
C-style Strings
In C a string (called a C-string or a C-style string in C++ literature) is a zero-terminated array of characters
char* p = "asdf"; char s[ ] = "asdf";
Remember
An array does not know how long it is There is no array assignment
use memcpy()
p:
'a'
's'
'd'
'f'
s:
'a'
's'
'd'
'f'
05.02.2013
C-style Strings
Comparing strings
#include <string.h> if (s1 = = s2) { } if (strcmp(s1,s2) = = 0) { /* do s1 and s2 hold the same characters? */ } /* do s1 and s2 point to the same array? (typically not what you want) */
C- style Strings
The string copy function strcpy() is the archetypical C function (found in the ISO C standard library) Unless you understand the implementation below, do not claim to understand C:
char* strcpy(char *p, const char *q) { while (*p++ = *q++); return p; }
Copying strings
strcpy(s1,s2);
Warning: By default, Microsoft tries to force you to use safer, but non-standard, alternatives to the unsafe C standard library functions
Uncast malloc()
The major C/C++ incompatibility in real-world code
Not-type safe Historically a pre-standard C compatibility hack/feature
Always controversial
Unnecessarily so IMO void* alloc(size_t x); /* allocate x bytes in C, but not in C++, void* converts to any T* */ void f (int n) { int* p = alloc(n*sizeof(int)); /* ok in C; error in C++ */ int* q = (int*)alloc(n*sizeof(int)); /* ok in C and C++ */ /* */ }
No initialization/cleanup
malloc() does not call constructors free() does not call destructors Write and remember to use your own init() and cleanup()
There is no way to ensure automatic cleanup Do not use malloc()/free() in C++ programs
new/delete are as fast and almost always better
05.02.2013
Pointer void*
Why does void* convert to T* in C but not in C++?
C needs it to save you from casting the result of malloc() C++ does not: use new
Comments
// comments were introduced by Bjarne Stroustrup into C++ from Cs ancestor BCPL when he got really fed up with typing /* */ comments // comments are accepted by most C dialects including the new ISO standard C (C99)
const
// in C, a const is never a compile time constant const int max = 30; const int x; // const not initialized: ok in C (error in C++) void f(int v) { int a1[max]; // error: array bound not a constant (max is not a constant!) int a2[x]; // error: array bound not a constant (here you see why) switch (v) { case 1: // case max: // error: case label not a constant // } }
Beware of Macros
#include "my_header.h" // int max(int a, int b) { return a>=b?a:b; } // error: obscure error message
C/C++ Interoperability
Works because of shared linkage model Works because a shared model for simple objects
built-in types and structs/classes
As it happened my_header.h contained the macro max from the previous slide so what the compiler saw was int 30(int a, int b) { return a>=b?a:b; } No wonder it complained! There are tens of thousands of macros in popular header files. Always define macros with ALL_CAPS names, e.g. #define MY_MAX 30 and never give anything but a macro an ALL_CAPS name Unfortunately, not everyone obeys the ALL_CAPS convention
Optimal/Efficient
No behind-the-scenes reformatting/conversions
05.02.2013
int main() { record table[MAX_WORDS + 1]; int num_words = 0; char word[MAX_WORD_LENGTH + 1]; int iter; while(scanf("%" XSTR(MAX_WORD_LENGTH) "s", word) != EOF) { for(iter = 0; iter < num_words && strcmp(table[iter].word, word); ++iter); if(iter == num_words) { strncpy(table[num_words].word, word, MAX_WORD_LENGTH + 1); table[num_words++].count = 1; } else table[iter].count++; if(num_words > MAX_WORDS){ printf("table is full\n"); return EXIT_FAILURE; } } qsort(table, num_words, sizeof(record), strcmp); for(iter=0; iter<num_words; ++iter) printf("%s %d\n", table[iter].word, table[iter].count); return EXIT_SUCCESS; }
It is also C++ except that in C++, the argument to qsort() should be cast to its proper type:
(int (*)(const void*, const void*))strcmp
What are those macros doing? Maxes out at MAX_WORD words Does not handle words longer than MAX_WORD_LENGTH First reads and then sorts Inherently slower than the colloquial C++ version (which uses a map)