[Phy 405/905 Home Page] [ Lecturer ]
Last time I tried to sneak in the idea of the many basic types in C++ by talking about the (not so) many types of literals. It's not that the number of types is confusing, it's actually the automatic conversions between them that is both confusing and usually very convenient (when combined with type-safety for function arguments). So, we'll just plunge into the topic, and emerge on the other side with an idea of how things'll be for classes. On the way, we'll mention the difference between declaration and definition of objects, derived types (types built out of the fundamental types) and incidentally show how to declare and define functions the type-safe way.
Integers - {short int, int, long int} of possibly increasing sizes which may be qualified by {signed,unsigned}, where signed is the default, and an unsigned vs. signed int takes up the same space. The type "int" is supposed to be "natural" for the particular machine. The size in bytes of each type (any type, actually) can be gotten through the sizeof() operator:
cout << sizeof(char)<<"\n"; // outputs '1'The different sizes are not guranteed to be different, only properly ordered: sizeof(int) <= sizeof(long int).
A short-hand notation (which is a bad habit) is possible, of dropping the "int" for any of the qualified int types: unsigned int -> unsigned, signed long int -> signed long. This is behavior is implemented just to conform to ANSI C code.
Finally, the unsigned int types are often used as multi-bit flags; being unsigned, all n=8*sizeof( whatever int) bits are available for use, and arithmetic is mod 2^n, with no overflow. Good for, for example, data encryption.
Floating point numbers - {double, float, long double}
Characters - {char, signed char, unsigned char}. The type char always signifies the type of character (signed or unsigned) appropriate to the machine for which the program is being compiled. For physics programming you might not have too much to do with the other two types. All three take up the same space
Then there are all the other derived types that are - you guessed it - derived from the fundamental types, including arrays, pointers, constants, ..., classes (our eventual goal), structures,... and functions. You're familiar with arrays, possibly with pointers, but it is curious to think of a function of given argument(s) type and return value type as a type in and of itself; but there you have it, that's what's behind function overloading.
Now, to put all the above to any practical purpose, - to use an object, for example, a variable of type double, in a program - we must first name it (my_sqrt, or x, or ...). The same is true of functions as well. The same is true of types, templates, and other entities, but we'll concentrate for the moment on {functions,objects}= {lvalues}. Don't forget that objects include not just the fundamental types described above, but all the derived types (excepting functions).
There are two basic steps needed to make a name available for use in a program:
// my_prog.ccThe syntax for objects is quite easy and apparent from this example.
int main()
{
int i; //declaration and definition
int j=4; // declaration and definition and initialization
}
// program showing scope
#include <iostream.h>
// declare/define some variables with file scope
int j=4.0; // initialization!
int i; // main() which defines its own local scope
int main()
{
i=4; // global i
int i=3; // local scope i, hides previous one
cout <<"j: "<<j<<" global i"<<::i<<" local i "<<i<<'\n';
{ // new local scope
char i= 'd';
cout <<"nested i:"<<i<<" global i:"<<::i<<'\n';
}
}
You should copy this into a file and try it out (and check out the exercises, once I get them written).
[ Phy 405/905 Home Page] [Lecturer ]