Shop OBEX P1 Docs P2 Docs Learn Events
Question about Pointer Behaviour — Parallax Forums

Question about Pointer Behaviour

Background: For my knitting machine, I want to add a camera as sensor. The camera is ESP32 (Tensilica) based and I use the Arduino environment for this. Which uses the GnuC++, as far as I know. Unfortunately I updated board definitions for ESP32 and since some code does not work anymore as before. The routine is part of a Forth compiler.

It is unclear to me, if this is the result of
a) changed compiler optimation strategies
b) changed definition of size_t
c) an alignment problem of the pointer. (Not at a 4 byte boundary)
d) the pHere++ was formerly done before the right side of the line and is now done afterward (As I thought would be the idea.)

....
typedef int32_t cell_t;
...
cell_t* pHere;               // HERE, points to the next free position in
                             // Forth Space
....

void _does(void) {
  *pHere++ = SUBROUTINE_IDX;
  // Store location for a subroutine call
  // *pHere++ = (size_t)pHere + sizeof(cell_t); // **used to work **Code beginnt in übernächster Zelle
  *pHere++ = (size_t)pHere + 2*sizeof(cell_t); // **works now** Code beginnt in übernächster Zelle
  *pHere++ = EXIT_IDX;
  // Start Subroutine coding, entry must point to this location!
}

Actually, I don't understand, why this ever worked before. Codes in this Forth machine are 32bit. As far as I understand, size_t is long long integer. I don't understand, why this was chosen.

Perhaps, someone can give me some hints. I don't want to create new further problems.
Thank you!
Christof

Comments

  • ersmithersmith Posts: 6,102

    size_t is an unsigned integer type that will hold the size of any possible object. On a 32 bit system (like most modern MCUs) it will typically be a 32 bit unsigned integer. However, if you've changed compilers recently then it's possible that the new compiler has a different definition for size_t. If it's now using 64 bits for size_t then perhaps it also needs 64 bits for cell. Indeed, I would have defined the cell_t type as typedef intptr_t cell_t;, as that says that a cell has to be able to hold a pointer (so on 64 bit machines it should be 64 bits).

  • Christof Eb.Christof Eb. Posts: 1,241
    edited 2025-01-26 14:35

    @ersmith said:
    size_t is an unsigned integer type that will hold the size of any possible object. On a 32 bit system (like most modern MCUs) it will typically be a 32 bit unsigned integer. However, if you've changed compilers recently then it's possible that the new compiler has a different definition for size_t. If it's now using 64 bits for size_t then perhaps it also needs 64 bits for cell. Indeed, I would have defined the cell_t type as typedef intptr_t cell_t;, as that says that a cell has to be able to hold a pointer (so on 64 bit machines it should be 64 bits).

    Thank you!
    I still don't understand, why the old code was able to compile the correct address which is pHere+8bytes.

  • maccamacca Posts: 829

    @"Christof Eb." said:
    d) the pHere++ was formerly done before the right side of the line and is now done afterward (As I thought would be the idea.)

    The right-side is evaluated first, so the post-increment always happens after the assignment. If the compiler did otherwise, then it was likely a bug.

    All other things, seems irrelevant (aligment, size of size_t, have nothing to do with it).

    ....
    typedef int32_t cell_t;
    ...
    cell_t* pHere;               // HERE, points to the next free position in
                                 // Forth Space
    ....
    
    void _does(void) {
      *pHere++ = SUBROUTINE_IDX;
      // Store location for a subroutine call
      // *pHere++ = (size_t)pHere + sizeof(cell_t); // **used to work **Code beginnt in übernächster Zelle
      *pHere++ = (size_t)pHere + 2*sizeof(cell_t); // **works now** Code beginnt in übernächster Zelle
      *pHere++ = EXIT_IDX;
      // Start Subroutine coding, entry must point to this location!
    }
    

    Actually, I don't understand, why this ever worked before. Codes in this Forth machine are 32bit. As far as I understand, size_t is long long integer. I don't understand, why this was chosen.

    To me, the commented line that "used to work" didn't worked, or maybe it worked because of a side effect of something else (compiler bug ?).

    Anyway, the line "works now" seems correct, if that location should point to the location after EXIT_IDX, then adding 2 * sizeof(cell_it) is correct, because on the right side, pHere still points to the location before the post-increment (so 4 bytes to skip the current location + 4 bytes to skip EXIT_IDX location). With the commented line, it will point to the location of EXIT_IDX.

    That if I haven't missed something.

  • @macca said:

    @"Christof Eb." said:
    d) the pHere++ was formerly done before the right side of the line and is now done afterward (As I thought would be the idea.)

    The right-side is evaluated first, so the post-increment always happens after the assignment. If the compiler did otherwise, then it was likely a bug.

    All other things, seems irrelevant (aligment, size of size_t, have nothing to do with it).

    ....
    typedef int32_t cell_t;
    ...
    cell_t* pHere;               // HERE, points to the next free position in
                                 // Forth Space
    ....
    
    void _does(void) {
      *pHere++ = SUBROUTINE_IDX;
      // Store location for a subroutine call
      // *pHere++ = (size_t)pHere + sizeof(cell_t); // **used to work **Code beginnt in übernächster Zelle
      *pHere++ = (size_t)pHere + 2*sizeof(cell_t); // **works now** Code beginnt in übernächster Zelle
      *pHere++ = EXIT_IDX;
      // Start Subroutine coding, entry must point to this location!
    }
    

    Actually, I don't understand, why this ever worked before. Codes in this Forth machine are 32bit. As far as I understand, size_t is long long integer. I don't understand, why this was chosen.

    To me, the commented line that "used to work" didn't worked, or maybe it worked because of a side effect of something else (compiler bug ?).

    Anyway, the line "works now" seems correct, if that location should point to the location after EXIT_IDX, then adding 2 * sizeof(cell_it) is correct, because on the right side, pHere still points to the location before the post-increment (so 4 bytes to skip the current location + 4 bytes to skip EXIT_IDX location). With the commented line, it will point to the location of EXIT_IDX.

    That if I haven't missed something.

    Thank you!
    Your comment makes totally sense for me. Though I find it very strange that those compensating bugs in compiler and code has worked for several years?!

Sign In or Register to comment.