char a[50][50]
declares a
as a 50-element array of 50-element arrays of char
. That means each a[i]
is a 50-element array of char
. It will be laid out in memory like:
+---+
a: | | a[0][0]
+---+
| | a[0][1]
+---+
| | a[0][2]
+---+
...
+---+
| | a[0][49]
+---+
| | a[1][0]
+---+
| | a[1][1]
+---+
...
+---+
| | a[1][49]
+---+
| | a[2][0]
+---+
...
This code is storing up to 50 strings, each up to 49 characters long, in a
(IOW, each a[i]
can store a 49-character string). In C, a string is a sequence of character values including a 0-valued terminator. For example, the string "hello"
, is represented as the sequence {'h', 'e', 'l', 'l', 'o', 0}
. That trailing 0
marks the end of the string. String handling functions and output functions like puts
and printf
with the %s
specifier need that 0 terminator in order to process the string correctly.
Strings are stored in arrays of character type, either char
(for ASCII, UTF-8, or EBCDIC character sets) or wchar_t
for “wide” strings (character sets that require more than 8 or so bits to encode). An N-character string requires an array that’s at least N+1 elements wide to account for the 0 terminator.
Unless it is the operand of the sizeof
or unary &
operator, or is a string literal used to initialize an array of character type, an expression of type “N-element array of T
” will be converted (“decay”) to an expression of type “pointer to T
“, and the value of the expression will be the address of the first element of the array.
When you call
gets( a[i] );
the expression a[i]
is converted from type “50-element array of char
” to “pointer to char
“, and the value of the expression is the address of the first element of the array (&a[i][0]
)1. gets
will read characters from standard input and store them to the array starting at that address. Note that gets
is no longer part of the standard C library – it was removed in the 2011 version of the standard because it is unsafe. C does not require any sort of bounds checking on array accesses – if you type in more characters than the target buffer is sized to hold (in this case, 50), those extra characters will be written to memory immediately following the last element of the array, which can cause all sorts of mayhem. Buffer overflows are a popular malware exploit. You should replace the gets
call with
fgets( a[i], 50, stdin );
which will read up to 49 characters into a[i]
from standard input. Note that any excess characters are left in the input stream.
Also, the behavior of fflush
is not defined for input streams2 – there’s no good, safe, portable way to clear excess input except to read it using getchar
or fgetc
.
- This is why you got the error message you did when you changed
a
fromchar [50][50]
tochar [50]
– in that case,a[i]
has typechar
, notchar *
, and the value ofa[i]
is not an address. - Microsoft’s Visual Studio C compiler is a notable exception – it will clear excess input from the input stream. However, that’s specific to MSVC, and not portable across different compilers. The operation is also a little nonsensical with respect to “flush” semantics.
solved What does char a[50][50] mean in C?