Understand piece of code.....

T

Terry Andersen

Could anyone please help me understand what is going on in the code below. A
short explanation would be nice.....

Best Regards
Terry

struct mystruct {
unsigned char testchar;
unsigned short testshort;
unsigned char anothertestchar;
};



void testfunc(unsigned char* mymemlocation) {

struct mystruct *thedata = (struct mystruct*) mymemlocation;

thedata->testchar = 0x55;
thedata->testshort = 0xFFFF;
thedata->anothertestchar = 0x11;

}
 
G

Greg P.

Terry Andersen said:
struct mystruct {
unsigned char testchar;
unsigned short testshort;
unsigned char anothertestchar;
};
You have created a structure, which is something like a container for
arbitrary types and related variables.
void testfunc(unsigned char* mymemlocation) {

struct mystruct *thedata = (struct mystruct*) mymemlocation;
This is a function that passes a pointer for a memory location to store your
struct. This is _nasty code_. Never assume that unsigned char* is equal to
anything else but unsigned char. The parameter should be void*
mymemlocation. Most likely, this function is requiring that you supply your
own allocated pointer for manipulation of the structure on the heap.
thedata->testchar = 0x55;
Pointers use -> or (*struct). to access members if they are pointers.
Otherwise they use a period '.'. This line here sets testchar to the letter
'U', which is 0x55 in hexadecimal. 0x before a value indicates that it is
hexadecimal. You could have also made it equal to 85.
thedata->testshort = 0xFFFF;
This sets testshort, the unsigned short int from the structure, to 65535.
thedata->anothertestchar = 0x11;
This sets the other character to 17, which is an unprintable (not
alpha-numeric) digit.
There should be a semicolon here.
 
T

Terry Andersen

Greg P. said:
You have created a structure, which is something like a container for
arbitrary types and related variables.

This is a function that passes a pointer for a memory location to store your
struct. This is _nasty code_. Never assume that unsigned char* is equal to
anything else but unsigned char. The parameter should be void*
mymemlocation. Most likely, this function is requiring that you supply your
own allocated pointer for manipulation of the structure on the heap.

Pointers use -> or (*struct). to access members if they are pointers.
Otherwise they use a period '.'. This line here sets testchar to the letter
'U', which is 0x55 in hexadecimal. 0x before a value indicates that it is
hexadecimal. You could have also made it equal to 85.

This sets testshort, the unsigned short int from the structure, to 65535.

This sets the other character to 17, which is an unprintable (not
alpha-numeric) digit.

There should be a semicolon here.

Thanks a lot. Would this mean that testchar, testshort and anothertestchar
are stored from memory location mymemlocation and further? If mymemlocation
would be like:

unsigned char TheBuffer[100];
//and you called the testfunc with:

testfunc(TheBuffer[50]);

/*
Would TheBuffer then look like:
TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11
???
*/

Best Regards
Terry
 
G

Greg P.

Terry Andersen said:
Thanks a lot. Would this mean that testchar, testshort and anothertestchar
are stored from memory location mymemlocation and further? If mymemlocation
would be like:

unsigned char TheBuffer[100];
//and you called the testfunc with:

testfunc(TheBuffer[50]);
No. First of all you would not pass TheBuffer to testfunc() with the
subscript on it. It would be passed as

testfunc(TheBuffer);

instead. The name of an array is a pointer to the first value, which you
could later iterate over.
Would TheBuffer then look like:
TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11
No. I think you mean: would the buffer[index] hold the values from the
function as array indexes. No.

With this code, you are now overwriting the boundary of your array, which
ends at 49. Remember that arrays start from 0, and go to length-1. So if I
had an array like:

char array[45];

I can only access array[0] to array[44].

If you access anything outside of your array's range, it is undetermined
behavior, but most likely you will overwrite another program's (running on
your machine) data causing a crash or something nastier.

To get back to your question about whether the members from the struct are
part of the array, no. You are attempting to pass an unsigned char to your
function as a form of memory reservation. Instead use:

struct mystruct p_yourstruct* = (struct mystruct) malloc(sizeof(mystruct));

to get the memory. For example:
---------------------------------------------
struct mystruct
{
unsigned char testchar;
unsigned short testshort;
unsigned char anothertestchar;
};

struct mystruct* mem_location = (struct mystruct) malloc(sizeof(mystruct));

void testfunc(struct mystruct* mymemlocation)
{
thedata->testchar = 0x55;
thedata->testshort = 0xFFFF;
thedata->anothertestchar = 0x11;
};
-----------------------------------------------------------------------
malloc() allocates memory for your struct. You need to call
free(mem_location) to free up the memory before your program terminates, or
else you will get memory leak.

To use the code you would pass:

testfunc(mem_location);

and then you could goof off with the variables.

Try not to mix apples and oranges. The only thing you should pass to hold a
struct is another struct of the same type. It would be like passing a car
variable to a function that uses the car to hold a mansion.

Any more questions? =)
 
T

Terry Andersen

Greg P. said:
Terry Andersen said:
Thanks a lot. Would this mean that testchar, testshort and anothertestchar
are stored from memory location mymemlocation and further? If mymemlocation
would be like:

