CSE 333 Exercise 2
Due: Monday, January 12 by 11 AM
Rating: 1 (note)
Each exercise this quarter is rated on a integer scale of 1 – 5, inclusive, with 1 being the "least time-consuming" and 5 being the "most time-consuming".
This difficulty scale is meant as a rough guide for you in predicting the amount of time to set aside for each exercise as you balance the work required for 333 with your other obligations. However, it is necessarily imperfect as everyone's set of circumstances and experiences with the exercises differ. If your experience with an exercise does not align with its rating, that is not a reflection of you or your abilities.
Goals
- Write code that uses pointers and data representations.
- Examine data structure representation in memory.
Background
Recall the topics of endianness and C struct layout:
- Endianness determines the ordering of the bytes when multibyte
data is stored in memory – the least significant
byte is stored at the littlest or biggest address.
- This does not affect the address of the data, which is always that of the first/lowest byte.
- In C, the layout of a struct instance is determined by the
compiler based on the following rules:
- The fields appear in the order in which they are declared.
- Each field is placed at an offset that is a multiple of its individual alignment requirement (K).
- The size of the struct instance (and its alignment requirement) is based on Kmax.
Problem Description
Write a C program (ex2.c) that does the following:
-
Contains a function called
PrintByteswith prototypevoid PrintBytes(void* mem_addr, int num_bytes);. This function should print out the length, the address passed in, and the bytes of memory as exactly two digits each in lowercase hexadecimal, e.g.,
The 4 bytes starting at 0x7fff1081856c are: ff 01 30 4e
-
Contains the
mainfunction found below that prints the bytes of a struct instance and its fields using the function that you wrote. Your main should match the provided code exactly; copy-and-paste this code from the spec instead of re-typing it. If you notice any style issues with it, feel free to ignore them.int main(int argc, char** argv) { float float_val = 1.0f; char char_val = '1'; int32_t int_val = 1; double double_val = 1.0; typedef struct { float float_val; char char_val; int32_t int_val; double double_val; } Ex2Struct; Ex2Struct struct_val = { float_val, char_val, int_val, double_val }; PrintBytes(&float_val, sizeof(float)); PrintBytes(&char_val, sizeof(char)); PrintBytes(&int_val, sizeof(int32_t)); PrintBytes(&double_val, sizeof(double)); PrintBytes(&struct_val, sizeof(struct_val)); return EXIT_SUCCESS; } - When your program compiles and runs, it should
produce output that is identical to the following,
except for values that might change from one execution to the
next because of randomness outside of your control, including the
values of uninitialized/mystery data and security measures such
as stack randomization.
$ gcc -Wall -g -std=c17 -o ex2 ex2.c $ ls ex2 ex2.c $ ./ex2 The 4 bytes starting at 0x7ffce824a700 are: 00 00 80 3f The 1 bytes starting at 0x7ffce824a6ff are: 31 The 4 bytes starting at 0x7ffce824a704 are: 01 00 00 00 The 8 bytes starting at 0x7ffce824a708 are: 00 00 00 00 00 00 f0 3f The 24 bytes starting at 0x7ffce824a710 are: 00 00 80 3f 31 00 00 00 01 00 00 00 0d 62 00 00 00 00 00 00 00 00 f0 3f $
- The last output line is a single line, but may wrap in your browser.
- The number of bytes shown on the last line is NOT the sum of the number of bytes shown on the previous lines!
Implementation Notes
- You will want to match the formatting shown in the example
given above exactly, including spacing and
capitalization.
- For the case of
num_bytes = 0, it's ok to have a space at the end of the output. - For the case of
num_bytes > 0, there should not be a space at the end of the output.
- For the case of
- You will need to convince the compiler to let you access bytes
in memory starting from a
void*, then loop to print each byte one-by-one using a pointer. - You will need to use format specifiers in
printfto print out a pointer value as well as auint8_tin lowercase hexadecimal. As a hint, take inspiration from the following code:#include <inttypes.h> uint8_t a_byte = 0xD1; printf("The byte is: %02" PRIx8 " -- enjoy!\n", a_byte);
Style Focus
No new style things to point out, but we strongly recommend that you revisit the Exercise 1 Style Focus section.
Submission
Submit the following file(s) by creating an ex2-submit tag in your exercise repo before the assignment deadline. The file(s) should be located in the exact directory listed below, including capitalization:
ex2/ex2.c
Your code must:
- Compile without errors or warnings on CSE Linux machines
(lab workstations,
attu, or CSE home VM). - Have no runtime errors, memory leaks, or memory errors
(
gccandvalgrind). - Be contained in the file listed above that compiles with the
command:
$ gcc -Wall -g -std=c17 -o ex2 ex2.c
- Have a comment at the top of your
.cfile with your name(s) and CSE or UW email address(es). - Be pretty: the formatting, modularization, variable and
function names, commenting, and so on should be consistent with
class style guidelines.
Additionally, the linter shouldn't have any complaints about your
code (
cpplint.py --clint). - Be robust: your code should deal with hard-to-handle/edge cases and bogus user input (if there are any) gracefully.