-2

In C arrays are not assignable, but in line 36 (line that I have also commented on) I assign a value to the array name without getting any errors. Why is this happening? Also, aside from this baffling thing I would really appreciate if you checked whether my freeStudents function is working properly. Thanks for your time guys!

#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME 50

struct students
{
    char name[MAX_NAME];
    float average;
};

void storeStudents(struct students *lst, int n);
void printStudents(struct students *lst, int n);
void freeStudents(struct students *lst);

int main(void)
{
    int n;
    printf("How many students you wanna store? ");
    scanf("%d", &n);
    struct students *list;
    list = (struct students *)malloc(n*sizeof(struct students));

    storeStudents(list,n);
    printStudents(list,n);
    freeStudents(list);

    return 0;
}

void storeStudents(struct students *lst, int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        printf("Name of student: ");
        scanf("%s", &(lst[i].name)); //In C arrays are not assignable, so why is this line working?
        printf("Average of student: ");
        scanf("%f", &(lst[i].average));
    }
    printf("\n");
}

void printStudents(struct students *lst, int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        printf("Name: %s\tAverage: %.2f", lst[i].name, lst[i].average);
        printf("\n");
    }
}

void freeStudents(struct students *lst)
{
    free(lst);
}
Costantino Grana
  • 3,132
  • 1
  • 15
  • 35
Mike th
  • 13
  • 5
  • 2
    If you enable compiler warnings, you'll see what's really going on: https://ideone.com/7JPJFH – Oliver Charlesworth Dec 02 '17 at 21:28
  • Oliver Charlesworth codeblocks compiler gives me no warnings/errors whatsoever.. – Mike th Dec 02 '17 at 21:31
  • What does it mean that "In C arrays are not assignable"? What an array contains is obviously mutable, so you can assign a new value to an element of it. Where did you read that "arrays are not assignable"? – Lasse V. Karlsen Dec 02 '17 at 21:33
  • 1
    @LasseVågsætherKarlsen - Arrays are indeed non-assignable, in the sense that you can't do `a = b;` if `a` is an array type. – Oliver Charlesworth Dec 02 '17 at 21:36
  • Lasse Vågsæther Karlsen, I read that arrays are not assignable in c in a stackoverflow post (best voted answer). Check it out: https://stackoverflow.com/questions/1292586/char-array-in-a-struct-incompatible-assignment – Mike th Dec 02 '17 at 21:36
  • @Miketh Codeblocks does give warnings "main.c|36|warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[50]' [-Wformat=]|" :) – Burstful Dec 02 '17 at 21:36
  • @CoreyLakey If you don't escape the `*`, the comment is incomprehensible. – EOF Dec 02 '17 at 21:40
  • @CoreyLakey Well my codeblocks doesn't show any warnings, maybe I might not have configured codeblocks well since i'm a rookie, but in any case shouldn't we expect an error? why is it working...? – Mike th Dec 02 '17 at 21:41
  • @OliverCharlesworth While that may be, that's not what is happening here. The 36th line here is `scanf("%s", &(lst[i].name)); //In C arrays are not assignable, so why is this line working?`, which clearly assigned an element of the array, not *the* array. – Lasse V. Karlsen Dec 02 '17 at 21:49
  • @LasseVågsætherKarlsen The array I mean is _name[MAX_NAME]_ . How can the array _name[MAX_NAME]_ change all at once? it's not like i'm saying _name[0]="a"_ , _name[1]="b"_ , ... , . what (I think) my program does is that it assigns all at once _name_ = "abcd" which is an error.. – Mike th Dec 02 '17 at 22:06
  • Oh, I'm sorry. I misunderstood your question completely. I actually *read* your question you see, and you mention line 36, and even mark this with a comment. I am so sorry that I didn't understand that you meant something completely different. Best of luck getting your new question answered though. – Lasse V. Karlsen Dec 02 '17 at 22:13
  • @LasseVågsætherKarlsen It's okay, thanks for taking the time to answer anyway! – Mike th Dec 02 '17 at 22:21
  • I'm terribly sorry you didn't understand what I meant by that. Your question, as asked, explicitly mentions line 36, which even contains a comment, and now the accepted answer doesn't even relate to that, but instead talks about assigning whole arrays, which line 36 doesn't even do. As such I'll keep my close vote in the hopes that enough people clost this as "what the heck?" because clearly the question doesn't related to the described solution at all. – Lasse V. Karlsen Dec 02 '17 at 22:35
  • @LasseVågsætherKarlsen Just for the records, the answer explicitly address the problem and clarifies that there's no assignment in line 36. – Costantino Grana Dec 03 '17 at 19:09
  • @Miketh Remember to mark the answer as accepted if it solves your problem. – Costantino Grana Dec 03 '17 at 19:11

1 Answers1

2

In C you cannot assign an array to another, basically because an array cannot be on the left side of an assignment. So the following:

char a[5] = { 1, 2, 3, 4, 5 };
char b[5];
b = a; 

is not correct. But of course this is correct:

b[0] = a[0]; 
b[1] = a[1]; 
b[2] = a[2]; 
b[3] = a[3]; 
b[4] = a[4]; 

because b[0] (which is *(b+0)) is not an array, but a char.

Now to the point. In line 36 you do:

scanf("%s", &(lst[i].name));

A comment before dissecting: don't use scanf() for user input.

Anyway, the function is a variable argument function, meaning that it will happily accept anything you pass as the second parameter. But what you should be passing there is a char* (a pointer to char). Why? Because the guys who devised the function decided so: when the format string has a %s you need a char* parameter.

What type is &(lst[i].name)? The expression lst[i].name is of type char[50] (an array of 50 char), so &(lst[i].name) is "the address of an array of 50 char", which in C is called "a pointer to an array of 50 char" or in C syntax char(*)[50]. Which is not a char*. So this is wrong or better Undefined Behavior.

What should the correct version have been? Well, this:

scanf("%s", lst[i].name);

because when you use an array in an expression it decays to a pointer to the first element.

Ok, but why does it work anyway? It may work on some compilers, because they just pass the address of the array in both cases, so on the stack both things are the same number.

Finally, no array is "assigned" in this expression statement, thus the question in fact makes no sense in the first place. Or better, the function receives the address of the array and fills it using that pointer to the first element. Another funny thing is that you cannot have functions with array parameters. Only pointers.

Costantino Grana
  • 3,132
  • 1
  • 15
  • 35