unsigned char TheBuffer[100];
//and you called the testfunc with:

testfunc(TheBuffer[50]);
No. First of all you would not pass TheBuffer to testfunc() with the
subscript on it. It would be passed as

testfunc(TheBuffer);

instead. The name of an array is a pointer to the first value, which you
could later iterate over.
Would TheBuffer then look like:
TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11
No. I think you mean: would the buffer[index] hold the values from the
function as array indexes. No.

With this code, you are now overwriting the boundary of your array, which
ends at 49. Remember that arrays start from 0, and go to length-1. So if I
had an array like:

char array[45];

I can only access array[0] to array[44].

If you access anything outside of your array's range, it is undetermined
behavior, but most likely you will overwrite another program's (running on
your machine) data causing a crash or something nastier.

To get back to your question about whether the members from the struct are
part of the array, no. You are attempting to pass an unsigned char to your
function as a form of memory reservation. Instead use:

struct mystruct p_yourstruct* = (struct mystruct) malloc(sizeof(mystruct));

to get the memory. For example:
---------------------------------------------
struct mystruct
{
unsigned char testchar;
unsigned short testshort;
unsigned char anothertestchar;
};

struct mystruct* mem_location = (struct mystruct) malloc(sizeof(mystruct));

void testfunc(struct mystruct* mymemlocation)
{
thedata->testchar = 0x55;
thedata->testshort = 0xFFFF;
thedata->anothertestchar = 0x11;
};
-----------------------------------------------------------------------
malloc() allocates memory for your struct. You need to call
free(mem_location) to free up the memory before your program terminates, or
else you will get memory leak.

To use the code you would pass:

testfunc(mem_location);

and then you could goof off with the variables.

Try not to mix apples and oranges. The only thing you should pass to hold a
struct is another struct of the same type. It would be like passing a car
variable to a function that uses the car to hold a mansion.

Any more questions? =)

Seems like I have much to learn when programming C.... :)
What I would like my code to do is what I described, namely I would like to
"update" part of a global array with the struct data.......what if I called
testfunc like: testfunc(TheBuffer+50); would'nt I get the desired result
then? I Mean:

TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11

Or is this a silly way of doing this.....?

Best Regards
Terry
 
G

Greg P.

Terry Andersen said:
Seems like I have much to learn when programming C.... :)
What I would like my code to do is what I described, namely I would like to
"update" part of a global array with the struct data.......what if I called
testfunc like: testfunc(TheBuffer+50); would'nt I get the desired result
then? I Mean:

TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11

Or is this a silly way of doing this.....?
Silly =)

If you want to update a global array with the values, you would have to call
your function testfunc() first, properly, then do something like.

TheBuffer[50] = your_struct->testchar;
TheBuffer[51] = your_struct->anothertextchar;

Do not put the unsigned short into the buffer, unless you are sure of its
value being within range of a byte, which is not likely. You will truncate
(round off) the value if you try to cast it as a char.

Also, you keep trying to pass an array of chars to testfunc(), which
manipulates a structure. No no no <slaps hand>. struct->testchar, testshort,
and anothertestchar have nothing to do with TheBuffer. You are assuming that
the compiler puts the value of testchar into TheBuffer[50], the value of
testshort into TheBuffer[51], and the value of anothertestchar into
TheBuffer[52]. This is not true. The compiler puts the values into the
structure, which you can then put into the array.

What books are you reading on C?
--

Regards,
Greg P.

Golden Rule of Open Source Programming:
"Don't whine about something unless you plan to implement it yourself"
 
G

Greg P.

I don't think I am being clear enough. What you need to do, then, is remove
the mystruct struct and just work on the array.

void testfunc(unsigned char array[])
{
array[50] = something;
array[51] = something;
array[52] = something;
};
 
D

Dan Pop

In said:
Could anyone please help me understand what is going on in the code below. A
short explanation would be nice.....

struct mystruct {
unsigned char testchar;
unsigned short testshort;
unsigned char anothertestchar;
};

void testfunc(unsigned char* mymemlocation) {
struct mystruct *thedata = (struct mystruct*) mymemlocation;

thedata->testchar = 0x55;
thedata->testshort = 0xFFFF;
thedata->anothertestchar = 0x11;
}

If you do not understand this code, the right thing to do is to (re)read
the chapters dealing with structures and pointers in your favourite C
book. This is very basic C code and you have a big problem if you don't
understand it.

The proper type for mymemlocation in standard C is void pointer, but this
is a minor detail.

Dan
 
T

Terry Andersen

Dan Pop said:
If you do not understand this code, the right thing to do is to (re)read
the chapters dealing with structures and pointers in your favourite C
book. This is very basic C code and you have a big problem if you don't
understand it.

The proper type for mymemlocation in standard C is void pointer, but this
is a minor detail.

Dan



You are both quite right. Back to the books. Thank you very much for your
time (especially Greg) and effort.
 
R

Richard Bos

