simple Q about C array syntax

hello so i'm never gonna figure out the syntax of arrays in C so it would be helpful if someone could check this bit of code for me.

i got a file of x # of bytes (say 10 for example) stored on an SD card.
i wanna make an array in RAM called "table" of x bytes, then
read bytes from the file and
store those bytes in table in the same order as in the file.

  int  x;
  char * table;
  x = 10;
  table = (char *) malloc(x);    // reserve space for table
  myFile = SD.open("file.bin");
  x = 0;
  while (myFile.available()) {
    table + (char *)x++ = myFile.read();
    }

is this correct?
thanx, mike

What are you talking about? Array accessing in C is the same as any other languagesuggestions (that I know of).

To access array use: a[index] where index start at 0 to size-1

If you don't need the array to scope outside the block your code is contained within you don't need to use malloc().

  char  table[10];
  myFile = SD.open("file.bin");
  int x = 0;
  while (myFile.available() && (x < 10)) {
    table[x++] = myFile.read();
    }

If the array must exist outside the scope there are several ways you might tackle the problem> For example you can use a global array or you can pass in a pointer to the array. Which is best depends on exactly how you are going to use the array.

    table + (char *)x++ = myFile.read();

No, it would be:

    *(table + x++) = myFile.read();

If you wanted to use pointers...

But you said arrays. C allows arrays and pointers to be used interchangably, so even with malloc, the much more obvious syntax would be:

    table[x++] = myFile.read();

more obvious syntax would be:

    table[x++] = myFile.read();

Doh! of course that's the obvious syntax.

*(table + x++) = myFile.read();

this is the kinda stuff that i'll never understand. table is char* and x is an int. if i tried a line like that, gcc would slap me in the face.
and what is this?: *(expression)
pointer to nothing? how do you guys keep this shit straight?
not to mention the syntax of strings. and i have NEVER seen anything on the internet that clearly describes all these rules with consistent terminology.
anyway, yeah i had a brain fart, sorry to waste y'all time.

  char  table[10];
  myFile = SD.open("file.bin");
  int x = 0;
  while (myFile.available() && (x < 10)) {
    table[x++] = myFile.read();
    }

ok that i understand. but the point is that the file i'm reading from is not constant. it changes from one instance to the next. what i have to do is open the file, count how many bytes it contains and then make a table in RAM of the same size.

It's not good idea to use dynamic memory on arduino unless you understand the risk.
If you know the largest size it should be (and you should have a constraint on the max size anyway unless only you use the system), you can make a global array with the largest size.
Then do work there.

mikewax:
table is char* and x is an int. if i tried a line like that, gcc would slap me in the face.

Nope, perfectly legal. The compiler understands how to do certain arithmetic operations on pointers:

pointer + integer = pointer
pointer - integer = pointer
pointer - pointer = integer

but,
pointer + pointer is undefined

and what is this?: *(expression)

The '*' is the dereferencing operator. *pointer returns the value that pointer is pointing to.

*(table + x++) = myFile.read();

this is the kinda stuff that i'll never understand.

ptr++ increments a pointer to the next element, right? And of course it's just shorthand for "ptr = ptr+1"
So "ptr + n" is the same as N increments of the pointer.
Take the pointer to (something) and add integer x to it to get a pointer to the Xth element (and increment x, afterward.) Then dereference the resulting value (which is still a pointer) with "*" to get the contents of the thing at that pointer location.

It would all be so obvious if they just taught everyone PDP11 assembly language!

C is very flexible regarding the syntax of array and pointer expressions,
which can lead to quite strange looking code. :wink:

char alpha[] = " abcdefghijklmnopqrstuvwxyz";
char* pAlpha = alpha;
void setup() {
  Serial.begin(250000);
  Serial.print(alpha[1]);
  Serial.print(alpha[12]);
  Serial.print(12[alpha]);
  Serial.print(*alpha);
  Serial.print(pAlpha[20]);
  Serial.print(8[pAlpha]);
  Serial.print(*(pAlpha + 5));
  Serial.print(*pAlpha);
  Serial.print(0[19 + pAlpha]);
  Serial.print(0[alpha + 1]);
  Serial.print(13[alpha]);
  Serial.print(*(alpha + 5));
}
void loop() {}

