3

Let me start by saying that I openly admit this is for a homework assignment, but what I am asking is not related to the purpose of the assignment, just something I don't understand in C. This is just a very small part of a large program.

So my issue is, I have a set of data that consists various data types as follows:

[16 bit number][16 but number][16 bit number][char[234]][128 bit number]

where each block represents a variable from elsewhere in the program. I need to send that data 8bytes at a time into a function that accepts uint32_t[2] as an input. How do I convert my 234byte char array into uint32_t without losing the char values?

In other words, I need to be able to convert back from the uint32_t version to the original char array later on. I know a char is 1byte, and the value can also be represented as a number in relation to its ascii value, but not sure how to convert between the two since some letters have a 3 digit ascii value and others have 2.

I tried to use sprintf to grab 8byte blocks from the data set, and store that value in a uint32_t[2] variable. It works, but then I lose the original char array because I can't figure out way to go back/undo it.

I know there has to be a relatively simple way to do this, i'm just lacking enough skill in C to make it happen.

cHam
  • 2,624
  • 7
  • 26
  • 28
  • Do you know the number of elements in the array? The actual count, not just the byte length? – Benjamin Trent Apr 11 '14 at 16:13
  • Please post a concrete example of what are you trying to do. – this Apr 11 '14 at 16:13
  • yes, one of the elements of the data set hold the length of the `char array` – cHam Apr 11 '14 at 16:15
  • What do you mean by `[2bytes- uint32_t]`? And when you write "byte", are you refering to "byte" as a set of 8 bits, or the unit of `sizeof()`? – Filipe Gonçalves Apr 11 '14 at 16:16
  • I do not understand your notation. `[2bytes-uint32_t]` means 2 uint32_t, or that a unit32_t is somehow 2 bytes? Similarly, `[234byte-char*]` means a char* to 234 char, or 234 char*, or that a char* is somehow horribly 234 bytes? – Adam Burry Apr 11 '14 at 16:18
  • Shall that describe a binary format? Then please describe it thus: `[Field width in byte or bit-interpret as (signed/unsigned) number/0-terminated string/symbol-sensible name]...`. Your description is not self-consistent. Also, avoid C data-types, unless they are used as-is, not packed somehow. – Deduplicator Apr 11 '14 at 16:19
  • made some edits to clarify – cHam Apr 11 '14 at 16:25
  • What is passed to your function? A `char *` that points to the data as described, or separate arguments for the initial 16-bit integers, then a pointer to 234 characters, and ... well what is sent for the 128-bit number too? How is the data laid out? – Jonathan Leffler Apr 11 '14 at 16:27
  • I thought `[16 but number]` would be the last number. ;-) – chux - Reinstate Monica Apr 11 '14 at 16:50
  • 1
    Showing an example of input would add clarity to the post. – chux - Reinstate Monica Apr 11 '14 at 17:01
  • I simplified the question and added some code that, if fixed, would give me a solution. – cHam Apr 11 '14 at 17:12

3 Answers3

2

Your question is very confusing, but I am guessing you are preparing some data structure for encryption by a function that requires 8 bytes or 2 uint32_t's.

You can convert a char array to uint32_t as follows

#define NELEM 234
char      a[NELEM];
uint64_t  b[(NELEM+sizeof(uint64_t)-1)/sizeof(uint64_t)]; // this rounds up to nearest modulo 4

memcpy(b,a,NELEM);

for(i .. ) {

   encryption_thing(b[i]);

}

or

If you need to change endianess or something, that is more complicated.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • As a side comment, you can also "attempt" to cast the `char` array to `(uint64_t*)` but you may get into trouble if the char pointer is not 8-byte aligned. It is safest to copy the unknown pointer to a known aligned uint64_t array. – Mark Lakata Apr 11 '14 at 16:26
0
#include <stdint.h>

void f(uint32_t a[2]) {}

int main() {
  char data[234]; /* GCC can explicitly align with this: __attribute__ ((aligned (8))) */
  int i = 0;
  int stride = 8;

  for (; i < 234 - stride; i += stride) {
    f((uint32_t*)&data[i]); }

  return 0; }
Adam Burry
  • 1,904
  • 13
  • 20
  • You forgot to use the implementation defined extension for non-aligned pointers. – Deduplicator Apr 11 '14 at 16:28
  • `char` is not aligned the same as `uint32_t`. That would crash on some platforms if dereferenced. – this Apr 11 '14 at 16:30
  • Can either of you clarify with further reading or a code sample? – Adam Burry Apr 11 '14 at 16:33
  • Ah, I see what you are saying now... my compiler did the right thing in this case anyway. Explicitly aligning on an 8 byte boundary did not change the generated code. But I have updated my example anyway. – Adam Burry Apr 11 '14 at 16:42
0

I need to send that data 8bytes at a time into a function that accepts uint32_t[2] as an input. How do I convert my 234byte char array into uint32_t without losing the char values?

you could use a union for this

typedef union 
{
  unsigned char arr[128]; // use unsigned char
  uint32_t uints[16]; // 128/8
} myvaluetype;

myvaluetype value;
memcpy(value.arr, your_array, sizeof(value.arr));

say the prototype that you want to feed 2 uint32_t at a time is something like

foo(uint32_t* p);

you can now send the data 8 bytes at the time by

for (int i = 0; i < 16; i += 2)
{
  foo(myvaluetype.uints + i);
}

then use the same struct to convert back.

of course some care must be taken about padding/alignment you also don't mention if it is sent over a network etc so there are other factors to consider.

AndersK
  • 35,813
  • 6
  • 60
  • 86