#include <stdio.h>
struct record {
char subject;
int year;
};
main() {
struct record Peter = {"Maths" , 1991};
printf("%s", Peter.subject);
}

- 48,281
- 17
- 65
- 115
-
5`char subject;` defines `subject` as a ***single*** `char` value. To store a string (multiple `char` values ending with a "null-terminator") you must use an array. – Some programmer dude Apr 23 '21 at 05:35
-
5Strings are character arrays in C. It should be ```char subject[10]``` otherwise it will just hold one character and **not** ```"Maths"``` – anirudh Apr 23 '21 at 05:37
-
1`const char *subject;` would also be valid in this example. – paddy Apr 23 '21 at 05:39
-
Read: https://stackoverflow.com/a/8732449/4386427 – Support Ukraine Apr 23 '21 at 05:43
1 Answers
Why can't I use a string directly in a structure without creating an array?
Short answer: Because strings in C are stored in char arrays
More details:
C has no explicit string-type. A C style string is a special use of an array of char.
Without an array of char, there simply can't be any string.
To store a string in C you'll need to do two things:
Create an array of char
Set the value of (at least) one char in the array to NUL (aka '\0')
The NUL from step 2 represent the end-of-string (i.e. a sentinel telling that the string ends here).
So having a string like
"Maths"
requires an array of 6 chars with memory being
'M', 'a', 't', 'h', 's', '\0'
Notice that the array is allowed to be larger than 6 chars - like:
char str[10] = "Maths";
in which case the memory will be:
'M', 'a', 't', 'h', 's', '\0', '\0', '\0', '\0', '\0'
The standard string functions (e.g. strlen
, strcpy
, etc) will operate on the array from start until it see the first '\0'
. Everything after the first '\0'
is ignored.
So even if the memory was changed to contain:
'M', 'a', 't', 'h', 's', '\0', 'a', 'b', 'c', 'd'
the string functions would still consider this to be the string "Maths"
But... if some code (e.g. str[5] = 'A'
) changed the array/memory to be:
'M', 'a', 't', 'h', 's', 'A', 'a', 'b', 'c', 'd'
there wouldn't be a string anymore and calling any standard string function using str
as parameter would be illegal.
Conclusion: If you want your struct to actually store a string, the struct must contain an array of char. Like:
#define MAX_RECORD_STR_LEN 20
struct record{
char subject[MAX_RECORD_STR_LEN];
int year;
};
String literal
Now you may ask: "If the above is correct, how can the code below be valid?"
char *str = "Maths"; // Isn't this a string without an array ???
Well, it may look that way but no - there is an array involved!
Here the variable str
is a pointer to char, i.e. it points to some other memory in the system where (at least one char) is located. The compiler has made sure that the memory at that location is an array of char containing 'M', 'a', 't', 'h', 's', '\0'
. This is called a string literal.
So even if there is no array declaration in the code, the compiler made sure that a char array is present at the "pointed-to" memory location with the correct values.
Can I use a char pointer in the struct?
Well... it depends...
If you want the string to be stored as part of the struct, the answer is No. In that case the char array must be a struct member.
However, in many cases it isn't required that the string is stored as part of the struct. It may be fine that the struct contains a pointer to some other memory where the string are stored (much like the string literal mentioned above).
Something like:
struct record{
char *subject;
int year;
};
struct record Peter = {"Maths" , 1991}; // Fine
Here Peter.subject
points to some other memory where the compiler has placed the string "Maths".
This is especially useful when you don't know the maximum string size. In that case you would want dynamic allocation of memory so that your strings can have any size.
It could look like:
struct record Peter = {NULL , 1991};
char *p = GetNameFromStdin(); // Function to read user input
size_t size_needed = strlen(p) + 1; // note: add 1 for the NUL-termination
Peter.subject = malloc(size_needed); // Allocate memory
assert(Peter.subject != NULL); // Test that malloc went fine
strcpy(Peter.subject, p); // Copy the string

- 42,271
- 4
- 38
- 63