write a four byte integer to a memory region allocated as (char)

R

rlc

Hey guys,

I have a buffer in memory allocated as 1 byte chars. I need to
periodically write a four byte integer number into this structure.

int nextIndex = 1024;
char *buffer = malloc(sizeBuffer);
buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer
will contain the index, but how do I do this?
If I just write buffer[0] = nextIndex;
then nextIndex will be truncated to one byte. And I can't index the
buffer with integers for a couple of different reasons.

Thanks
 
J

Jens Thoms Toerring

rlc said:
I have a buffer in memory allocated as 1 byte chars.

That's a bit of a tautology - at least in C a char is always
one byte;-)
I need to
periodically write a four byte integer number into this structure.
int nextIndex = 1024;
char *buffer = malloc(sizeBuffer);
buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer
will contain the index, but how do I do this?
If I just write buffer[0] = nextIndex;
then nextIndex will be truncated to one byte.

Did you try

* ( int * ) buffer = nextIndex;

or, if you don't like that

memcpy( buffer, &nextIndex, sizeof nextIndex );

The latter method is required if buffer shouldn't be
properly aligned for int wide access - but as long as
buffer is an address returned by malloc() etc. it's
not an issue. But if you try do e.g.

* ( int * ) ( buffer + 15 ) = some_int_value;

you may get in trouble on a numberof architectures.

Regards, Jens
 
R

rlc

rlc said:
I have a buffer in memory allocated as 1 byte chars.

That's a bit of a tautology - at least in C a char is always
one byte;-)
I need to
periodically write a four byte integer number into this structure.
int nextIndex = 1024;
char *buffer = malloc(sizeBuffer);
buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer
will contain the index, but how do I do this?
If I just write buffer[0] = nextIndex;
then nextIndex will be truncated to one byte.

Did you try

* ( int * ) buffer = nextIndex;

or, if you don't like that

memcpy( buffer, &nextIndex, sizeof nextIndex );

The latter method is required if buffer shouldn't be
properly aligned for int wide access - but as long as
buffer is an address returned by malloc() etc. it's
not an issue. But if you try do e.g.

* ( int * ) ( buffer + 15 ) = some_int_value;

you may get in trouble on a numberof architectures.

                                Regards, Jens

Excellent, thank you. * ( int * ) buffer = nextIndex; was exactly
what I needed.
 
W

Willem

rlc wrote:
) Hey guys,
)
) I have a buffer in memory allocated as 1 byte chars. I need to
) periodically write a four byte integer number into this structure.
)
) int nextIndex = 1024;
) char *buffer = malloc(sizeBuffer);
) buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer
) will contain the index, but how do I do this?
) If I just write buffer[0] = nextIndex;
) then nextIndex will be truncated to one byte. And I can't index the
) buffer with integers for a couple of different reasons.

Do you want it little-endian/big endian/etc or machine-endian ?

Or, to put it differently: what is the purpose of writing these integers ?

From the fact that you want four-byte integers, I guess you want
specific-endian. In which case you simply split up your integer
into four bytes (using arithmetic operators, or shifts and ands)
and assign them to the four buffer positions separately. Big- or
little endian is then simply a matter of which order you assign.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Ben Bacarisse

rlc said:
I have a buffer in memory allocated as 1 byte chars. I need to
periodically write a four byte integer number into this structure.

int nextIndex = 1024;
char *buffer = malloc(sizeBuffer);
buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer
will contain the index, but how do I do this?
If I just write buffer[0] = nextIndex;
then nextIndex will be truncated to one byte. And I can't index the
buffer with integers for a couple of different reasons.

I am sure you can! In fact, doing so is the easiest way to put an int
where you want it:

int *now_index_as_int = (void *)buffer;
now_index_as_int[0] = nextIndex;

This is a long-winded version of:

*(int *)buffer = nextIndex;

You will get into trouble if the pointer is not properly aligned, but
pointers returned from malloc always will be. If you need to do this
in a relatively portable way (even when the pointer may not be
correctly aligned) you need to pack the int byte-by-byte. This lets
you choose the byte-order which is important if the buffer is
going to be sent somewhere where it might be read by different
hardware:

buffer[0] = nextIndex;
buffer[1] = nextIndex >> 8;
buffer[2] = nextIndex >> 16;
buffer[3] = nextIndex >> 24;

for example. The best way to avoid surprises here is to make all the
types unsigned.
 
R

rlc

Yeah, it should be buffer[0-3]. On my architecture int is four bytes.
Specifically what I was trying to do is to take a long segment of byte
data and periodically write header information to it so that I can
split it up to be processed on a parallel architecture. The header info
(the four byte ints) point to the beginning of sub-sections so that
they can be processed as a cohesive unit.

for instance, I want my byte stream to appear as thus:

10aaaaaa6bb8cccc

where the numbers are four byte ints and the letters are arbitrary one
byte symbols. The integers point to the beginning of the next
segment, denoting the length of a subsection. The 10 indicates that
the first subsection is 10 bytes in length and the subsection begins
at buffer[10]. In actuality these subsections are going to be much
longer, which is the reason I need a greater number of bits than a
single byte.

Best regards to everyone and thanks for the illuminating responses. I
actually didn't realize that you could cast a memory buffer to change
the indexing. I knew bit shifting would probably work, but I always
manage to screw things up and introduce bugs, plus I save cycles by
casting because it is done at compile time, right?
 
B

Ben Bacarisse

Ben Bacarisse wrote:
int *now_index_as_int = (void *)buffer;
now_index_as_int[0] = nextIndex;

