Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 257
  • Last Modified:

Converting structure object to char*

Hey experts,

 I took the following as a part of an open source code, but it doesn't seem to be working properly:

#define RTP_HDR_SZ 12

typedef struct {
        unsigned int version:2;   /* protocol version */
        unsigned int p:1;         /* padding flag */
        unsigned int x:1;         /* header extension flag */
        unsigned int cc:4;        /* CSRC count */
        unsigned int m:1;         /* marker bit */
        unsigned int pt:7;        /* payload type */
        unsigned int seq:16;      /* sequence number */
        unsigned int ts:32;       /* timestamp */
        unsigned int ssrc:32;     /* synchronization source */
} rtp_hdr_t;

rtphdr.version = 2;
rtphdr.p = 0;
rtphdr.x = 0;
rtphdr.cc = 0;
rtphdr.m = 0;
rtphdr.pt = 24;
rtphdr.seq = (unsigned int)(3);
rtphdr.ts = (unsigned int)time(0);
rtphdr.ssrc = 1094;
char* rtp_header = new char[RTP_HDR_SZ];
memcpy(rtp_header,&rtphdr, RTP_HDR_SZ);
for(i=0;i<RTP_HDR_SZ;i++)
{
      cout<<rtp_header[i]<<" ";
}
cout<<endl;

when I try to print the characters of rtp_header to see if it was actually filled by the contents of rtphdr, they turn out to be some weird characters (and not corresponding to that data that I filled the structure object with...any idea where the problem is??
0
mte01
Asked:
mte01
  • 8
  • 7
  • 2
2 Solutions
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,

Your structure contains binary values that are packed, often several fields to a byte.  When you display the structure by sending it to cout, the C libraries simply copy the bytes.  The do not convert the data as you seem to want.

You're going to have to format the output yourself.  Here's a start.  Just add the fields that you want displayed.

  printf (" Version=%d, pad=%d, extension=%d\n", rtphdr.version, rtphdr.p, rtphdr.x);


Good Luck!
Kent
0
 
sunnycoderCommented:
Hi mte01,

Data has been packed into bit fields and you are printing out chars!! ... get a dump in hex and compare with the information you stored.

Cheers!
Sunnycoder
0
 
mte01Author Commented:
>>Kdo

Yes, I know that, but I guessed there should be something that I could recognize from the printed characters (related to the inputted data)...anyway, what I am doing is that I am sending this char* over a simulated udp channel, and then I am receiving it at the client side...any help on how to extract from the received char* the sequence number for example??
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,

The receiving end is going to have to know the format of the data so that it can unpack it.  Include your structure there and as a debugging test, print the fields to make sure that you're getting what you expect.


Kent
0
 
mte01Author Commented:
>>The receiving end is going to have to know the format of the data so that it can unpack it

Yes, I know

>>Include your structure there and as a debugging test, print the fields to make sure that you're getting what you expect

Thats what I am asking you to help me in, do I also use memcpy to the char* object to an rtp_hdr_t object or what??
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,

That's probably the easiest, though you can explicitly just recast the items on the fly.


Kent
0
 
sunnycoderCommented:
You can use memcpy and it will work if the endianness of both machines is the same ... If they can be different, you need to use htonl at the sender and ntohl at the receiver end, since order of bits gets reversed in that case.
0
 
mte01Author Commented:
This thing is going to drive me crazy:)....I did the following:

rtp_hdr_t rtphdr;
rtp_hdr_t* rtphdr2 = new rtp_hdr_t[RTP_HDR_SZ];

rtphdr.version = 0;
rtphdr.p = 0;
rtphdr.x = 0;
rtphdr.cc = 0;
rtphdr.m = 0;
rtphdr.pt = 0;
rtphdr.seq = (unsigned int)(12);
rtphdr.ts = (unsigned int)(0);
rtphdr.ssrc = 0;
char* rtp_header = new char[RTP_HDR_SZ];
memcpy(rtp_header,&rtphdr, RTP_HDR_SZ);
memcpy(rtphdr2,&rtp_header, RTP_HDR_SZ);
cout<<rtphdr2->seq<<endl;

I am getting an output of 73!! any idea why??
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi sunnycoder,

What hardware and operating systems are you using on both ends?


Kent
0
 
mte01Author Commented:
>>Kdo

Forget the client now...now I am just testing as you see only at the server....I am converting from structure to char* and then back to structure & I am getting different output; I am just testing right now the code of the server on a windows xp pc (AMD Athlon processor) using MS Visual C++ 6.0
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,

The bit signatures of 12 and 73 are completely different (1100 vs 1001001) so I'd like to know what is being displayed.  :)

Can you run your test again setting seq to 0.  Then run it again with seq = 1.  I'd like to see what the results are.

Kent
0
 
mte01Author Commented:
>>Kdo

It's always 73...:D....and the timestamp is always 500.....try it on your pc..(the structure is in the question above)....
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,

That's very telling.  :)  It suggests that what you're displaying is NOT the field that you set!

So..... Let's experiment and see if it's correct in the original structure.  Right before the cout statement, insert this:

cout << rtphdr.seq << endl;

Kent
0
 
mte01Author Commented:
>>memcpy(rtp_header,&rtphdr, RTP_HDR_SZ);

That was the problem....It should be: memcpy(&rtp_header,&rtphdr, RTP_HDR_SZ);

I hate C & C++ because of these things!!.....thanks for your help guys!!
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,

Don't think so.  rtp_header is a pointer so passing the pointer should be corrent.  rtphdr is a structure so you must pass its pointer by prepending the '&'

By the way, you're using C++ syntax.  I've converted to C and run the following code.  Both lines yield 12, 12.

rtp_hdr_t rtphdr;

main ()
{
  char* rtp_header;

  rtphdr.version = 2;
  rtphdr.p = 0;
  rtphdr.x = 0;
  rtphdr.cc = 0;
  rtphdr.m = 0;
  rtphdr.pt = 24;
  rtphdr.seq = (unsigned int)(12);
  rtphdr.ts = (unsigned int)time(0);
  rtphdr.ssrc = 1094;
  rtp_header = (char *)malloc (RTP_HDR_SZ);
  memcpy(rtp_header,&rtphdr, RTP_HDR_SZ);
  fprintf (stdout, " %d, %d\n", RTP_HDR_SZ, sizeof (rtp_hdr_t));
  fprintf (stdout, " %d, %d\n", rtphdr.seq, ((rtp_hdr_t *)rtp_header)->seq);


Kent
0
 
mte01Author Commented:
>>Kdo

Yes, apparently in C++ it needs this reference to the whole char* array (It is working now with me)......and by the way sorry for asking the question here in the C TA
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi mte01,
> sorry for asking the question here in the C TA

That's fine.  Most of the C experts are also fluent with C++.  :)



Kent
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 8
  • 7
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now