#include /**** * * This program illustrates same basics of strings, in particular how a string * is stored as an array of char. * * A very important convention about string variables in C is that they are * NULL TERMINATED. This means that the end of the string is marked by the * null character, which is denoted '\0'. * * Given the null termination convention, a character array of 10 chars can * only hold a string up to 9 useful characters long. This is because the last * character of any string needs to be a null. * * Since strings are stored as arrays, they are subject to the same bounds * rules as any other arrays. That is, you cannot store more chars in a string * than its array is declared to hold. And in the case of strings, you can * only store ONE FEWER character than the array is declared to hold. Again, * this is because the last char of a string must always be null. * */ /* Prototypes for functions used at the end of main. */ void compute_with_strings(char s1[], char s2[], char s3[]); void clobber_strings(char s1[], char s2[], char s3[]); int main() { /* * Variable char_10 is an array that can hold up to 10 characters. Because * of the null-termination convention, char_10 can only hold a string value * of 9 useful characters, since the last character must be null. * * Note that variable char_10 is not initialized in its declaration. This * means it holds garbage to start out. */ char char_10[10]; /* * Variable string_10 is also an array of of up to 9 useful characters. * This variable is initialized to the 5-character string value "abcde". */ char string_10[10] = "abcde"; /* * Variable string_10_array_init is exactly the same kind of variable as * char_10 and string_10. The difference here is in the style of * initialization value, which is a character-by-character array literal. * * The important thing is that variables string_10 and string_10_array_init * are exactly the same size and are initialized to exactly the same value. */ char string_10_array_init[10] = {'a', 'b', 'c', 'd', 'e', '\0'}; /* * Variable string_10_auto_sized is also string variable of up to 9 useful * characters. In its declaration, the size of the array is determined * automatically from the length of the initializing string. * * Note that the initial value of string_10_auto_sized is longer than * string_10 or string_10_array_init. However, all three of these * variables are arrays with 10 elements. */ char string_10_auto_sized[] = "abcdefghi"; /* * Let's print out the values of the three initialized string variables. * String values are printed out using the %s formatter in printf. When * printing with %s, printf totally relies on the null termination * convention. If a string value is not null-terminated, printf will do * unpredictable things. */ printf("string_10 = %s\n", string_10); printf("string_10_array_init = %s\n", string_10_array_init); printf("string_10_auto_sized = %s\n", string_10_auto_sized); /* * Now let's do some computation with the string variables, and print them * again. See the comment for the compute_with_strings function for what * the computation is. */ compute_with_strings(string_10, string_10_array_init, string_10_auto_sized); printf("Value of string variables after computation: %s, %s, %s\n", string_10, string_10_array_init, string_10_auto_sized); /* * In the preceding printf statements, we left out the printing of the * uninitialized variable char_10, since it's value is unknown garbage. * Let's live dangerously and print char_10, to see what happens. */ printf("Uninitialized value of char_10 = %s\n", char_10); /* * We'll finish by doing something purposely foolish -- writing well past * the bounds of the three string variables. See the comment for the * clobber_string function for what's likely to happen. */ clobber_strings(string_10, string_10_array_init, string_10_auto_sized); printf("Value of string variables after computation: %s, %s, %s\n", string_10, string_10_array_init, string_10_auto_sized); return 0; } /** * This function illustrates some would-be computation with three string * parameters. It doesn't do anything particularly useful -- it just sets the * first character of each string to 'X'. The important concept this function * illustrates is that string parameters behave in exactly the same way as any * other type of array parameter. Namely, changes made to string parameters * are reflected in the arrays at the calling site. This means that in the * above print after this function is called, the values of the three strings * have been changed with 'X' to be the first character. */ void compute_with_strings(char s1[], char s2[], char s3[]) { s1[0] = 'X'; s2[0] = 'X'; s3[0] = 'X'; } /** * This function flagrantly violates the rule of not storing values past the * end of any array. It puts 'X' characters in the first 100 elements of the * three string parameters. That's enough overwriting to likely cause some * damage. While the exact nature of the damage is not predictable, it's quite * likely to cause a fatal error when the program is run. */ void clobber_strings(char s1[], char s2[], char s3[]) { int i; for (i = 0; i < 100; i++) { s1[i] = 'X'; s2[i] = 'X'; s3[i] = 'X'; } }