topics memory alignment and structures typedef for struct names bitwise & for viewing bits...
TRANSCRIPT
Topics
memory alignment and structures typedef for struct names bitwise & for viewing bits malloc and free (dynamic storage in C) new and delete (dynamic storage in C++)
Memory allocation
How many bytes does this structure require?
struct malign {
char c; /* char = 1 byte */
double d; /* double = 8 bytes */
};
int main(int argc, char *argv[]) {
struct malign x;
// char: x.c, double x.d
printf("Size of malign is %d\n", sizeof(x) );
}
What size will be printed?
Memory Allocation, cont.
On x86 architecture, output is...
Size of malign is 12 or 16 (varies)
On SPARC (Sun) architecture, output is always...
Size of malign is 16
Memory allocation and alignment
Most computers require some data "alignment" floating point values must be aligned at word
boundaries on some machines, "double" must be aligned on even
word boundaries. Example: SPARC if you violate these rules you may get a run-time
"alignment error" and program failure problem can occur using dynamic memory and casts
1 word = 4 bytes
c
0 1 2 3 4 5 6 7 8 9 10 11 12 . . .
x
1 double word = 8 bytes
Memory re-alignment
Even if we change the struct like this:struct better {
double x; // put double firstchar c; // char is easy to align } a;
it still uses 16 bytes. Why? reason: you can create array of struct using:
struct better big[80];
compiler ensures all array elements are aligned.
c
0 1 2 3 4 5 6 7 8 9 10 11 12 . . .
x
1 double word = 8 bytes char = 1 byte
Why do we have to write "struct" ?
In C, you have to write "struct" a lot
struct node {char data[80];struct node *next;
};int main( ) {
struct node top;struct node *ptr;ptr = (struct node *)malloc(
sizeof(struct node));top.next = ptr;
This is boring! The compiler should know that "node" is a struct.
C "typedef" to alias struct name
In C, a "typedef" can be same name as a struct ...
typedef struct node node; /* define "node" := "struct node" *//* typedef creates an alias */
struct node {char data[80];node *next;
};int main( ) {
node top;node *ptr;ptr = (node *)malloc(sizeof(node));top.next = ptr;
C++ provides automatic "typedef"
C++ automatically creates a typedef for every named structure:
struct node {char data[80];node *next;
};int main( ) {
node top;node *ptr;ptr = (node *)malloc(sizeof(node));top.next = ptr;
This is nicer! Compile your C programs with C++ compiler and save some typing.
Viewing contents of memory
To learn details of data formats, sometimes it is helpful to see how the computer really stores a data value.
How does computer store (int) -9 or (float)1.1E3 ? In C we can do this using a union and bitwise
operators to select individual bits.
Memory "union"
A union defines multiple variables that occupy the same storage!
union share {
float f;
int i;
} ;
int main(int argc, char *argv[]) {
union share x;
// x.f is a float, x.i is an int
// but they share the same memory
printf("Size of x is %d\n", sizeof(x) ); //=4
Bitwise and (&)
bitwise and of 2 quantities
a = 0000111101
b = 0001010011
a&b = 0000010001 & is used to test individual bits in storage:
a = 0000111101
mask = 0000000001 mask = 0000000010
a&mask = 0000000001 a&mask = 0000000000
unsigned int mask = 1;for(k=0; k<8*sizeof(a); k++) {
if (a & mask) printf("1"); else printf("0");mask = mask*2; // shift mask bit, like mask<<1
}
Viewing all the bits (1)
use bitwise AND with a mask to view each bit. Idea:
set mask=0000000001 and test the lowest bit. shift mask to the left and test the next bit. continue until you test all the bits.
Example:
float a = 3.5E11;unsigned int mask = 1;for(k=0; k<8*sizeof(a); k++) {
if (a & mask) printf("1"); else printf("0");mask = mask*2; // shift mask bit, like mask<<1
}
Viewing all the bits (2)
C compiler doesn't allow (a & mask) for a of type float. So, union a with an unsigned int. Example:
union {float f;unsigned int ui;} both;
both.f = 3.5E11;unsigned int mask = 1;for(k=0; k<8*sizeof(both); k++) {
if (both.ui & mask) printf("1"); else printf("0");mask = mask*2; // shift mask bit
}
Dynamic Memory Allocation
Most languages allow dynamic memory allocation. Old languages such as Fortran, COBOL do not. At run-time, allocate new storage using:
new : Java, C++, C# malloc : C library routine
You also need a way to free storage you don't need any more.
Dynamic Memory Allocation
C or C++: use malloc and free
#define SIZE 1000char *p;p = (char *)malloc(SIZE * sizeof(char));if (p == 0) fprintf(stderr,"malloc failed\n");/* ...do something with p */free(p);
C++: new and delete
const int SIZE = 1000;char *p;p = new char[SIZE];if (p == 0) fprintf(stderr,"new failed\n");/* ...do something with p */delete [ ] p;
Dynamic allocation of user types
malloc and new can allocate memory for complex data types or user-defined structures and classes
struct node {char data[80];node *next;
};int main( ) {
node *ptr;ptr = new node; // hey! no cast needed
Important: don't use "new" and "malloc" in the same program. They manage heap space independently.
malloc and free
// storage allocation using malloc and freeconst int ASIZE = 1000;float *xp;int *ip;xp = (float *) malloc( sizeof(float) );ip = (int *) malloc( ASIZE*sizeof(int) ); /* array */if ( ip == null ) { /* memory allocation failed */ }else { ip[0] = ip[1] = 1; } /* can use array syntax *//* vars allocated with "malloc" must be deallocated with "free" */free(xp); // free one variablefree(ip); // free entire block
malloc and free are C library functions for dynamic memory alloc. malloc doesn't initialize memory (may contain garbage) free doesn't reset the pointer to null -- do it yourself.
new and delete
// allocate storage with newconst int ASIZE = 1000;float *xp;int *ip;xp = new float(3.14159); /* initialize value */ip = new int[ ASIZE ];if ( ip == null ) { /* memory allocation failed */ }else { ip[0] = ip[1] = 1; } /* use array syntax *//* vars allocated with "new" must be deallocated with "delete" */delete xp; // free one variablesdelete [ ] ip; // free array
new and date are C++ built-in commands for dynamic memory new initializes memory to default or your value delete doesn't reset the pointer to null -- do it yourself.
new throws bad_alloc exception
ANSI Standard C++ throws an exception if "new" fails.
// allocate storage with newconst int ASIZE = 1000;int *ip;try {
ip = new int[ ASIZE ];} catch( bad_alloc exception ) {
cout << "Memory allocation failed." << endl;}