Struct

The questions below are due on Monday October 12, 2026; 11:59:00 PM.
 
You are not logged in.

Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.
Back to Exercises

As you know, there is no string primitive in C. Instead, strings are represented as null-terminated char arrays. This can be clunky to work with, and we'd like to be able to easily access certain properties of the string, such as its length.

1) Exercise 1

First, as a reminder, write a function that takes a char array and returns the length of the string it represents. It is guaranteed that it will be null-terminated.

You can call string_length in the rest of these exercises.

It seems inefficient to keep computing the length this way every time, and we have to keep passing its length into functions as an argument. It would be nice if we could group them together into a single structure. This is the role of a struct in C.

struct intro_string {
	char* str; // a char array, not null-terminated
	int max_length; // maximum possible string length that can be stored in array (i.e. length of array)
	int length; // current length of string
}

The idea is that str will be a char array, no longer null-terminated, and length will tell us how much of the array to read to determine the string. The length of the array, max_length, is the maximum allowed string that can be stored. We can change characters in the array to change the string it represents. The entire array might not be used at a given time (i.e., for shorter strings), but remains available for assigning to longer strings later.

This is a rudimentary system for strings, and actual string objects in C++ can get much more complicated. To avoid confusion, we'll call our version intro_string.

2) Exercise 2

Which of the following is the most general allowed relationship between length and max_length to have a valid intro_string instance?

We can declare a new variable with intro_string type as

struct intro_string myString;

The struct keyword distinguishes it from a built-in type. It can get tiring to type struct string all the time, so it is common to use a typedef. The syntax is

typedef existing_type new_name;

In this case we can do

typedef struct intro_string string;

which should be read as "typedef (struct intro_string) string". It is idiomatic to combine the struct definition and typedef together as follows:

typedef struct {
	char* str; // a char array, not null-terminated
	int max_length; // maximum possible string length that can be stored in array (i.e. length of array)
	int length; // current length of string
} intro_string;

(What's going on here is that we define the struct without giving it a name, and then typedef the anonymous struct to intro_string. You could name the struct too, but it's not necessary.)

3) Exercise 3

Suppose we have a intro_string instance istr with istr.str = "Hello World!\n00000", istr.max_length=20, and istr.length=5. What string does istr represent?

We can access members of a struct via dot notation: struct.member. This is also how we can assign elements of a struct. For example, to initialize the instance above:

char[] message = "Hello World!\n00000\0\0";
intro_string myString;
myString.str = message;
myString.max_length = 20;
myString.length = 5;

There is also a shortcut for initializing structs with curly braces similar to arrays. This can only be used for initialization when declaring a variable, and you list the elements in order they are declared in the struct. For example:

char[] message = "Hello World!\n00000\0\0";
intro_string myString = {message, 20, 5};
// the following code for the next line would error:
// myString = {message, 20, 6}; <--- Cannot use this outside of declaration!

On the RISCV 32 microcontroller that we use in 6.1900, how big (in bytes) is the instance of struct myString?

Later on in the code, we do this:

char[] message2 = "Doe a deer, a female deer. Ray a drop of golden sun. Me a name I call myself.";
myString.str = message2;
myString.max_length = strlen(message2);
myString.length = strlen(message2);

On the RISCV 32 microcontroller that we use in 6.1900, how big (in bytes) is the instance of struct myString now?

4) Exercise 4

Write a function that takes in a intro_string object and converts it into a standard, C char array representing the string. It is guaranteed that the size for str_array is at least str.max_length. Remember str_array should be null-terminated.

In the exercise above, we passed the struct to the function by value. However, since structs are non-primitive objects, we generally pass pointers to functions instead of pass by value (both so that we can modify the specific instance of a struct, and to avoid copying large structs). If *str is a pointer, to access its members, one can do

(*str).length

However this dereferencing can get tiring, so it is idiomatic to use arrow notation instead:

str->length

5) Exercise 5

Write the same function as above but with a pointer input this time.

6) Exercise 6

Write a function that takes an intro_string object and replaces its str member with a new string if it fits, otherwise it does nothing. You should modify the existing char array in str, not replace it with new_str. Remember to update length as needed. Return 0 if the replacement is successful, 1 if not.

7) Exercise 7

Write a function that takes three intro_string pointers, and puts the concatenation of the first two into the third. (In Python, this is analogous to output = str1 + str2.) If output's array size is not large enough, then concatenate as much as possible until it is full.

Next, we'll define equality for our struct string. The built-in equality operator == does not know how to compare two structs. How should we define two structs to be equal? One option is if all their members are equal. In our case for intro_string, we might want to know if the two strings the intro_string instances represent are equal, regardless of the array size. Unfortunately, C does not have operator overloading (meaning we can't write our own == operator for structs), so we'll have to define a standard named function.

8) Exercise 8

Write a function to check whether two intro_string instances represent the same string. This means they should have the same length, and the first length characters in the array should match. Return 0 if false, 1 if true.

Back to Exercises