[ Bloody 'ell, what a lot of quoting. Out come the scissors... ]
What I would like my code to do is what I described, namely I would like to
"update" part of a global array with the struct data.......what if I called
testfunc like: testfunc(TheBuffer+50); would'nt I get the desired result
then? I Mean:

TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11

Not necessarily. There may well be holes in the struct, for example for
alignment purposes. E.g., it could well result in this:

TheBuffer[50] == 0x55
TheBuffer[51] == 0xA2 /* Whatever was there before. */
TheBuffer[52] == 0xFF
TheBuffer[53] == 0xFF
TheBuffer[54] == 0x11

or

TheBuffer[50] == 0x55
TheBuffer[51] == 0x55 /* Which happened to be in the register. */
TheBuffer[52] == 0xFF
TheBuffer[53] == 0xFF
TheBuffer[54] == 0x11

Moreover, if you change

thedata->testshort = 0xFFFF;

to

thedata->testshort = 0x1234;

you don't know whether it will end up as

TheBuffer[52] == 0x12
TheBuffer[53] == 0x34

TheBuffer[52] == 0x34
TheBuffer[53] == 0x12

unless you happen to know the endianness of your computer. And then you
have to consider that shorts need not be two bytes long... or, indeed,
that bytes may be 16 or 32 bits long.

And as a final thought, this could break depending on what you pass to
the function, because of alignment errors. For example, suppose that
shorts need to be aligned on even addresses. If you, your struct will
indeed have a hole in it, as above. Calling testfunc(TheBuffer+50) will
work, because the short will, as it should, end up on an even address.
Now consider where that short will be positioned if you call
testfunc(TheBuffer+51)...
Or is this a silly way of doing this.....?

Not necessarily, but it's a very system-specific one, and details may
depend on, e.g., the optimisation flags you used to compile your
program. IOW, it's risky, and it probably isn't quite as useful as you
think it is.

Richard
 
B

bd

Greg P. said:
Terry Andersen said:
Thanks a lot. Would this mean that testchar, testshort and anothertestchar
are stored from memory location mymemlocation and further? If mymemlocation
would be like:

unsigned char TheBuffer[100];
//and you called the testfunc with:

testfunc(TheBuffer[50]);
No. First of all you would not pass TheBuffer to testfunc() with the
subscript on it. It would be passed as

testfunc(TheBuffer);

instead. The name of an array is a pointer to the first value, which you
could later iterate over.
Would TheBuffer then look like:
TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11
No. I think you mean: would the buffer[index] hold the values from the
function as array indexes. No.

With this code, you are now overwriting the boundary of your array, which
ends at 49. Remember that arrays start from 0, and go to length-1. So if I
had an array like:

char array[45];

I can only access array[0] to array[44].

If you access anything outside of your array's range, it is undetermined
behavior, but most likely you will overwrite another program's (running on
your machine) data causing a crash or something nastier.

To get back to your question about whether the members from the struct are
part of the array, no. You are attempting to pass an unsigned char to your
function as a form of memory reservation. Instead use:

struct mystruct p_yourstruct* = (struct mystruct) malloc(sizeof(mystruct));

to get the memory. For example:
---------------------------------------------
struct mystruct
{
unsigned char testchar;
unsigned short testshort;
unsigned char anothertestchar;
};

struct mystruct* mem_location = (struct mystruct) malloc(sizeof(mystruct));

void testfunc(struct mystruct* mymemlocation)
{
thedata->testchar = 0x55;
thedata->testshort = 0xFFFF;
thedata->anothertestchar = 0x11;
};
-----------------------------------------------------------------------
malloc() allocates memory for your struct. You need to call
free(mem_location) to free up the memory before your program terminates, or
else you will get memory leak.

To use the code you would pass:

testfunc(mem_location);

and then you could goof off with the variables.

Try not to mix apples and oranges. The only thing you should pass to hold a
struct is another struct of the same type. It would be like passing a car
variable to a function that uses the car to hold a mansion.

Any more questions? =)

Seems like I have much to learn when programming C.... :)
What I would like my code to do is what I described, namely I would like to
"update" part of a global array with the struct data.......what if I called
testfunc like: testfunc(TheBuffer+50); would'nt I get the desired result
then? I Mean:

TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11

Or is this a silly way of doing this.....?

A struct may have padding - it could have any number of spaces in between
valid members that have no defined value (that is, could contain
anything).
 
G

Glen Herrmannsfeldt

(big snip)
Thanks a lot. Would this mean that testchar, testshort and anothertestchar
are stored from memory location mymemlocation and further? If mymemlocation
would be like:

unsigned char TheBuffer[100];
file://and you called the testfunc with:

testfunc(TheBuffer[50]);

/*
Would TheBuffer then look like:
TheBuffer[50] = 0x55
TheBuffer[51] = 0xFF
TheBuffer[52] = 0xFF
TheBuffer[53] = 0x11
???
*/

Well, it could, but on many machines that I know about it would be more like

TheBuffer[50] = 0x55;
TheBuffer[52] = 0xFF;
TheBuffer[53] = 0xFF;
TheBuffer[54] = 0x11;

as many machines require a short to have an even address.

Also, the two bytes of the short may be stored in different order on
different machines.

-- glen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top