5.5. Sizeof and storage allocationThe #include <stdlib.h> /* declares malloc() */ float *fp; fp = (float *)malloc(sizeof(float)); The operand of #include <stdlib.h> int *ip, ar[100]; ip = (int *)malloc(sizeof ar); In the last example, the array The fundamental unit of storage in C is the sizeof(char) is equal to 1, so you could allocate space for an array of ten
malloc(10) while to allocate room for an array of ten malloc(sizeof(int[10])) If As a first illustration of the use of The example is done first using fixed size arrays, then another version uses malloc and allocates space for the strings at run time. Unfortunately, the array of pointers is still fixed in size: a better solution would use a linked list or similar data structure to store the pointers and would have no fixed arrays at all. At the moment, we haven't seen how to do that. The overall structure is this:
while(number of strings read < MAXSTRING
&& input still remains){
read next string;
}
sort array of pointers;
print array of pointers;
exit;
A number of functions are used to implement this program:
It will help to understand the examples if you remember that in an
expression, an array's name is converted to the address of its first
element. Similarly, for a two-dimensional array (such as
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRING 50 /* max no. of strings */
#define MAXLEN 80 /* max length. of strings */
void print_arr(const char *p_array[]);
void sort_arr(const char *p_array[]);
char *next_string(char *destination);
main(){
/* leave room for null at end */
char *p_array[MAXSTRING+1];
/* storage for strings */
char strings[MAXSTRING][MAXLEN];
/* count of strings read */
int nstrings;
nstrings = 0;
while(nstrings < MAXSTRING &&
next_string(strings[nstrings]) != 0){
p_array[nstrings] = strings[nstrings];
nstrings++;
}
/* terminate p_array */
p_array[nstrings] = 0;
sort_arr(p_array);
print_arr(p_array);
exit(EXIT_SUCCESS);
}
void print_arr(const char *p_array[]){
int index;
for(index = 0; p_array[index] != 0; index++)
printf("%s\n", p_array[index]);
}
void sort_arr(const char *p_array[]){
int comp_val, low_index, hi_index;
const char *tmp;
for(low_index = 0;
p_array[low_index] != 0 &&
p_array[low_index+1] != 0;
low_index++){
for(hi_index = low_index+1;
p_array[hi_index] != 0;
hi_index++){
comp_val=strcmp(p_array[hi_index],
p_array[low_index]);
if(comp_val >= 0)
continue;
/* swap strings */
tmp = p_array[hi_index];
p_array[hi_index] = p_array[low_index];
p_array[low_index] = tmp;
}
}
}
char *next_string(char *destination){
char *cp;
int c;
cp = destination;
while((c = getchar()) != '\n' && c != EOF){
if(cp-destination < MAXLEN-1)
*cp++ = c;
}
*cp = 0;
if(c == EOF && cp == destination)
return(0);
return(destination);
}Example 5.10It is no accident that
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRING 50 /* max no. of strings */
#define MAXLEN 80 /* max length. of strings */
void print_arr(const char *p_array[]);
void sort_arr(const char *p_array[]);
char *next_string(void);
main(){
char *p_array[MAXSTRING+1];
int nstrings;
nstrings = 0;
while(nstrings < MAXSTRING &&
(p_array[nstrings] = next_string()) != 0){
nstrings++;
}
/* terminate p_array */
p_array[nstrings] = 0;
sort_arr(p_array);
print_arr(p_array);
exit(EXIT_SUCCESS);
}
void print_arr(const char *p_array[]){
int index;
for(index = 0; p_array[index] != 0; index++)
printf("%s\n", p_array[index]);
}
void sort_arr(const char *p_array[]){
int comp_val, low_index, hi_index;
const char *tmp;
for(low_index = 0;
p_array[low_index] != 0 &&
p_array[low_index+1] != 0;
low_index++){
for(hi_index = low_index+1;
p_array[hi_index] != 0;
hi_index++){
comp_val=strcmp(p_array[hi_index],
p_array[low_index]);
if(comp_val >= 0)
continue;
/* swap strings */
tmp = p_array[hi_index];
p_array[hi_index] = p_array[low_index];
p_array[low_index] = tmp;
}
}
}
char *next_string(void){
char *cp, *destination;
int c;
destination = (char *)malloc(MAXLEN);
if(destination != 0){
cp = destination;
while((c = getchar()) != '\n' && c != EOF){
if(cp-destination < MAXLEN-1)
*cp++ = c;
}
*cp = 0;
if(c == EOF && cp == destination)
return(0);
}
return(destination);
}Example 5.11Finally, for the extremely brave, here is the whole thing with even
#include <stdio.h>
#include <stdlib.hi>
#include <string.h>
#define MAXSTRING 50 /* max no. of strings */
#define MAXLEN 80 /* max length. of strings */
void print_arr(const char **p_array);
void sort_arr(const char **p_array);
char *next_string(void);
main(){
char **p_array;
int nstrings; /* count of strings read */
p_array = (char **)malloc(
sizeof(char *[MAXSTRING+1]));
if(p_array == 0){
printf("No memory\n");
exit(EXIT_FAILURE);
}
nstrings = 0;
while(nstrings < MAXSTRING &&
(p_array[nstrings] = next_string()) != 0){
nstrings++;
}
/* terminate p_array */
p_array[nstrings] = 0;
sort_arr(p_array);
print_arr(p_array);
exit(EXIT_SUCCESS);
}
void print_arr(const char **p_array){
while(*p_array)
printf("%s\n", *p_array++);
}
void sort_arr(const char **p_array){
const char **lo_p, **hi_p, *tmp;
for(lo_p = p_array;
*lo_p != 0 && *(lo_p+1) != 0;
lo_p++){
for(hi_p = lo_p+1; *hi_p != 0; hi_p++){
if(strcmp(*hi_p, *lo_p) >= 0)
continue;
/* swap strings */
tmp = *hi_p;
*hi_p = *lo_p;
*lo_p = tmp;
}
}
}
char *next_string(void){
char *cp, *destination;
int c;
destination = (char *)malloc(MAXLEN);
if(destination != 0){
cp = destination;
while((c = getchar()) != '\n' && c != EOF){
if(cp-destination < MAXLEN-1)
*cp++ = c;
}
*cp = 0;
if(c == EOF && cp == destination)
return(0);
}
return(destination);
}Example 5.12To further illustrate the use of If the string is more than ten characters long, To release storage allocated by The program reports errors by using
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GROW_BY 10 /* string grows by 10 chars */
main(){
char *str_p, *next_p, *tmp_p;
int ch, need, chars_read;
if(GROW_BY < 2){
fprintf(stderr,
"Growth constant too small\n");
exit(EXIT_FAILURE);
}
str_p = (char *)malloc(GROW_BY);
if(str_p == NULL){
fprintf(stderr,"No initial store\n");
exit(EXIT_FAILURE);
}
next_p = str_p;
chars_read = 0;
while((ch = getchar()) != EOF){
/*
* Completely restart at each new line.
* There will always be room for the
* terminating zero in the string,
* because of the check further down,
* unless GROW_BY is less than 2,
* and that has already been checked.
*/
if(ch == '\n'){
/* indicate end of line */
*next_p = 0;
printf("%s\n", str_p);
free(str_p);
chars_read = 0;
str_p = (char *)malloc(GROW_BY);
if(str_p == NULL){
fprintf(stderr,"No initial store\n");
exit(EXIT_FAILURE);
}
next_p = str_p;
continue;
}
/*
* Have we reached the end of the current
* allocation ?
*/
if(chars_read == GROW_BY-1){
*next_p = 0; /* mark end of string */
/*
* use pointer subtraction
* to find length of
* current string.
*/
need = next_p - str_p +1;
tmp_p = (char *)malloc(need+GROW_BY);
if(tmp_p == NULL){
fprintf(stderr,"No more store\n");
exit(EXIT_FAILURE);
}
/*
* Copy the string using library.
*/
strcpy(tmp_p, str_p);
free(str_p);
str_p = tmp_p;
/*
* and reset next_p, character count
*/
next_p = str_p + need-1;
chars_read = 0;
}
/*
* Put character at end of current string.
*/
*next_p++ = ch;
chars_read++;
}
/*
* EOF - but do unprinted characters exist?
*/
if(str_p - next_p){
*next_p = 0;
fprintf(stderr,"Incomplete last line\n");
printf("%s\n", str_p);
}
exit(EXIT_SUCCESS);
}Example 5.13That may not be a particularly realistic example of how to handle
arbitrarily long strings—for one thing, the maximum storage demand
is twice the amount needed for the longest string—but it
does actually work. It also costs rather a lot in terms of copying
around. Both problems could be reduced by using the library
A more sophisticated method might use a linked list, implemented with the use of structures, as described in the next chapter. That would have its drawbacks too though, because then the standard library routines wouldn't work for a different method of storing strings. 5.5.1. What sizeof can't doOne common mistake made by beginners is shown below:
#include <stdio.h>
#include <stdlib.h>
const char arr[] = "hello";
const char *cp = arr;
main(){
printf("Size of arr %lu\n", (unsigned long)
sizeof(arr));
printf("Size of *cp %lu\n", (unsigned long)
sizeof(*cp));
exit(EXIT_SUCCESS);
}Example 5.14The numbers printed will not be the same. The first will,
correctly, identify the size of 5.5.2. The type of sizeofNow comes the question of just what this does: sizeof ( sizeof (anything legal) ) That is to say, what type does the result of |
The C BookThis book is published as a matter of historical interest. Please read the copyright and disclaimer information. GBdirect Ltd provides up-to-date training and consultancy in C, Embedded C, C++ and a wide range of other subjects based on open standards if you happen to be interested. |
|
West Yorkshire Office
GBdirect Ltd
Training: 0800 651 0338 Please call between 0900 and 1700 (UK time) on Monday to Friday South East Regional Office
GBdirect Ltd
Training: 0800 651 0338 Please call between 0900 and 1700 (UK time) on Monday to Friday Please note: |