0

I need help. I have an unsigned char * and say I have a struct

struct{
     int a=3;
     char b='d';
     double c=3.14;
     char d='e';
     } cmp;
unsigned char input[1000]; 
l= recv(sockfd,input , sizeof(cmp),0);

I want to compare cmp and input. What is the fastest way?

Thanks a lot in advance.

Natan Streppel
  • 5,759
  • 6
  • 35
  • 43
user3260595
  • 53
  • 1
  • 8
  • 2
    This example is in C (although it is labeled C++). But the simple answer is that you can't; you have to marshal the byte array into an instance of the struct, according to the protocol specifications. – James Kanze Apr 28 '14 at 17:19
  • I see. Would this work obj=(cmp *) input; if(obj==cmp) { //code } ? – user3260595 Apr 28 '14 at 17:21
  • You'll probably have to pack the struct. – Alex Apr 28 '14 at 17:23
  • @user3260595 Of course not. And packing the struct doesn't change anything. You're example code uses a `recv`, so you're reading an externally defined protocol from a socket. What makes you think that there's any relationship between the way the protocol represents an `int` and the way it is represented inside your machine? (FWIW: the standard Internet protocols do _not_ represent an `int` the same way as the Intel architecture does.) – James Kanze Apr 29 '14 at 08:17

3 Answers3

2

If the compiler guarantees that there are no gaps between fields in the struct (usually happen due to packing) or you can use a #pragna to cancel any such gaps, then you can compare by either:

memcmp(&cmp, input, sizeof(stuct ThesSruct));

Or, my preferred:

cmp == *(struct TheStruct *)input // provided the struct doesn't contain pointers.

But a much safer way would be to compare it on a field by field basis. And even more, prepare special functions for extracting ints, floats, etc.. from the raw input. For example, extracting an int at index n may be as simple as

*(int *)&input[n]

But it might be more complicated, like shifting chars at 8, 16, 24 bits.

In short, accessing the communication data must be done with the most robust way, checking every basic element and not assuming anything.

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
0

Give reinterpret_cast a try. This will allow you to arbitrarily cast the char * to a cmp * http://msdn.microsoft.com/en-us/library/e0w9f63b.aspx

Beed
  • 460
  • 3
  • 10
0

In the general case James Kantzes comment is correct, you can't compare like that. This is , among other things, due to byte padding.

However in the specific case with the following assumptions;

  • The sender is on the same cpu architecture as the receiver
  • The sender is using the same compiler and linker as the receiver
  • The applications are compiled with the same compiler/linker flags
  • ...other things...you get the gist.
  • The sender is sending it straight from the struct.

    cmp c{ ...set variables... }; send(sockfd, (char*)&c, sizeof(c));

So in short, this is a very brittle way of transporting structs and you shouldn't do it for anything except simple tests or quick hacks.

dutt
  • 7,909
  • 11
  • 52
  • 85