#define ALLOW_INSTRUCTOR_CODE /*************************************************************************** *************************************************************************** ****** BEFORE BEGINNING OR TURNING IN THIS EXERCISE IT IS EXTREMELY ****** ****** IMPORTANT THAT YOU READ, FULLY UNDERSTAND, AND ADHERE TO THE ****** ****** REQUIREMENTS STATED IN THE DOCUMENT TITLED, "ASSIGNMENT ****** ****** SUBMISSION REQUIREMENTS", DOWNLOADABLE FROM THE COURSE WEB ****** ****** SITE. ****** *************************************************************************** **************************************************************************/ /*************************************************************************** ************* C/C++ Programming 2: Assignment 7 - Exercise 4 ************* ********* BEGIN EXERCISE REQUIREMENT - THIS MUST BE A "C" PROGRAM ********* *************************************************************************** (3 points) The purpose of this exercise is to illustrate the endian conversion of arbitrary scalar data within an aggregate type, such as a structure, class, or union. If it is arbitrarily assumed that a long is 4 bytes and a short is 2 bytes, a structure defined and initialized as: struct { long i; short j, k; } x = {0x01234567L, 0x89ab, 0xcdef}; will appear in memory in one of the two following orders, dependent upon the machine's endian implementation. (There can be an arbitrary amount of implementation-dependent padding after any member(s) of the structure): Big Endian Little Endian First byte in memory: 01 67 23 45 45 23 67 01 ----- possible compiler padding here ----- 89 ab ab 89 ----- possible compiler padding here ----- cd ef ef cd ----- possible compiler padding here ----- If such a structure is written into a file, such as with: fwrite(&x, sizeof(x), 1, fp); those bytes (including all padding) will be written into the file in the same order shown. For the structure defined as: struct Test { float f; double d; void *vp; }; write functions OpenTemporaryFile, ReverseEndian, ReverseStructure, ReadStructures, and WriteStructures: OpenTemporaryFile syntax: FILE *OpenTemporaryFile(void); Parameters: none Synopsis: Opens a temporary file using the standard C library tmpfile function. If the open fails an error message is output to stderr and the program is terminated with an error exit code. Return: A pointer to the open file if the open succeeds; otherwise, the function does not return. ReverseEndian syntax: void ReverseEndian(void *p, size_t size); Parameters: p - a pointer to the scalar object to be reversed size - the number of bytes in the object Synopsis: Swaps the bytes in the scalar object in

, thereby converting it from big endian to little endian, or vice versa. Return: void ReverseStructure syntax: void ReverseStructure(struct Test *p); Parameters: p - a pointer to the structure whose members are to be reversed Synopsis: Calls function ReverseEndian for each member of the structure in

, thereby converting each from big endian to little endian format, or vice versa. Return: void ReadStructures syntax: void ReadStructures(struct Test *p, size_t count, FILE *fp) Parameters: p - a pointer to where the structure(s) that are read will be placed in memory count - the number of structures to read fp - a pointer to an open binary file containing the structure(s) to be read. Synopsis: Reads count structures from and stores them in memory starting at address

. If structures can't be read an error message is output to stderr and the program is terminated with an error exit code. Return: void if structures are read; otherwise, the function does not return. WriteStructures syntax: void WriteStructures(const struct Test *p, size_t count, FILE *fp); Parameters: p - a pointer to where the structure(s) that are written will come from in memory count - the number of structures to write fp - a pointer to an open binary file into which the structure(s) will be written. Synopsis: Reads structures from memory starting at address

and writes them to the file . If structures can't be written an error message is output to stderr and the program is terminated with an error exit code. Return: void if structures are written; otherwise, the function does not return. * Make no assumptions about the number of bytes in any data type. * Make no assumptions about the presence, absence, value, or amount of padding. *************************************************************************** ************************ END EXERCISE REQUIREMENT ************************* **************************************************************************/ /*************************************************************************** * BEFORE PRINTING THIS ASSIGNMENT TO TURN IN, DELETE THIS COMMENT AND * EVERYTHING ABOVE IT. **************************************************************************/ /* * TODO: * REPLACE THIS COMMENT WITH YOUR TITLE BLOCK. */ /* Do not change the following line: */ struct Test { float f; double d; void *vp; }; /* * TODO: * REPLACE THIS COMMENT WITH YOUR C CODE, PLUS ANYTHING NECESSARY TO * SUPPORT MY TEST CODE BELOW. DO NOT INCLUDE ANY UNNEEDED HEADER FILES! */ /*************************************************************************** * BEFORE PRINTING THIS ASSIGNMENT TO TURN IN, DELETE THIS COMMENT AND * EVERYTHING BELOW IT. **************************************************************************/ /* ***** Change nothing below this comment without instructor permission. **** * Everything that follows was written to help test/verify your code. You * do not need to understand the details of my code to write yours! */ #ifdef ALLOW_INSTRUCTOR_CODE #define Elements(array) (sizeof(array)/sizeof((array)[0])) typedef unsigned char UChar; int main(void) { UChar *cp; size_t elemNo, byteNo; FILE *temporaryFile; struct Test x[] = /* an array of structures */ { /* declare and initialize */ {23.6F, -425e-6, (void *)0x2345}, /* structure 0 */ {2, 1, 0}, /* structure 1 */ {-6, 3.3, NULL} /* structure 2 */ }; /* Print bytes in structures before reversal. */ printf("Structure bytes before reversal:\n"); for (elemNo = 0; elemNo < Elements(x); ++elemNo, putchar('\n')) { printf(" Element %d:\n ", elemNo); cp = (UChar *)&x[elemNo]; for (byteNo = 0; byteNo < sizeof(*x); ++byteNo) printf(" %02x", cp[byteNo]); } /* file for unaltered structures */ temporaryFile = OpenTemporaryFile(); /* write multiple structures */ WriteStructures(x, Elements(x), temporaryFile); /* back to beginning */ rewind(temporaryFile); /* read multiple structures */ ReadStructures(x, Elements(x), temporaryFile); fclose(temporaryFile); printf("\n"); /* Print bytes in structures after reversal. */ printf("Structure bytes after reversal:\n"); for (elemNo = 0; elemNo < Elements(x); ++elemNo, putchar('\n')) { printf(" Element %d:\n ", elemNo); ReverseStructure(&x[elemNo]); cp = (UChar *)&x[elemNo]; for (byteNo = 0; byteNo < sizeof(*x); ++byteNo) printf(" %02x", cp[byteNo]); } printf("\n"); printf("ARE THE RESULTS CORRECT???\n"); return EXIT_SUCCESS; } #endif