Pointer confusion is hard to overcome...

Although I have read several pages about C pointer syntax I remain confused... let's say I have two char arrays (looking up UI button ids and mapping them into bytes for output). There are 15 buttons on page 1 of the UI and 20 buttons on page 2, so...

char keyMap1[15] = {
  'i',             // Ign
  'z',             // TA Zoom 'z'
  'b',             // Brake  'b'
  KEY_UP_ARROW,             // Shift Up  KEY_UP_ARROW
  0x20,             // ESC
  // end row 1
  'l',             // Lights 'l'
  'x',             // TA page  'x'
  '1',             // Cab View  '1'
...

char keyMap2[20] = {
  'c',             // Signal Left  'c'
  0x20,             // BLANK?
  'x',             // TA Page  'x'
  'z',             // TA Zoom 
  'v',             // Signal Right  'v'
  // end row 1
  'i',             // Ign
  't',             // Trailer 't'
...

Later in the code when someone hits a button on a certain UI page with a certain ID, I could do this:

   byte c;

   if (pg == 1) {
    c = keyMap1[i];
   } else {
    c = keyMap2[i];
   }

And this works. But I thought it would be more elegant if I set up a 2-element array containing the addresses of the two keyMap char arrays, something like this:

char *keyMaps[2] = {
  &keyMap1,
  &keyMap2,
};

and then later do this

   char *cp[] = keyMaps[pg-1];
   c = cp[i];

it doesn't really make much difference either way... but I find myself among the many who get flustered by the special syntax for pointers. I thought I had this right, but I get compile time errors. Doubtless if you really know your c syntax, I did something ludicrous; but I was trying to apply what I had been reading.

I don't mind doing this the dumb way :slight_smile: whatever works! just wondering why my attempt to be clever failed. I thought this kind of trick (stashing pointers in arrays) could potentially be a more elegant way to implement a dispatch table than long switch statements, too.

You are making 'cp' a one-element array of character pointers.

      char *cp[] = keyMaps[pg-1];
   // To use the one pointer in the array you have to fetch it first:
   c = (cp[0])[i];  // You can then use the character pointer as an array

I think you want 'cp' to be a pointer to an array of characters:

      char (*cp)[] = keyMaps[pg-1];
   c = cp[i];

And a pointer to a character can be treated as a pointer to an array of characters:

      char *cp = keyMaps[pg-1];
   c = cp[i];

This last option is simplest to read and therefore most desirable.

Oh John i am so impressed ! those braces !! i get to it but not of the top of my head.
I would actually just use a single keymap, more simple

  if (pg>1) {
    key+=15;
   }
char c=keymap[key]

Yet another syntax:

char *keyMaps[] = {
  keyMap1,
  keyMap2,
};

Access with:

char c = keyMaps[pg-1][i]

:slight_smile: I blush for feeling stupid. Particularly, why did I not think of Deva_Rishi's so-simple solution! I just don't think like a C programmer. Feels like I'm trying to drive screws with a crowbar, sometimes.

Anyway, I've bookmarked this thread as an excellent tutorial in chars vs char pointers and am very grateful to y'all.

Since i also tend to get a little lost i decided to make a complete example, yet i didn't manage to make the first of John's examples work.

char keyMap1[15] = {'i','z','b','g','h','m','n','y','u','w','q','e','&','*','('};
char keyMap2[20] = {'c',' ',':',';','x','!','@','

I tend to run into the pointer issue mainly when trying to pass 'struct' 's and arrays of them to functions. But also i need to rewrite some of my programs using Global 'Strings' in the near future to make use of char* instead.,'%','~','%','z','v','i','t','1','2','3','4','5'};

char *keyMaps = {keyMap1,keyMap2};

void setup() {
  Serial.begin(9600);
  Serial.println("char * Example");
  uint8_t c;
  uint8_t key=12;
  uint8_t kmap=1;
 
  char (*cp1) = keyMaps[kmap-1];
  c = cp1[key]; 
  Serial.println(c,DEC);
 
  char *cp2 = keyMaps[kmap-1];
  c = cp2[key];
  Serial.println(c,DEC);
 
  c = keyMaps[kmap-1][key];
  Serial.println(c,DEC);
}

void loop() {
}


I tend to run into the pointer issue mainly when trying to pass 'struct' 's and arrays of them to functions. But also i need to rewrite some of my programs using Global 'Strings' in the near future to make use of char* instead.
char keyMap1[15] = {...
char *keyMaps[] = {...
  uint8_t c;
  char (*cp1)[] = keyMaps[kmap-1];
  c = cp1[key]; 
  Serial.println(c,DEC);

I do NOT understand using anything other than a char type variable to hold a char. I do NOT understand printing the char as a number.

PaulS:
I do NOT understand using anything other than a char type variable to hold a char. I do NOT understand printing the char as a number.

Neither do i actually, but since that is not really relevant to the topic, i don’t really care.

For a little obfuscation, go with:

c = *(*(keyMaps + kmap - 1) + key);

@gfalvo Yikes! that is the kind of syntax that scares people away from C! beautiful in its own way, but frightening :slight_smile: