# exercise problem -- not homework

Discussion in 'C++' started by Charles, Jul 28, 2003.

1. ### CharlesGuest

I am going through the exercises and Bruce Eckel's Thinking in C++ and
I ran into an exercise that wasn't included in his solutions that I
think I could use some assistance with.

Exercise 3-26 pg 213:

Define an array of int. Take the starting address of that array and
use static_cast to convert it into an void*. Write a function that
takes a void*, a number (indicating a number of bytes), and a value
(indicating the value to which each byte should be set) as arguments.
The function should set each byte in the specified range to the
specified value. Try out the function on your array of int.

Here is what I have so far: (which isnt much)

#include <iostream>
using namespace std;

void fn (void* v, int n)
{
}

int main ()
{
int a[10];
void* vp = static_cast<void*>(&a);

return 0;
}

Maybe somebody can help me translate what is being asked in the
exercise.

Thanks in advance for any tips,
Charles

Charles, Jul 28, 2003

2. ### Jakob BielingGuest

<Charles> wrote in message
news:...

> Did I correctly recast the void to the type you are describing?

The cast itself is correct, but it is of no use for you.

> How do I set the value of each byte in the range as it applies to the
> int array?

See below.

> #include <iostream>
> using namespace std;
>
> void fn (void* v, size_t num_bytes, int value)
> {

This is what Karl meant. You cannot really work with a void-pointer,
because it is an incomplete type. So you need to cast 'v' to something that
allows you to work on bytes.

> for (size_t i = 0; i < num_bytes; ++i)
> // set the bytes here How?

Once you have the above casting done, you can easily assign to the byte
array, just like you would do any other variable assignment.

> }
>
> int main ()
> {
> int a[10], number = 10;
>
> void* p_v = static_cast<void*>(&a);
> unsigned char* p_byte = reinterpret_cast<unsigned char*>(p_v);

If you think about the use of this, what would it do? You cast to
'unsigned char', but what for?

> fn (p_v, sizeof p_byte, number);

In the excerise it said your function takes a number "indicating a
number of bytes" .. you can assume that the number of bytes of the array you
are passing to the function are meant. But that is not what you are passing
there. You are passing the size of a pointer-to-unsigned-char, which is 4 on
my machine. But the size of your array that you are passing is 10 (not 10
bytes!), and each element occupies several bytes by itself. By this, you
should be able to figure out the actual size of the array in bytes.

> return 0;
> }

hth
--
jb

(replace y with x if you want to reply by e-mail)

Jakob Bieling, Jul 28, 2003

On Mon, 28 Jul 2003 06:22:05 -0400, wrote:

>>Here the function should set the bytes indicated by the
>>starting address in void* to a value (which has not been
>>passed right now, but you are going to change this). There
>>are n bytes in sequence.

>
>>Hint: You can't do anything sensible with a void*, thus you
>>will need to cast the void* to some other pointer type. So
>>the question is: To what data type will you cast the void
>>pointer, such that the pointer can point to individual bytes
>>
>>Hint2: sizeof( unsigned char) equals 1 per definition.
>> unsigned char is also often used, if somebody deals
>> with memory on the byte level.

>
>>
>>You are asked to rewrite the standard function memset. Maybe
>>looking up its documentation may be of some help. Other then
>>that: The assignment seems to be pretty clearto me. Are there
>>any specific quesitions instead of the global: 'Help!'

>
> Did I correctly recast the void to the type you are describing?
>
> How do I set the value of each byte in the range as it applies to the
> int array?
>
> Charles
>
>
> #include <iostream>
> using namespace std;
>

#define ARRAY_SIZE 10

> void fn (void* v, size_t num_bytes, int value)

void fn (void* v, size_t num_bytes, char value)

Since you'll be writing the value into each individual byto of the array
value should probably be of type char.

> {
> for (size_t i = 0; i < num_bytes; ++i)
> // set the bytes here How?

Pointer arithmetic:

for(pointer = start ;pointer < start + size; pointer++) {
*pointer = value;
}

> }
>
> int main ()
> {

int a[ARRAY_SIZE];
char number = 10;

>
> void* p_v = static_cast<void*>(&a);
> unsigned char* p_byte = reinterpret_cast<unsigned char*>(p_v);
>
> fn (p_v, sizeof p_byte, number);

fn (p_v, sizeof(int) * ARRAY_SIZE ,number)

>
> return 0;
> }

