Array of Char Pointers in C – Why arr[1] Prints “bar”

An array of strings that contains no strings — just three pointers. char *arr[] is how C fakes a string list, and reading it correctly requires untangling a declaration that half of all beginners parse backwards. This question from our C Programming Quiz App checks whether you know what arr[1] is before asking what it prints.

The Quiz Question

char *arr[] = {"foo", "bar", "baz"};
printf("%s", arr[1]);

What is printed by this code?

  1. foo
  2. bar
  3. baz
  4. Compile error

The Correct Answer: bar

char *arr[] declares an array of three char pointers ([] binds tighter than *, so it’s an array of pointers, not a pointer to an array). Each element points at one string literal. arr[1] is the second pointer — aimed at "bar" — and %s follows it, printing characters up to the null terminator. Verified on gcc 13.3 and Apple clang 21, clean under -ansi -Wall -Wextra:

$ gcc -ansi -Wall -Wextra strings.c && ./a.out
arr[1]    = bar
arr[1][0] = b
sizeof(arr) = 24

That sizeof is telling: 24 bytes = three 8-byte pointers. The nine characters of string data (plus terminators) live elsewhere — the array holds only addresses.

Why Each Wrong Answer Is Wrong

Why not “foo”?

“foo” is arr[0] — the 1-based-indexing slip. C arrays index from zero, so element 1 is the second entry. (The same off-by-one drives wrong answers in the *(a + 1) question.)

Why not “baz”?

“baz” is arr[2], the last element — the answer if you counted from the end or doubled the off-by-one. With three elements the valid indices are 0, 1, 2.

Why not a compile error?

Everything type-checks: the initializer list has three string literals, each of which decays to a char *; arr[1] is a char *; and %s expects exactly that. One legitimate quibble: pointing non-const char * at string literals is allowed in C (unlike C++11+, where it’s an error), but writing through those pointers would crash — the literals live in read-only memory, as the char array vs string literal question demonstrates the hard way. const char *arr[] is the safer declaration.

Two Levels of Indexing — and What This Layout Buys You

Because arr[1] is itself a pointer, a second subscript reaches individual characters: arr[1][0] is 'b', arr[1][2] is 'r'arr behaves like a 2-D jagged structure without being one. Compare the two ways to store a string table:

char *arr[]   = {"foo", "bar", "baz"};   /* 3 pointers → shared literals   */
char arr2[3][4] = {"foo", "bar", "baz"}; /* 3 writable rows of 4 bytes     */

The pointer form is compact, rows can have wildly different lengths, and swapping two entries means swapping two pointers — this is why argv, environment lists, and menu tables all use it. The 2-D form owns writable storage but pads every row to the longest. The pointer form’s other superpower is sorting: rearranging pointers instead of copying string bytes is what makes qsort on a string table cheap.

This is also exactly the shape of main‘s second parameter — char *argv[] is an array of pointers to the command-line arguments, and argv[1] being “the first argument” (index 1!) trips people for the same reason this question does.

Frequently Asked Questions

What does char *arr[] declare in C?

An array of pointers to char[] binds tighter than *. With three string-literal initializers it’s three pointers, each aimed at a literal stored elsewhere. sizeof(arr) is 24 on a 64-bit machine: three 8-byte pointers, no string data.

What is arr[1][0] for char *arr[] = {“foo”, “bar”, “baz”}?

'b'. The first subscript selects the pointer to “bar”; the second indexes into that string. The double subscript works even though arr is not a 2-D array.

Can you modify the strings in a char *arr[] table?

Not the literal-initialized ones — they point into read-only storage, and writing crashes. Use char arr[3][4] for writable rows, or declare the table const char *arr[] to let the compiler enforce the read-only reality.

Related Reading

Recommended Books

This question is #124 in the C Programming Quiz App — 155 questions with explanations covering pointers, arrays, memory, and more.
Download on Google Play →

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>