February 19th, 2003, 03:15 PM
Equality operator for structs
I have a struct defined (an array of 4 bytes). Variables a and b are both of this same type of struct. C or C++ will not accept this:
if (a == b) do something;
Besides for defining my own overloaded operator, is there any way you can set the compiler to know that they are of the same type and to accept the code above? I would assume the compiler would produce much better code if it just knew they were of the same type, rather than me making an overloaded operator to do it. It surprises me that this type of operator overloadind isn't available by default.
(btw, since the struct I am using is just an array of 4 bytes, there's no 'empty' bits whose randomness could possibly cause a memory compare of two equal structs to fail)
February 19th, 2003, 03:27 PM
structs are stored as pointers to their data. so imho there is no way around overloading operators or defining a "compare()" function :(
for small structs, like 4 bytes, you could cast them to *(int*) and compare the result. but for bigger ones, .... ???
ps. are you Matthew´s brother? just curious...
February 19th, 2003, 07:20 PM
#include <memory.h> Required only for function declarations
#include <string.h> Use either STRING.H (for ANSI compatibility)
Syntax int memcmp( const void *buf1, const void *buf2, size_t count );
buf1 First buffer
buf2 Second buffer
count Number of characters
The memcmp and function compares the first count bytes of buf1 and buf2 and return a value indicating their relationship, as follows:
< 0 buf1 less than buf2
= 0 buf1 identical to buf2
> 0 buf1 greater than buf2
February 20th, 2003, 09:05 AM
Thank you for your replies.
M.Hirsch: Yes, I am Matthew's brother. :) I have to be honest that I did not realize that structs are stored as pointers to their data. One of the major things I dislike about C and its derivatives is that no one (manuals, tutorials, teachers, etc.) seems to explain exactly what is going on when they explain code like structs and multi-dimension arrays. I always like to know what is happening 'under the hood'.
Dereferencing a type cast to a 32-bit int would solve this particular problem... thanks. But, this doesn't solve the lack of a default overloaded operator for structs larger than 32-bits (or for those whose bits are all not used). I guess making a function or overloaded operator is the only way...
dwise1_aol: Thanks, memcmp would also work. As M.Hirsch has pointed out, since structs are pointers, you would have to make sure to deference them first, so you don't compare the pointers themselves.
February 20th, 2003, 09:45 AM
No need to dereference first, since memcmp takes pointers as its arguments.
I have always passed structs using the address operator; eg, memcmp(&struct_a,&struct_b,n). I'll have to experiment with what happens if I just use the name. Off-hand, I'm not sure that it would compile.
February 20th, 2003, 12:21 PM
Both ways should work. Saying that structs are stored as pointers to their data is a bit misleading. Structs are not stored as pointers. You can, and probably will, use a pointer to access them, but you don't have to.
February 20th, 2003, 02:02 PM
Both ways do work. For example, having declared a struct rec:
void Report(struct rec *s);
struct rec A;
Both work. But not:
void Report(struct rec s);
struct rec A;
For that, you will get an "incompatible type for argument" error.
void Report(struct rec *s);
struct rec A;
However, all the library functions I've seen want you to pass them a struct pointer, so the first would be the prefered/more-conventional way.
February 21st, 2003, 07:42 AM
dwise1_aol: Yes, you are right, memcmp takes pointers, so you don't have to deference a pointer first. Since you have shown the structs are not pointers, then you would have to pass the address of the struct with the & operator as you have shown.
3dfxMM: Yes, you are also right, structs are not pointers (as dwise1_aol has proven). Just because you will regularly use pointers to access them, or when you pass them into functions, it does not mean that structs themselves are pointers...
M.Hirsch: I would like to know why you said that strcuts are pointers? I wish to know what you were getting at. Perhaps it was the fact that they are often passed into functions as pointers?
I was under the impression that structs were not pointers. Then you stated that they were, so I assumed that it was yet another detail that is skipped during most explanations of structs, and that they were simply a 'hidden' pointer like arrays (in which you don't have to dereference it, since the compiler takes care of that for you, hiding the fact that it is a pointer - which, I must say, is a horrible thing for any language).
Thanks for the response, guys!
February 21st, 2003, 10:17 AM
I did yet another quick experiment in which I looked at the assembly listing generated by my previous examples -- gcc -S structs.c -- in order to compare their "thunk codes" (what I learned years ago in school as the term for the code that sets up for a function call). Of course, I also had to dig back a long ways to remember how to read assembly.
The code generated by passing an address (eg, Report(&A); ) did a "load effective address" of the structure. The code generated by passing the struct itself (eg, Report(A); ) actually pushed the contents of the structure onto the stack to pass the structure.
What immediately comes to mind is that exactly how the code that the compiler generates actually passes a structure is most likely implementation-dependent, which means that it depends on the compiler and operating environment rather than on the C language itself. I suspect that some implementations do treat a struct name as a pointer while others (eg, MinGW port of gcc to Windows) do not. Hirsch might have learned or worked on an implementation that did.
February 21st, 2003, 12:50 PM
I think the real difference we are seeing here is the difference between C and C++. In C you cannot pass complex data types. You must pass them by reference so compilers typically make allowances, i.e. the address of operator is assumed. In C++ you can pass a pointer to the struct, a reference to the struct, or the struct itself. In the first case, you explicitly reference the passed struct via a pointer. In the second case, it is passed by reference but you treat it as a struct on the other end. In the third case, it is passed directly on the stack and you treat it as a local variable. The first two allow for changes to the original struct while the last one does not.
February 21st, 2003, 01:23 PM
3dfxMM: Your explanations of the 3 ways to pass a struct into a function in C++ are quite correct. But, I don't believe there are any differences from C to C++ (in regards to structs being pointers or not). I.e. the only differences is what C does and doesn't allow (like you said: "In C you cannot pass complex data types."). So, basically, if you are priveleged enough to be using C++, then you have more options on how to access structure variables from within functions. But nothing is really different about implementations. I would be very surprised (and displeased) to find an implementation of C that stores struct in a different way. I can't see how this wouldn't cause mass confusion and tons of programming errors.
If structs were pointers, there would be someway of accessing that pointer (like we can do with pointers that are made when we declare arrays), and we would be able to tell when a struct is declared that the stuct and its pointer both take up memory. I am fairly certain we will find that this is not the case with structs.
February 21st, 2003, 03:20 PM
Pointers are pointers. It doesn't matter if you declare an array or a struct. What you get in memory is an array or a struct, not a pointer. In the case of arrays, C/C++ lets you use the name of the array as a sort of pseudo-pointer. There isn't actually a pointer stored anywhere. It just uses the array name as an alias for &array.
February 22nd, 2003, 12:26 PM
3dfxMM, thank you for that explanation!! Finally someone has explained this properly.
So, arrays aren't pointers, and there is no memory allocated to store this pointer. This is exactly how I used to think was happening 'under the hood' (since it is very intuitive to do it this way) until I decided to look it up and find out for sure, and then I was mislead every place I looked.
Why C chooses to have an alias for the name of the array is beyond me. Why not treat all names in the same manner, like Pascal does? If you want a pointer to it, use &, the operator that is specifically made to get the pointer to a variable. Logically, it makes much more sense, and no one would ever be confused when explaining arrays and pointers.
February 22nd, 2003, 01:12 PM
I remember hearing once that the ANSI C committee was asked why they were allowing a similar ambiguity (I don't remember the exact one) and do you know what their answer was?
February 22nd, 2003, 02:46 PM
That's simply amazing. It really blows my mind that there are so many things wrong with this language.