3
#include <stdio.h>

typedef struct {
    char * name;
    int age;
} person;

int main() {
    person john;

    /* testing code */
    john.name = "John";
    john.age = 27;
    printf("%s is %d years old.", john.name, john.age);
}

This a well-working code, I just got a small question. In the struct part, after I delete the * before name, this code no longer works, but no matter the age's type is, int or a pointer, it always works fine. So can anyone tell me why name has to be a pointer rather than just a type of char?

Abhineet
  • 5,320
  • 1
  • 25
  • 43
ABeginner
  • 31
  • 2

4 Answers4

3

char type is short for character and can hold one character. C has no string type, instead a string in C is an array of char terminated with '\0' - the null character (null terminated strings).

Thus to use a string you need a pointer to memory that contains lots of characters. So why does it work for an int with or without the *. Well we can either have the age as an int or we can have a pointer to memory that stores the age. Either works well. But we can't store a string in one character.

dave
  • 4,812
  • 4
  • 25
  • 38
1

This has to do with format specifiers you've in printf function. %s tries to output the string (reads a portion of memory), %d interprets everything in gets like an integer, thus even a pointer sort of works, however, you shouldn't to that, it's undefined behavior.

I suggest you to read some good books on C to get a good grasp on such things, a good list is here The Definitive C Book Guide and List

Community
  • 1
  • 1
buld0zzr
  • 962
  • 5
  • 10
1

but no matter the age's type is int or a pointer, it always works fine.

That's undefined behaviour.

To elaborate, a double-quote delimited string (as seen above) is a string literal, and when used as an initializer, it basically gives you a pointer to the starting of the literal thereby it needs a pointer variable to be stored. So, name has to be a pointer.

OTOH, the initializer 27 is an integer literal (integer constant) and it needs to be stored into an int variable , not an int *. If you use 27 to initialize an int * and use that, it works (rather, seem to work) because that way, it invokes undefined behavior later, by attempting to use invalid memory location.

FWIW, if you try something like

typedef struct {
    char * name;
    int *age;
} person;

and then

john.age = 27;  //incompatible assigment

compiler will warn you about wrong conversion from integer to pointer.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

char *name: name is a pointer to type char. Now, when you make it to point to "John", the compiler stores the John\0 i.e., 5 chars to some memory and returns you the starting address of that memory. So, when you try to read using %s (string format specifier), the name variable returns you the whole string reading till \0.

char name : Here name is just one char having 1 byte of memory. So, you can't store anything more than one char. Also, when you would try to read, you should always read just one char (%c) because trying to read more than that will take you to the memory region which is not assigned to you and hence, will invoke Undefined Behavior.

int age : age is allocated 4 bytes, so you can store an integer to this memory and read as well, printf("%d", age);

int *age : age is a pointer to type int and it stores the address of some memory. Unlike strings, you do not read integers using address (loosely saying, just for the sake of avoiding complexity). You have to dereference it. So first, you need to allocate some memory, store any integer into it and return the address of this memory to age. Or else, if you don't want to allocate memory, you can use compiler's help by assigning a value to age like this, *age = 27. In this case, compiler will store 27 to some random memory and will return the address to age which can be dereferenced using *age, like printf("%d", *age);

Abhineet
  • 5,320
  • 1
  • 25
  • 43