hth
npv

Nils Petter Vaskinn, Jul 28, 2003
4. ### Jakob BielingGuest

<Charles> wrote in message
news:...
> Here is what I have in an attempt to apply the advice given to me in
> this thread. It seems to satisfy the criteria given in the
>
>
> #include <iostream>
> using namespace std;
>
> void fn (void* v, size_t num_bytes, int val)
> {
> reinterpret_cast<unsigned char*>(v);
> unsigned char byte =
> static_cast<unsigned char>(val);
>
> cout << "num_bytes = " << num_bytes << endl;
>
> for (size_t i = 0; i < num_bytes; ++i)
> {
> }
> }
>
> int main ()
> {
> int a[10], value = 67;
>
> void* vp = static_cast<void*>(&a);
>
> fn (vp, sizeof a, value);

The loop for printing the result seems wrong.

> // output each of 4 bytes of int array
> // index each element
> for (size_t i = 0; i < (sizeof a / sizeof a[0]); ++i)
> {
> reinterpret_cast<unsigned char*>(a);

'a ' is of type 'int'. Above, you are casting that to 'unsigned
char*'. I think this is not what you intended to do. Instead, you probably
want to take the /address/ of the i-th element in the a-array, so that
p_addr points to the first byte that the i-th 'int' in the array occupies.
(*)

> unsigned char byte =
> static_cast<unsigned char>(a);

I do not think this is intended either. 'byte' contains part of 'a '.
Seeing the loop below, you print out 'byte', but you never change its value,
until the point of execution reaches the above line again. You can actually
remove this line completely.

> // iterate each byte
> for (size_t j = 0; j < sizeof(int); ++j)
> {
> cout << byte ;

You seem to be thinking that incrementing 'p_addr' implicitly changes
'byte' as well. But this is not the case. The value you have assigned to
'byte' is just there, without any connection to where it came from.

If you did as I explained (the paragraph marked with an asterisk), then
you only need to change 'byte' in the above loop to '*p_addr' and it will
print out the real values. This works, because before the loop starts, you
let 'p_addr' point to the first byte of the element in the array (see
above). The inner loop then prints the bytes as you intended.

> }
> cout << endl;
> }
>
> return 0;
> }
>
>
>
> The output on my machine is:
> num_bytes = 40
> CCCC
> CCCC
> CCCC
> CCCC
> CCCC
> CCCC
> CCCC
> CCCC
> CCCC
> CCCC

hth
--
jb

(replace y with x if you want to reply by e-mail)

Jakob Bieling, Jul 28, 2003
5. ### CharlesGuest

> The loop for printing the result seems wrong.

You are correct.
I noticed this too after I posted.

Here is my correction.

#include <iostream>
using namespace std;

void fn (void* v, size_t num_bytes, int val)
{
reinterpret_cast<unsigned char*>(v);
unsigned char byte =
static_cast<unsigned char>(val);

cout << "num_bytes = " << num_bytes << endl;

for (size_t i = 0; i < num_bytes; ++i)
{
}
}

int main ()
{
int a[10], value = 67;

void* vp = static_cast<void*>(&a);

fn (vp, sizeof a, value);

// output each of 4 bytes of int array
unsigned char* byte =
reinterpret_cast<unsigned char*>(vp);

// iterate number of elements
for (size_t i = 0; i < (sizeof a / sizeof a[0]); ++i)
{
// iterate each byte per element
for (size_t j = 0; j < sizeof(int); ++j)
{
cout << *byte;
byte++;
}
cout << endl;
}

return 0;
}

Charles, Jul 28, 2003
6. ### CharlesGuest

This seems to be correct now for displaying the byte content of each
of the array elements.

If i change line 15

from

to

I get the following output:

num_bytes = 40
CDEF
GHIJ
KLMN
OPQR
STUV
WXYZ
[\]^
_`ab
cdef
ghij

which, I think, shows that the program is setting and displaying 40
bytes for the 10 element int array.

Charles

Charles, Jul 28, 2003