1

This seems such a basic question, but I cannot find an answer anywhere on SO.

I know that C/C++ do not have a byte datatype. I know that sizeof(char) == 1.

I'm trying to store 12 transmissions, each of 96 bytes on Pebble, as transmitted from my Android app.

Due to limitation in the transmission size, I'm sending one at a time. Each one should be 'appended' to the last, as they should end up forming sequential space in memory, for reading as an image (one bit per pixel).

I'm trying to do something like this:

int transNum = 0;
uint8_t image[][] = new uint8t[12][12] //not sure about uint8_t, and I've forgotten how to do 'new' in C, I have to create just a pointer, and then malloc?

receivedHandler(DictionaryIterator *iter, void *context){
    Tuple *receivedImage = dict_find(iter, KEY_IMG);
    for (int i = 0; i < 12; i++) {
        image[transNum][i] =  receivedImage->value[i]->uint8_t;
    }
    transNum += 1; //this is in an implicit loop, since once done Pebble ACKs the transmission, and receivedHandler is called again by the next transmission
}

Am I even remotely close?

OJFord
  • 10,522
  • 8
  • 64
  • 98

4 Answers4

5

You can allocate 12*96 byte of contiguous memory having 12 rows & 96 columns

char*   image = (char*)malloc(sizeof(char)*12*96);

also, a global array will do just fine

char image[12][96];

From what I understand, you are recieving data row wise ie 96 bytes at a time:

char rcvd_data[96]={0};

and access/set like this::

for(row=0;row<12;row++) //to point to the row (0-11 rows)
{
   rcvd_data= recv_function(); //whatever your recv function is
   for(col=0;col<96;col++) //to point to the col in that row (0-95 col)
   {
      *(image + row*96 + col)= rcvd_data[col]//whatever value you want to assign 
    }
}

and to transfer all 96 bytes in one go:

for(row=0;row<12;row++) //to point to the row (0-11 rows)
{
   rcvd_data= recv_function(); //whatever your recv function is
   memcopy((image + row*96), rcvd_data, 96);
}
brokenfoot
  • 11,083
  • 10
  • 59
  • 80
  • When you say row/col, memory is one dimensional. So am I correct that this looks like `{r0c0, r0c1, ... , r0c95, r1c0, ... , r11c95}`? And I assume `i == col_no` there? – OJFord Mar 07 '14 at 02:41
  • Yup, that's right. And yes, `i=col` in the above code – brokenfoot Mar 07 '14 at 02:44
  • Any real difference between the two declarations? I assume if I use `char image[12][96];` then I don't dereference when accessing the element. Any other difference/reason for preference? – OJFord Mar 07 '14 at 02:46
  • For both the declaration, you reference the elements the same way. Essentially either way you get a char* `image` which points to a contiguous memory 12*96 bytes long. – brokenfoot Mar 07 '14 at 02:48
  • and you can safely not cast output of malloc() http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – KedarX Mar 07 '14 at 02:51
  • @Kedar: I do that just to avoid the compiler warning. – brokenfoot Mar 07 '14 at 02:52
  • Okay, thanks. Last Q - what I need to assign to is the value of a dict KV `Tuple`. Except, this `tuple->value` is the 96 bytes. How do I get at one - or is there some way to assign the whole lot in one hit? – OJFord Mar 07 '14 at 02:53
  • you can use memcopy for that. – brokenfoot Mar 07 '14 at 02:56
2

One thing I will add to this is be careful using just a char. Use something like unsigned char,signed char, or uint8_t when dealing with pure byte data. While a char is one byte I've seen loss of data because of it's use.

TerraOrbis
  • 91
  • 4
1

The simplest solution to allocate the array you describe is:

uint8_t image[12][96];

However, based on your description " Each one should be 'appended' to the last, as they should end up forming sequential space in memory", that suggests you actually want:

uint8_t image[12 * 96];

and then you will just write your 12 transmission sequentially into that array.

This code you wrote:

for (int i = 0; i < 12; i++) {
    image[byteNum][i] =  receivedImage->value[i]->uint8_t;
}

isn't right, uint8_t is a data type, not a field name.

Also, probably you want to do something with image[i], rather than image[byteNum][i] although I can't be more specific without knowing what the TupleType is and how much you're expecting to find in each Tuple.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • what's the difference between `image[12][96];` and `image[12 * 96];` ? Don't they both allocate contiguous memory? – brokenfoot Mar 07 '14 at 03:15
  • They both allocate contiguous memory, although it is undefined if you attempt to treat the first one as a long series of bytes. (According to the C standard you're not allowed to read past the bounds of an array, even if you know exactly what is in the next memory location). – M.M Mar 07 '14 at 03:17
  • Coming from Python, I prefer `two_d[i][j]`. I just find it more transparent about where I am. It makes looping easier too IMO. – OJFord Mar 07 '14 at 03:28
  • @MattMcNabb - are you familiar with Pebble SDK? Would appreciate some help in chat perhaps. – OJFord Mar 07 '14 at 05:08
  • I'm not unfortunately, I've just been reading the online documentation. It's pretty simple to use a one-dimensional array and just index into it by `96 * i`. – M.M Mar 07 '14 at 05:09
  • The issue I face now seems to be two-fold. Firstly, half my transmissions are NACK'd. Secondly, nothing (not even ACK'd) rows of image display.. – OJFord Mar 07 '14 at 05:10
  • @MattMcNabb I think the issue is what you begin to address at the end - right now I just have `memcpy(dest, rcvd->value, 16)` - what is the 'field name'? – OJFord Mar 07 '14 at 05:28
  • I think you will need to find a Pebble expert to help you from here, sorry :) – M.M Mar 07 '14 at 05:40
0

I think you need to malloc two times.

char** image = (char**)malloc(sizeof(char*)*12);
int i = 0;
for(; i < 12; ++i){
   image[i] = (char*)malloc(sizeof(char)*12);
}

You can then treat image as a two-dimension array.

FaceBro
  • 787
  • 2
  • 13
  • 29