Little confused on how to used pointers with this?

Mar 16, 2009 at 10:32am
I understand the problem itself. And I understand what happens by pulling out every 4 values which is what I'm meant to do I'll explain that in a second but here's the problem:

11: Below is a character array, representing what you might receive from a network stream. It is formatted in the following way: int, float, float, float, int, float, float, float etc. Convert the array into the appropriate data types and output the result. It should be obvious if you are correct or not.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char stream[] = {
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 
  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40, 
  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 
  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 
  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x40, 
  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x10, 0x41, 
  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 
  0x00, 0x00, 0x30, 0x41, 0x00, 0x00, 0x40, 0x41, 
  0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x41, 
  0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x70, 0x41, 
  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 
  0x00, 0x00, 0x88, 0x41, 0x00, 0x00, 0x90, 0x41, 
  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 
  0x00, 0x00, 0xa0, 0x41, 0x00, 0x00, 0xa8, 0x41, 
  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x41, 
  0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xc0, 0x41, 
  0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x41, 
  0x00, 0x00, 0xd0, 0x41, 0x00, 0x00, 0xd8, 0x41, 
  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x41, 
  0x00, 0x00, 0xe8, 0x41, 0x00, 0x00, 0xf0, 0x41
};


Ok so it says the pattern is int, float, float, float .. and so on.
So the first 4 joined would be
(int)0x01 + 0x00 + 0x00 + 0x00 = 1;
the second would be
(float)0x00 + 0x00 + 0x80 + 0x3f = -65.00
and the third would be
(float)0x00 + 0x00 + 0x00 + 0x40 = 64.00


I think what I'm saying is correct - but now the main issue is I have to use a pointer to pull the values out to do this problem. Little confused on how to attack the problem?

Thanks guys,
Myth.
Mar 16, 2009 at 10:57am
If you have to use pointers, it could be for a pointer conversion:
eg: int *i = (int*)stream;
But the result of that would depend on the computer's endianness and architecture.
Mar 16, 2009 at 11:02am
But that's only grabbing one value at a time, so how would i grab 4 and put them together by using that exactly?
Mar 16, 2009 at 11:14am
int *i = (int*)stream;
Sets the position of i to the position of stream with the difference that i would read integers instead of chars so i[n] return the value corresponding to the integer with the byte values contained in stream starting from n*sizeof(int)

For example 4 bytes little endian int:
*i is the same as (stream[0]) + (stream[1]<<8) + (stream[2]<<16) + (stream[3]<<24)
Mar 16, 2009 at 11:24am
Ok so if we are setting i to the position of stream. Then doing a c-style cast so we can read ints instead of chars. But with you saying that i[n] would return the first value corresponding to the int - would mean its getting the first 4 bytes so it technically fills the int value of i - as we are asking for 4 bytes pulling out the first 4 elements in the array?

Sorry this question has just thrown my knowledge around a little.
Mar 16, 2009 at 11:50am
Think that the bytes in stream instead of being read as single chars they are read as something like this:

0x01, 0x00, 0x00, 0x00, < i[0] - 0x00000001
0x00, 0x00, 0x80, 0x3f, < i[1] - 0x3f800000
0x00, 0x00, 0x00, 0x40, < i[2] - 0x40000000
0x00, 0x00, 0x40, 0x40, < i[3] - 0x40400000
0x02, 0x00, 0x00, 0x00, < i[4] - 0x00000002
0x00, 0x00, 0x80, 0x40, < ...
0x00, 0x00, 0xa0, 0x40,
...