But it'sall the same

what i have to do is open the file, count how many bytes it contains and then make a table in RAM of the same size.

Why not just declare an array of the maximum size that will be ever be used ? After all, if the array may need say 100 levels at some time then you will need that amount of memory at that time.

Is the fact that the array is of type char and not byte significant to your program ?

gfvalvo:
Nope, perfectly legal. The compiler understands how to do certain arithmetic operations on pointers:

pointer + integer = pointer
pointer - integer = pointer
pointer - pointer = integer

but,
pointer + pointer is undefined
The '*' is the dereferencing operator. *pointer returns the value that pointer is pointing to.

ok i'm makin a cheat sheet with all this stuff.
so if i go:
type * var, the * means pointer to type
and if i go:
*expression, * means dereference of pointer
but what about this?: *int
or this?: *char

mikewax:
but what about this?: *int
or this?: *char

Please provide a complete example you've seen of this notation.

arduino_new:
It's not good idea to use dynamic memory on arduino unless you understand the risk.
If you know the largest size it should be (and you should have a constraint on the max size anyway unless only you use the system), you can make a global array with the largest size.
Then do work there.

well i'm using a mega with 8k of RAM and the table in question will never be bigger than 2.5k, so yes that would work, since i don't really understand the risk.
but which is better:
this: table = (char *) malloc(2560)
or this: char table[2560]
?

westfw:
this is the kinda stuff that i'll never understand.
ptr++ increments a pointer to the next element, right? And of course it's just shorthand for "ptr = ptr+1"
So "ptr + n" is the same as N increments of the pointer.
Take the pointer to (something) and add integer x to it to get a pointer to the Xth element (and increment x, afterward.) Then dereference the resulting value (which is still a pointer) with "*" to get the contents of the thing at that pointer location.

It would all be so obvious if they just taught everyone PDP11 assembly language!

ok thanx that makes sense, and i guess if i made a living writing this kind of code, i'd eventually be able to get all these rules straight. but i was lucky to get a high school diploma, and this stuff is harder than learning a foreign language.

#include <SD.h>

void setup()
{
    SD.begin();

    File file = SD.open("file.bin");
    if ( file )
    {
        // this will allocate the buffer as a stack based local variable
        // the "danger" here is that the stack collides with the heap.
        const size_t length = file.size();
        char buffer[length];

        file.read(buffer, length);
        file.close();

        // ... play with your buffers comtents here ...


        // the buffer will be 'released' frrom the stack when function exits
        // like any 'local' variable
    }
}

void loop()
{   }

mikewax:
*expression, * means dereference of pointer

Assuming 'expression' evaluates to a valid pointer.

*expression, * means dereference of pointer

Assuming 'expression' evaluates to a valid pointer.

Alas, no. Just "anything the compiler thinks is a pointer", which can include invalid pointers, as well as any expression that the user tells the compiler is a pointer. Thus causing Many Bugs, and New Languages That Are More Careful.

Most of the AVR IO registers are accessed via #defines that eventually expand to look like:

   *((unsigned char *)(0x20 + 5))

westfw:
Assuming 'expression' evaluates to a valid pointer.

Alas, no. Just "anything the compiler thinks is a pointer", which can include invalid pointers, as well as any expression that the user tells the compiler is a pointer. Thus causing Many Bugs, and New Languages That Are More Careful.

Most of the AVR IO registers are accessed via #defines that eventually expand to look like:

   *((unsigned char *)(0x20 + 5))

with a 'volatile' thrown in there somewhere.

C does do an exquisite job of allowing the careless to shoot themselves in the foot.

gfvalvo:
Please provide a complete example you've seen of this notation.

i've never seen it i just thought that if pointer - pointer = integer then you'd have *int