/** @file malloc_fish.c * @author Alejandro Cabrera * @date October 18, 2010, 7:57am * @brief A brief overview of handling objects with malloc/free in C. * @note compile: gcc -std=gnu99 */ #include #include #include static const size_t MAX_FISH = 100000; static const size_t MAX_FINS = 255; static const size_t MAX_EYES = 255; static const size_t MAX_FIN_SPAN = 127; static const size_t MAX_PUPIL_WIDTH = 127; struct Fin { size_t span; }; struct Eye { size_t pupilWidth; }; // could also add teeth, scales, tentacles... struct Fish { size_t numFins; size_t numEyes; struct Fin *fins; struct Eye *eyes; }; int main(int argc, char **argv) { size_t howManyFish; struct Fish *freakyFishes = 0; // error checking for the next three sections // correct number of arguments? if (argc != 2) { fprintf(stderr, "usage: %s HOW_MANY_FISH\n", argv[0]); exit(EXIT_FAILURE); } // correct type of argument? if (sscanf(argv[1], "%lu", &howManyFish) != 1) { fprintf(stderr, "error: %s is not a number\n", argv[1]); exit(EXIT_FAILURE); } // are there more fish than we care to produce? if (howManyFish > MAX_FISH) { fprintf(stderr, "error: %lu is too many fish. Go eat some!\n", howManyFish); exit(EXIT_FAILURE); } // allocate an array of fish that can hold 'howManyFish' freakyFishes = (struct Fish *) malloc(sizeof(struct Fish) * howManyFish); if (!freakyFishes) { perror("fish allocation failed"); exit(EXIT_FAILURE); } // for each fish, generate the number of fins, allocate the fins, // generate the number of eyes, allocate the eyes, // set the fin span, and set the pupil width. for (size_t i = 0; i < howManyFish; ++i) { size_t finCount = (random() & MAX_FINS) + 1; size_t eyeCount = (random() & MAX_EYES) + 1; freakyFishes[i].numFins = finCount; freakyFishes[i].numEyes = eyeCount; freakyFishes[i].fins = (struct Fin *) malloc(sizeof(struct Fin) * finCount); assert(freakyFishes[i].fins && "error: could not allocate fins"); freakyFishes[i].eyes = (struct Eye *) malloc(sizeof(struct Eye) * eyeCount); assert(freakyFishes[i].eyes && "error: could not allocate eyes"); for (size_t j = 0; j < finCount; ++j) { freakyFishes[i].fins[j].span = random() & MAX_FIN_SPAN; } for (size_t j = 0; j < eyeCount; ++j) { freakyFishes[i].eyes[j].pupilWidth = random() & MAX_PUPIL_WIDTH; } } // for each fish, print the number of fins the fish has and the span // of each fin, print the number of eyes that the fish has and // print the pupil width of each eye printf("Let's see some freaky fish!\n"); for (size_t i = 0; i < howManyFish; ++i) { printf("Fish %lu has %lu fins and %lu eyes!\n", i, freakyFishes[i].numFins, freakyFishes[i].numEyes); printf("\tThe fins are...\n\t["); for (size_t j = 0; j < freakyFishes[i].numFins; ++j) { printf("%lu, ", freakyFishes[i].fins[j].span); } printf("\t] inches long! Freaky, right?\n"); printf("\tThe pupils are...\n\t["); for (size_t j = 0; j < freakyFishes[i].numEyes; ++j) { printf("%lu, ", freakyFishes[i].eyes[j].pupilWidth); } printf("\t] inches long! That's kind of weird...\n"); } // for each fish, free the memory allocated to holding the fins // and the eyes printf("Let's cook these fish!\n"); for (size_t i = 0; i < howManyFish; ++i) { free(freakyFishes[i].fins); free(freakyFishes[i].eyes); } // now, free the fish free(freakyFishes); printf("Enjoy the fish fry! :) \n"); return 0; }