Uhhh, he said four bytes, not sizeof(int) bytes. On one of my compilers,
this would only write two bytes.

Picky! I guessed he wanted an int and it just happens to be 4 bytes.

... If you need to do this
in a relatively portable way (even when the pointer may not be
correctly aligned) you need to pack the int byte-by-byte. This lets
you choose the byte-order which is important if the buffer is
going to be sent somewhere where it might be read by different
hardware:

buffer[0] = nextIndex;
buffer[1] = nextIndex >> 8;
buffer[2] = nextIndex >> 16;
buffer[3] = nextIndex >> 24;

for example. The best way to avoid surprises here is to make all the
types unsigned.

Still a problem, since buffer is a char*.

Well, I said "all types". I wanted that to include the buffer.
He should make it a uint8_t*,
which ensures it's 8 bits per byte as he's assuming:

I am less sure about the advantages of using uint8_t. I agree it is
good way to stop the program working (compiling even) on systems that
violate an assumption, but depending on what you are doing with the
8-bit parts, you might get away with it even when char is wider than
8.

<snip>
 
B

Barry Schwarz

rlc said:
I have a buffer in memory allocated as 1 byte chars.

That's a bit of a tautology - at least in C a char is always
one byte;-)
I need to
periodically write a four byte integer number into this structure.
int nextIndex = 1024;
char *buffer = malloc(sizeBuffer);
buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer
will contain the index, but how do I do this?
If I just write buffer[0] = nextIndex;
then nextIndex will be truncated to one byte.

Did you try

* ( int * ) buffer = nextIndex;

or, if you don't like that

memcpy( buffer, &nextIndex, sizeof nextIndex );

The latter method is required if buffer shouldn't be
properly aligned for int wide access - but as long as
buffer is an address returned by malloc() etc. it's
not an issue. But if you try do e.g.

* ( int * ) ( buffer + 15 ) = some_int_value;

you may get in trouble on a numberof architectures.
   \__________________________      http://toerring.de

Excellent, thank you. * ( int * ) buffer = nextIndex; was exactly
what I needed.

Did you not read the caveat? It will work for a buffer that has been
dynamically allocated as in your example but may fail miserably if you
try with a defined buffer.
 
B

Barry Schwarz

blargg said:
Ben said:
I have a buffer in memory allocated as 1 byte chars. I need to
periodically write a four byte integer number into this structure.

int nextIndex = 1024;
char *buffer = malloc(sizeBuffer);
buffer[0-4] = nextIndex; //meaning that the first four bytes of buffer

First four or five? 0, 1, 2, 3, 4 is five indicies.
will contain the index, but how do I do this?
If I just write buffer[0] = nextIndex;
then nextIndex will be truncated to one byte. And I can't index the
buffer with integers for a couple of different reasons.
I am sure you can! In fact, doing so is the easiest way to put an int
where you want it:

int *now_index_as_int = (void *)buffer;
now_index_as_int[0] = nextIndex;

Uhhh, he said four bytes, not sizeof(int) bytes. On one of my compilers,
this would only write two bytes.

He said "four byte integer".

long is a four byte integer.
 
D

David Thompson

Yeah, it should be buffer[0-3]. On my architecture int is four bytes.
Specifically what I was trying to do is to take a long segment of byte
data and periodically write header information to it so that I can
split it up to be processed on a parallel architecture. The header info

Is the splitter part of the architecture, or a separate front-end or
manager or whatever? In particular, do you KNOW they are the same
endian (as well as the same size = 4 bytes and the same bytesize,
and no differences in padding -- or just no padding at all)?
(the four byte ints) point to the beginning of sub-sections so that
they can be processed as a cohesive unit.

for instance, I want my byte stream to appear as thus:

10aaaaaa6bb8cccc

where the numbers are four byte ints and the letters are arbitrary one
byte symbols. The integers point to the beginning of the next
segment, denoting the length of a subsection. The 10 indicates that
the first subsection is 10 bytes in length and the subsection begins

IAYM the _next_ subsection, really the next count, begins at 10.
at buffer[10]. In actuality these subsections are going to be much
longer, which is the reason I need a greater number of bits than a
single byte.
This brings up the already-mentioned issue of alignment. If this
buffer is (at the beginning of) malloc'ed space, it is correctly
aligned for any C datatype -- including int. But buff+10 bytes is NOT
guaranteed to be aligned correctly, and for some systems it isn't.

If your system doesn't have alignment requirements, you're OK.
If it has only a 'soft' requirement (misaligned access still works but
is slower) and the amount of accesses to these count fields is small
(enough) compared to your other processing, still OK. Otherwise, you
have two choices:

- do the byte-by-byte access, either explicitly or with memcpy. This
will probably be a little slower on every count, although compared to
the rest of your processing it is likely negligible.

- move each count position to the next aligned location, wasting up to
3 bytes (padding) as needed. If the data is already large, as you say,
wasting say .0001% or whatever of the buffer space may be OK.
Best regards to everyone and thanks for the illuminating responses. I
actually didn't realize that you could cast a memory buffer to change
the indexing. I knew bit shifting would probably work, but I always
manage to screw things up and introduce bugs, plus I save cycles by
casting because it is done at compile time, right?

Not necessarily. But most machines nowadays are byte addressed, so
(data) pointer conversions require no actual computation, they only
change the type of the value. On the rare machines where say an int
pointer is different, and you want to do an int access, then the
runtime conversion is needed and had better be done.
 

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

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,237
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top