So, you have to take as int i[0] and i[4], which will be 1 and 2
(I'm always assuming the small endian 4b ints )

each element of i contains 4 elements of stream
Last edited on Mar 16, 2009 at 11:50am
Mar 16, 2009 at 12:12pm
Ok this makes a lot more sense now as the code:
1
2
3
4
printf("Decimal Value = %d | Pointer Value = %p\n", i[0], i[0]);
printf("Decimal Value = %d | Pointer Value = %p\n", i[1], i[1]);
printf("Decimal Value = %d | Pointer Value = %p\n", i[2], i[2]);
printf("Decimal Value = %d | Pointer Value = %p\n", i[3], i[3]);


Gives me all the correct memory addresses as you said in the above post.

The problem is now for the 2, 3 and 4th values here as they are meant to be floats I gather the output is wrong?

Decimal Value = 1 | Pointer Value = 00000001
Decimal Value = 1065353216 | Pointer Value = 3F800000
Decimal Value = 1073741824 | Pointer Value = 40000000
Decimal Value = 1077936128 | Pointer Value = 40400000


So lets say we use %f instead for a float the value looks correct now but I gather I shouldn't do it this way as going by the pointers address it looks like it's invalidated the pointer in a way?

1
2
3
4
printf("Decimal Value = %d | Pointer Value = %p\n", i[0], i[0]);
printf("Decimal Value = %f | Pointer Value = %p\n", i[1], i[1]);
printf("Decimal Value = %f | Pointer Value = %p\n", i[2], i[2]);
printf("Decimal Value = %f | Pointer Value = %p\n", i[3], i[3]);

Decimal Value = 1 | Pointer Value = 00000001
Decimal Value = 0.007813 | Pointer Value = 3F23478C
Decimal Value = 2.000000 | Pointer Value = 3F23478C
Decimal Value = 32.000008 | Pointer Value = 3F23478C


So the values look correct now but the pointer is spiting out gibberish

Sorry I took a while to reply as the previous post i hit f5 on so it reloaded the page after I was nearly done.. Anyway should i be using a pointer to a float to grab out these other values?

Or is there something else I should do?

Thanks a heap Bazzy,
Myth.

EDIT: Fixed post Wasn't displaying correctly.
Last edited on Mar 16, 2009 at 12:14pm
Mar 16, 2009 at 12:39pm
I got the feeling I'm way off with what I'm doing. The first lot of ints display fine but i think the floats are way out..?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>

int main()
{
	//int, float, float, float, int, float, float, float...
	char stream[] = {
		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 
		0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40, 
		0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 
		0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 
		0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x40, 
		0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x10, 0x41, 
		0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 
		0x00, 0x00, 0x30, 0x41, 0x00, 0x00, 0x40, 0x41, 
		0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x41, 
		0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x70, 0x41, 
		0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 
		0x00, 0x00, 0x88, 0x41, 0x00, 0x00, 0x90, 0x41, 
		0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 
		0x00, 0x00, 0xa0, 0x41, 0x00, 0x00, 0xa8, 0x41, 
		0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x41, 
		0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xc0, 0x41, 
		0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x41, 
		0x00, 0x00, 0xd0, 0x41, 0x00, 0x00, 0xd8, 0x41, 
		0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x41, 
		0x00, 0x00, 0xe8, 0x41, 0x00, 0x00, 0xf0, 0x41
	};

	//40 Overall Values
	int iOne[10];
	float fOne[10];
	float fTwo[10];
	float fThree[10];

	int *i = (int*)stream;

	int temp = 0;
	printf("Int\n");
	for(int c = 0; c < 40; c += 4)
	{
		iOne[temp] = i[c];
		printf("%d\n", iOne[temp]);
		temp++;
	}
	temp = 0;
	printf("Float One\n");
	for(int c = 1; c < 41; c += 4)
	{
		fOne[temp] = (float)i[c];
		printf("%f\n", fOne[temp]);
		temp++;
	}
	temp = 0;
	printf("Float Two\n");
	for(int c = 2; c < 42; c += 4)
	{
		fTwo[temp] = (float)i[c];
		printf("%f\n", fTwo[temp]);
		temp++;
	}
	temp = 0;
	printf("Float Three\n");
	for(int c = 3; c < 43; c += 4)
	{
		fThree[temp] = (float)i[c];
		printf("%f\n", fThree[temp]);
		temp++;
	}

    return 0;
}


Output:
Int
1
2
3
4
5
6
7
8
9
10
Float One
1065353216.000000
1082130432.000000
1088421888.000000
1092616192.000000
1095761920.000000
1098907648.000000
1100480512.000000
1102053376.000000
1103626240.000000
1105199104.000000
Float Two
1073741824.000000
1084227584.000000
1090519040.000000
1093664768.000000
1096810496.000000
1099431936.000000
1101004800.000000
1102577664.000000
1104150528.000000
1105723392.000000
Float Three
1077936128.000000
1086324736.000000
1091567616.000000
1094713344.000000
1097859072.000000
1099956224.000000
1101529088.000000
1103101952.000000
1104674816.000000
1106247680.000000
Last edited on Mar 16, 2009 at 12:41pm
Mar 16, 2009 at 12:42pm
i[n] is not a pointer. &i[n] is.

why not just overlay a struct?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Element {
    int x;
    float f1, f2, f3;

    template< typename charT, typename Traits > friend
    std::basic_ostream<charT, Traits>& operator<<(
       std::basic_ostream<charT, Traits>& os, const Element& e )
       { return os << e.x << ", " << e.f1 << ", " << e.f2 << ", " << e.f3; }
};

Element* e = static_cast<Element*>( stream );

for( ; /* some end condition */; ++e )
    std::cout << *e << std::endl; 


(with boost::lambda the for() loop can be replaced by std::foreach with a lambda expression to output the result; it would look something like:

 
foreach( e, e + numElems, std::cout << *boost::lambda::_1 << std::endl );

Mar 16, 2009 at 12:50pm
I see what your structs doing and dame thats pretty awesome. But for displaying it i get:
error C2440: 'initializing' : cannot convert from 'char [160]' to 'Element *'

Looking into it atm

C2440 can be caused if you attempt to convert a pointer to member to void*
Says msdn
Last edited on Mar 16, 2009 at 12:55pm
Mar 16, 2009 at 1:00pm
A reinterpret_cast works

Ok with that cast I got this outputting now ..
1, 1, 2, 3
2, 4, 5, 6
3, 7, 8, 9
4, 10, 11, 12
5, 13, 14, 15
6, 16, 17, 18
7, 19, 20, 21
8, 22, 23, 24
9, 25, 26, 27
10, 28, 29, 30


If this is in fact the correct answer whats the point in the floats?
Last edited on Mar 16, 2009 at 10:39pm
Mar 16, 2009 at 3:34pm
Looks right to me.

I just went to
http://babbage.cs.qc.edu/IEEE-754/Decimal.html

and typed in 1.0 for the decimal value and the single precision equivalent in hex is 3F800000, which matches the first float in the byte stream above.

Also, the problem statement above does say that it should be obvious if you've got it right.

Mar 16, 2009 at 10:39pm
Sorry the above post looks a little weird, i forgot to delete the first line of the post as they were two separate. Point being was i was just making sure they are not meant to display as 27.00 etc.

Thanks jsmith.
Mar 17, 2009 at 4:02am
Just posting this back I figured out out before but I did it like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
int *ptrInt = (int*)stream;
for(int i = 0; i < 40; i += 4)
{
    printf("%d\n", ptrInt[i]);
}

float *ptrFloat = (float*)stream;
for(int i = 1; i < 41; i += 4)
{
    printf("%f\t", ptrFloat[i]);
    printf("%f\t", ptrFloat[i + 1]);
    printf("%f\n", ptrFloat[i + 2]);
}


I used your way as well Bazzy so thank you for that. Gave me a better idea on how to lay it out and step through it to see exactly how it works.

So thank you :)
Topic archived. No new replies allowed.