1

I'm trying to write a program that allows to add data about different types of stars and print them back on the screen. Why does this not work:

typedef union{

    struct{
        char name_main[30];
        int age;
        char color[12];
    };

    struct{
        char name_binary[30];
        double radius_1, radius_2;
    };

    struct{
        char name_light[30];
        double luminosity_low, luminosity_high, period;
    };

}STARS;

int main(int argc, char **argv)
{
    bool running = true;
    int choice;
    STARS *star = (STARS *)malloc(sizeof(star));

    printf("Star Menu\n");
    putchar('\n');
    
    while(running)
    {
        putchar('\n');
        printf("Please choose a type of star:\n");
        printf("1. Main Sequence Star\n2. Binary Star\n3. Variable Light Star\n4. Exit\n");
        scanf("%d", &choice);
    
        switch(choice)
        {
            case 1:
                printf("You've chosen: Main Sequence Star\n");
                printf("Please enter the name of the star:\n");
                scanf("%s", star->name_main);
                //printf("%s", star->name_main);
                printf("Please enter the age of: %s\n", star->name_main);
                scanf("%d", &star->age);
                printf("Age: %d\n", star->age);
                printf("Please enter the color of: %s\n", star->name_main);
                scanf(" %s", star->color);
                printf("Color: %s\n", star->color);
            //  printf("Type : Main sequence | Name : %s | Age : %d | Color : %s\n", star->name_main, star->age, star->color);
                break;
            case 2:
                printf("You've chosen: Binary Star\n");
                printf("Please enter the name of the star:\n");
                scanf("%s", star->name_binary);
                printf("Name: %s\n", star->name_binary);
                printf("The radius of the first star:\n");
                scanf("%lf", &star->radius_1);
                printf("The radius of the second star:\n");
                scanf("%lf", &star->radius_2);
                printf("Radius 1: %.2lf | Radius 2: %.2lf\n", star->radius_1, star->radius_2);
                break;
            case 3:
                printf("You've chosen: Variable Light Star\n");
                break;
            case 4:
                printf("Exit\n");
                running = false;
                break;
        }
    }

    return 0;
}

I'm using a union of structs because each star has specific characteristics and we don't care about the others' when we write for a certain type. The issue appears at the color, if I write red the output will be: Color: r:. I've tried adding a space before the format specifier, consuming a character before using scanf but the issue persists and I'm not sure why. Any thoughts?

Andrei0408
  • 197
  • 7
  • 2
    [Don't use `scanf("%s", ...)`](https://stackoverflow.com/questions/2430303/disadvantages-of-scanf), its vulnerable to buffer overflow. Use `fgets` instead. – SuperStormer May 18 '21 at 17:00
  • 4
    [Couldn't reproduce](https://wandbox.org/permlink/K6V0omAo5rNxDVeH). Please post a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) wihich includes the definition (and initialization, if exists) of `star`. – MikeCAT May 18 '21 at 17:00
  • 1
    You should not attempt to print something read via `scanf` without checking its return code. This, since it's likely you're executing something other than what you posted. – Jeff Holt May 18 '21 at 17:04
  • @SuperStormer could the overflow theoretically be solved by using ```%len-1s``` when using scanf? – Andrei0408 May 18 '21 at 17:09
  • @MikeCAT I've edited the code, to include the initialization of star. I didn't post the whole code because it's a long switch-menu type of code, and I thought it might be redundant EDIT: I've posted the whole code because I noticed another issue with scanf, this time when reading a double, not a string. After the inputting radius 1, it's printing garbage, but the 2nd radius is correct – Andrei0408 May 18 '21 at 17:10

2 Answers2

4

You didn't allocate enough size of buffer. sizeof(star) is the size of the pointer. A pointer is typically 4-byte or 8-byte long, but the structure is at least 30-byte long for char name_main[30];.

Also note that casting results of malloc() family is considered as a bad practice.

Wrong line:

STARS *star = (STARS *)malloc(sizeof(star));

It should be:

STARS *star = malloc(sizeof(*star));
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
4

STARS *star = (STARS *)malloc(sizeof(star));

It's a mistake. sizeof(star) returns size of the pointer, not the structure. Change it to: STARS *star = (STARS *)malloc(sizeof(*star)); to fix your problem.

Nierusek
  • 333
  • 4
  • 13