1
struct Users{
        int id;
        char msg[];
};

int nUsers;

struct Users users[10];

void connectUser(struct Users user){
     if(nUsers<10){
        for(int i=0;i<10;i++){
                if(users[i]==NULL){
                        users[i]=user;
                        printf("user %d connected!\n", user.id);
                        nUsers++;
                }
        }
    }else
        printf("number of users reached!\n");
}

That's my code and when I try to compile, comes with error:

[s3450124@csitprdap01 ~]$ gcc -std=c99 socketserver.c -o socketserver
socketserver.c: In function ‘connectUser’:
socketserver.c:24: error: invalid operands to binary == (have ‘struct Users’ and ‘void *’)
socketserver.c:21: note: The ABI of passing struct with a flexible array member has changed in GCC 4.4
socketserver.c: In function ‘disconnectUser’:
socketserver.c:37: error: incompatible types when assigning to type ‘struct Users’ from type ‘void *’

Every time I try to compile, these errors comes up. Can you guys help me?

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
JamesThiago
  • 33
  • 1
  • 8
  • Remove `if(users[i]==NULL)`. The other error is in `disconnectuser`. Oh. Remove `users[i]=NULL` from `disconnectuser`. `NULL` is used for pointers. You can't assign/compare `users[i]`(which *isn't* a pointer) with `NULL`. – Spikatrix May 09 '15 at 10:55

2 Answers2

3

The type of users[i] when say i = 0 is Struct Users. It is NOT a pointer so cannot have a value of NULL. That is what your compiler is complaining about. you are checking if the value is NULL when it cannot be. You only check for NULL when comparing pointers.

// you already check here that you do not exceed bounds of array - 10
for(int i=0;i<10;i++){
    users[i]=user;
    etc
Angus Comber
  • 9,316
  • 14
  • 59
  • 107
1

As noticed by @CoolGuy, the problem is due to if(users[i]==NULL). Since users is an array of struct Users, users[i] is a struct Users and a struct Users cannot be compared to NULL.

A pointer to a struct Users, declared as a struct Users* can be compared to NULL.

Now that the problem is found, how to solve it ?

  • The straightforward answer is to use a convention. For instance, let's say that users[i].id==0 means that this user is disconnected. At the beginning of the program, the users must be initialized :

    for(i=0;i<10;i++){
      users[i].id=0;
    }
    

    As the user is connected a free slot must be found :

     for(int i=0;i<10;i++){
            if(users[i].id==0){
                    users[i]=user;
                    printf("user %d connected!\n", user.id);
                    nUsers++;
                    break;
            }
      }
    

    Do not forget the break statement : the user must be connected only once ! As the user is diconnected, users[i].id=0;

  • The other option is to declare struct Users *users[10];. Hence users is an array of pointers to struct Users. Again, these pointers must be initialized :

    for(i=0;i<10;i++){
      users[i]=NULL;
    }
    

    As a new user is connected, some memory must be allocated or a valid pointer must be provided.

      for(int i=0;i<10;i++){
            if(users[i]==NULL){
                    users[i]=malloc(1*sizeof(struct user));
                    if(users[i]==NULL){printf("malloc failed\n");exit(1);}
                    users[i]->id=user.id;
                    printf("user %d connected!\n", user.id);
                    nUsers++;
                    break;
            }
      }
    

    Using users[i]=&user; would not be a good idea, because user is a local variable : it does not exist out of the function connectUser(struct Users user). If you do so, it can trigger an undefined behavior somewhere else.

    As the user is disconnected, the memory must be freed and the pointer must be set to NULL : free(users[i]);users[i]=NULL;

francis
  • 9,525
  • 2
  • 25
  • 41
  • Thanks for the answer bro! So, I'll try to explain, in the main() function, there will be a menu(connect, disconnect, deposit, retrieve, inquire)...this program is a kind of messenger, so, when u choose to connect, you will be connected in a "chat room", so, execute the function connect() and each user will have an id when enter in the chat room...so, i want something like, when connect, insert this user in a vector(chat room) and give an ID for him, and when you want to disconnect, delete from the chat room and so on....so, do u have a better solution for this? or u think this is enough? – JamesThiago May 09 '15 at 12:32
  • I was thinking in your solution, but I though that I will just initialize the user when connected.... – JamesThiago May 09 '15 at 12:34
  • A array featuring a fixed size may not be the best way to go...What if more than 10 users wanted to join the chat ? A user may be involved in many chats and a chat may involve many users : what if each user had a list of pointers to chats and each chat had a list of pointers to users ? C++ containers such as a List or a vector could be better (performance, easier to maintain) . You can build something similar in C http://stackoverflow.com/questions/4694401/how-to-replicate-vector-in-c – francis May 09 '15 at 12:55
  • By the way, do you have any suggestion for me how can i give an id for each user? like, I was thinking in 1 for the firs user connected , 2 for the second an etc... – JamesThiago May 09 '15 at 13:50
  • The id of a user in a chat can be `i+1` by doing `users[i]->id=i+1;`. That way, two users can't share the same id in the chat. Since you are using an additionnal field `connected`, you can even use `users[i]->id=i;` – francis May 09 '15 at 14:22
  • I just want to insert in the vector is the position is free....How can i check if the position is free? because I was trying to do this in the beginning like: void connectUser(){ if(nUsers<10){ for(int i=0;i<10;i++){ if(users[i]==NULL){ idGiven++; users[i].id=idGiven; users[i].connected=1; printf("user %d connected!\n", users[i].id); nUsers++; break; } } }else ... ... – JamesThiago May 09 '15 at 14:32