190 likes | 205 Views
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 */
E N D
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 0 1 2 3 4 5 6 7 8 9 10 11 12 . . . 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 c x 1 word = 4 bytes 1 double word = 8 bytes
Memory re-alignment 0 1 2 3 4 5 6 7 8 9 10 11 12 . . . Even if we change the struct like this: struct better { double x; // put double first char 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. x c 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 1000 char *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 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. // storage allocation using malloc and free const 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 variable free(ip); // free entire block
new and delete 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. // allocate storage with new const 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 variables delete [ ] ip; // free array
new throws bad_alloc exception ANSI Standard C++ throws an exception if "new" fails. // allocate storage with new const int ASIZE = 1000; int *ip; try { ip = new int[ ASIZE ]; } catch( bad_alloc exception ) { cout << "Memory allocation failed." << endl; }