What's different between char and char [1]?

121 Views Asked by At
#include <stdio.h>
#include <string.h>

struct Student {
  int id;
  char name[10];
  char sex;
  int grade;
};

int main() {
  struct Student std;
  std.id = 1;
  strcpy(std.name, "Kevin");
  std.sex="M";
  std.grade = 2;
  printf("%d %s %s %d\n", std.id, std.name, std.sex, std.grade);
}

In this code, got error on allocating a sex character in std variable. I thought 'M' is only one character so that It will works in structure like normal variable did.

#include <stdio.h>
#include <string.h>

struct Student {
  int id;
  char name[10];
  char sex[1];
  int grade;
};

int main() {
  struct Student std;
  std.id = 1;
  strcpy(std.name, "Kevin");
  strcpy(std.sex, "M");
  std.grade = 2;
  printf("%d %s %s %d\n", std.id, std.name, std.sex, std.grade);
}

I fixed code like this then it works.

So my question is,

  1. What's different between char and char [1] in memory perspection?
  2. Why char sex doesn't work in structure?

I seached but can't find answer. Help me!

1

There are 1 best solutions below

0
Vlad from Moscow On BEST ANSWER

char is a scalar type while char[1] is an array type with one element. "M" is a string literal that has character array type char[2] and in memory is stored like { 'M', '\0' }.

You can check that using this call of printf

printf( "sizeof( \"M\" ) = %zu\n", sizeof( "M" ) );

In this statement

std.sex="M";

you are trying to assign the array (string literal) "M" to the scalar object std::sex of the type char. In this assignment the character array is implicitly converted to a pointer to its first element. In fact you have

std.sex = &"M"[0];

while you need to write at least like

std.sex = "M"[0];

though instead of the string literal it will be simpler and clear to use an integer character constant like

std.sex = 'M';

Correspondingly in the call of printf you shall use conversion specifier c instead of s to output a single character

printf("%d %s %c %d\n", std.id, std.name, std.sex, std.grade);
              ^^

In the second program as the data member sex is declared as an array with one element

char sex[1];

then this call of strcpy

strcpy(std.sex, "M");

writes into memory outside the array sex because as pointed out above the string literal "M" has two elements. As a result the second program is also invalid. It seems it works only due to the alignment of the data member int grade; that is the compiler inserts additional bytes after the data member sex to provide the alignment.

You could declare the character array like

char sex[2];

though as you are going to use only one character then it will be enough to declare the data member sex as

char sex;

and use it as shown above in the comments for the first program.

Pay attention to that you could initialize the object of the structure type in its declaration the following way

struct Student std = 
{
    .id = 1, .name = "Kevin", .sex = 'M', .grade = 2
};

or

struct Student std = 
{
    1, "Kevin", 'M', 2
};