struct sockaddr_in stSockAddr; ... bind(SocketFD,(const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in)); 

Why do I need to bring stSockAddr to (const struct sockaddr *)?

  • one
    Simply because the type of const struct sockaddr * registered in the prototype of the bind function ( sockaddr_in is a special case of the struct sockaddr , look in / usr / include / ... socket.h, in.h, etc. (though there is a rather complicated architecture-dependent file structure)). - avp
  • @avp, so what happens? Here there is an object sockaddr_in, and there are 4 fields in it, then it is brought to sockaddr, and 2 fields become in it, but how are unnecessary fields cut off and the necessary fields remain? Maybe there are some ready-made examples somewhere in which the implementation is shown, how does it look like explicitly? - xinakapu
  • 2
    @xinakapu, in this case, no one throws out any fields. You simply tell the compiler that at the given address there is a structure of type struct sockaddr and nothing more than that . Actually, the memory address is passed to the function. In fact, how to interpret data (real chains of bits) depends on the function being called. On the first field, bind will determine which of the internal implementations (IPv4, IPv6, etc.) should be called and give it your address. And already that will interpret this data as it is programmed. - avp
  • one
    You just need to distinguish between "real" type conversions, of the form: (double) 1/2 // we get 0.5 when the compiler converts the bit representation of a number from one type (from to from int ) to another (to double ) or long l = 123456789; int x = (unsigned char) l; // in x, the low byte of l when the size of the integer type changes, from the pointer type casts (I would call it a “fictitious” cast (as “in science” they call it - I don't remember)). In the latter case (like with bind ), in fact, nothing (except for the "cheating" of the compiler) does not occur with the bit representation of the variable. - avp
  • one
    IMHO it will be a problem with writing loops on arrays of such structures. For example: struct x1 {int a, b; }; struct x2 {int a, b; double z; }; struct x2 a [10] = {...}; f ((struct x1 *) a, sizeof (a [0]), 5); In a function that expects an array of type struct x1 , you have to pass the size of the actual structure and write the loop like this: f (struct x1 * p, size_t ps, int n) {for (int i = 0; i <n; i ++) f2 (( struct x1 *) ((char *) p + i * ps)); // instead of f2 (p [i]); } This is for passing to f2 (struct x1 *) correct address of the struct x1 to which struct x2 . - avp

1 answer 1

Sockets arranged cleverly, but beautiful. There is one basic structure and several "heirs". Their difference - they start the same, but the endings are different. It's all like with classes, only manually. Let's look at the definition of these two structures:

 struct sockaddr { ushort sa_family; char sa_data[14]; }; struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; 

(Honestly copied from the site of Microsoft , although they could be copied in other places.)

That is, if it were on classes, then the first one was basic, and the second was an heir with two additional fields.

Now closer to the goal. Some socket functions are basic, they work with just sockets. And there are sighting - for example, working with tcp / udp sockets (there are other types of sockets - for example, file descriptors, pipes and others). The basic functions work with the base structure, sighting - with its structure. Since the beginning of the structure is the same, then the basic functions are "sideways" at the end, the main thing is to know the size (in case you need to copy, transfer somewhere further).

bind is such a basic function.

Since c ++ is a typed language, and on structures "manually inherited", it is necessary to lead "to the basic structure".

  • Thanks, for reasons it became clear now. But how does this reduction of an object of one structure to an object of another work? I read your detailed answers about this somewhere, but I already forgot and cannot find it. That is, when and what kind of implicitly called constructor or something like that. By the way, will such code not work on C? - xinakapu
  • one
    The structure in memory is just an array of bytes, no more, no less. Referring to a structure field is simply referring to some part of this array. Therefore, in fact, it is possible to replace the structure, as long as the fields “overlap” correctly. Therefore, the main thing is to correctly decompose the field - that's all the cast. - KoVadim