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
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
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de
Excellent, thank you. * ( int * ) buffer = nextIndex; was exactly
what I needed.
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
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.
--
Ben.
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.
> 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.
Still a problem, since buffer is a char*. He should make it a uint8_t*,
which ensures it's 8 bits per byte as he's assuming:
uint8_t* p = malloc( 4 );
p [0] = nextIndex >> 0 & 0xFF;
p [1] = nextIndex >> 8 & 0xFF;
p [2] = nextIndex >> 16 & 0xFF;
p [3] = nextIndex >> 24 & 0xFF;
(the masks eliminate warnings on some compilers, and make it clear to
everyone that truncation is occurring)
He said "four byte integer".
I think the task is to write the integer value,
and he is also saying that he has four byte integers.
--
pete
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?
> Ben Bacarisse wrote:
<snip>
>> 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.
<snip>
>> ... 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>
--
Ben.
char *buf;
size_t max_buf = 4;
int i = 1024;
buf = malloc(max_buf);
if (NULL == buf) {
...
}
assert(max_buf >= sizeof i);
memcpy(buf, &i, sizeof i);
--
Tor <echo bwz...@wvtqvm.vw | tr i-za-h a-z>
>On Jun 12, 8:58�am, j...@toerring.de (Jens Thoms Toerring) wrote:
>> rlc <rcl...@gmail.com> wrote:
>> > 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.
--
Remove del for email
>blargg wrote:
>> Ben Bacarisse wrote:
>>> rlc <rcl...@gmail.com> writes:
>>>> 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.
>
>I think the task is to write the integer value,
>and he is also saying that he has four byte integers.
--
Remove del for email
Not necessarily.
Not in some 64-bit Linux platforms. It is guaranteed to be at *minimum*
a four *octet* integer, though (not necessarily four bytes, since on
some platforms a byte has 16 bits, like many DSPs, where sizeof(long)<4).
> 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.