Difficulties to understand pointer-notations *myVar / myVar* (byte*&) myVar

Yes. These do the same thing.

char x = 'A';
char y = 'B';
char z = 'C';

void setup() {
  Serial.begin(9600);
  char*  p  = &x;
  char** pp = &p;
  Serial.println(*p);
  foo(p); // Use reference to pointer
  Serial.println(*p);
  bar(pp); // Use pointer to pointer
  Serial.println(*p);
}

void loop() {
}

void foo(char*& p) {
  p = &y;
}
void bar(char** pp) {
  *pp = &z;
}

apparently "&" is ok by not "&"
never used this but over the years have had to futz with ptr-to-ptrs when necessary.

the 2nd ed. of The C Programming Language had a program that translates variable definitions into english. in other words, it's confusing.

 func0: 123
 func1: 123
 func1: 123
 func2: 123
 func3: 123
#include <stdio.h>

int  val   = 123;
int *pVal  = & val;

void func0 ( int    x) { printf (" %s: %d\n", __func__, x); }
void func1 ( int  * x) { printf (" %s: %d\n", __func__, *x); }
void func2 ( int ** x) { printf (" %s: %d\n", __func__, **x); }
void func3 ( int *& x) { printf (" %s: %d\n", __func__, *x); }

int
main ()
{
    func0 (val);

    func1 (&val);
    func1 (pVal);

    func2 (&pVal);

    func3 (pVal);

    return 0;
}

```[http://cslabcms.nju.edu.cn/problem_solving/images/c/cc/The_C_Programming_Language_%282nd_Edition_Ritchie_Kernighan%29.pdf](http://cslabcms.nju.edu.cn/problem_solving/images/c/cc/The_C_Programming_Language_%282nd_Edition_Ritchie_Kernighan%29.pdf)

As written, the code is certainly an invitation for a memory leak. That alone would be enough for me to question the quality of the entire library code and motivate me to rewrite it myself.

There are several ways to improve it ... for example use STL smart pointers or containers. But, the simplest would probably be for the calling function to provide the storage space (as an array) and pass a pointer to it into the conversion function (along with a maximum size). The conversion function would then fill the storage provided by the caller.

I added comments to the function fromBase32
can the experienced users here read through my comments and respond if my understanding of what the code does is correct?

int Base32::fromBase32(byte* in, long length, byte*& out) {
  int result = 0; // Length of the array of decoded values.
  int buffer = 0;
  int bitsLeft = 0;
  byte* temp = NULL;

  temp = (byte*)malloc(length); // Allocating temporary array.

  for (int i = 0; i < length; i++) {// for-loop to iterate through the bytes the parameter "in" is pointing to
    byte ch = in[i];  // assign a single character of the "input" byte-sequence to ch
    
    // look up one base32 symbols: from 'A' to 'Z' or from 'a' to 'z' or from '2' to '7'
    if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A)) { ch = ((ch & 0x1F) - 1); }
    else if (ch >= 0x32 && ch <= 0x37) { ch -= (0x32 - 26); }
    else { free(temp); return 0; }

    buffer <<= 5;    
    buffer |= ch;
    bitsLeft += 5;

    // if more than 8 bits are processed in the conversion 
    if (bitsLeft >= 8)
    {
      // store this byte into array "temp"
      temp[result] = (unsigned char)((unsigned int)(buffer >> (bitsLeft - 8)) & 0xFF);
      result++;
      bitsLeft -= 8;
    }
  }

  // allocate temporary memory in the length of "result" bytes  
  // and use "out" as the name for the pointer-variable pointing to this adress in RAM
  out = (byte*)malloc(result); 
  memcpy(out, temp, result);   // copy byte-sequence stored at "temp"  to RAM-location where  "out" points to
  free(temp); // "mark RAM-area formely reserved for "temp" as free to use

  return result;
}

which means after leaving the function fromBase32 the variable handed over by the call to the function
as the third parameter is pointing to that area in RAM where the converted byte-sequence is stored?

Now If I would like to use an array of byte as the third parameter

byte myTargetForConvertedASCII_HexKey[16];

and that this variable called "myTargetForConvertedASCII_HexKey" should contain the converted byte-sequence
How do I have to modify the function?

What I find difficult is that I have to "hand-over" an array of bytes as a parameter or do I hand-over a pointer to the beginning of the byte-array?

If yes how does this look like?

byte mySourceArray[32];
byte myTargetArray[32];

void demoFunc (//not sure how the definition must look like) {

void demoFunc("myTargetArray", "mySourceArray") {

best regards Stefan

But Arduino uses C++, not C. There is no pass by reference in C but you can simulate it by passing pointers or pointers to pointers, etc.

There are several ways to pass an array to a function.

Old-School C Using a Pointer and Array Size:

const size_t arraySize = 10;
uint8_t myArray[arraySize];
void functionThatTakesAnArray(uint8_t *array, size_t theSize);

void setup() {
  functionThatTakesAnArray(myArray, arraySize);
}

void loop() {
}

void functionThatTakesAnArray(uint8_t *array, size_t theSize) {
  for (size_t i = 0; i < theSize; i++) {
    // do stuff with element array[i]
  }
}

Or, you could go a little more C++:

const size_t arraySize = 10;
using newArrayType = uint8_t[arraySize];
void functionThatTakesAnArray(newArrayType &array);

newArrayType myArray;

void setup() {
  functionThatTakesAnArray(myArray);
}

void loop() {
}

void functionThatTakesAnArray(newArrayType &array) {
  for (uint8_t j : array) {
    // do stuff with j
  }
}

The next step might be to use a template. But, that's probably unnecessary here.

@StefanL38
I tried to write without a library as a brain teaser, but I may has bad sense. :woozy_face:

Encode / Decode Base32 using a predefined fixed length C-string buffer.
Sorry, It's tested in Arduino Nano...

#define MAX_STRING_LENGTH 50 // Must multiple of 5
/* RAM consumes bytes about 2.6 times this value and additional few bytes */

// Must set to length of an array of both string buffer
#define     RAWSTR_BUFFER_BYTES     (MAX_STRING_LENGTH + 1)
#define     BASE32_BUFFER_BYTES     (MAX_STRING_LENGTH / 5 * 8 + 1)

char rawstr[RAWSTR_BUFFER_BYTES];
char base32[BASE32_BUFFER_BYTES];

void setup() {
  Serial.begin(9600);

  strlcpy_PF(rawstr, PSTR("Arduino Forum"), sizeof(rawstr));
  encodeBase32(base32, rawstr);
  Serial.println(base32);

  strlcpy_PF(base32, PSTR("KRUGS4ZANVSXG43BM5SSA53BOMQGIZLDN5SGKZBAMZZG63JAIJQXGZJTGI======"), sizeof(base32));
  decodeBase32(rawstr, base32);
  Serial.println(rawstr);
}

void loop() {
}

void encodeBase32(char* b32, const char* str) {
  unsigned char fin = 0, bits;
  unsigned int bcnt = 0, scnt = 0;
  while (bcnt < BASE32_BUFFER_BYTES) {
    bits = *(str + scnt);
    if (!bits) break;
    fin = (fin + 5) & 7;
    if (fin >= 5) {
      bits >>= 8 - fin;
    } else {
      bits <<= fin;
      bits |= *(str + ++scnt) >> (8 - fin);
    }
    bits &= ~0xE0;
    bits += bits < 26 ? 0x41 : 0x18;
    *(b32 + bcnt++) = bits;
  }
  for (scnt = 8; scnt < bcnt; scnt += 8);
  while (bcnt < scnt) *(b32 + bcnt++) = '=';
  while (bcnt < BASE32_BUFFER_BYTES) *(b32 + bcnt++) = 0;
}

void decodeBase32(char* str, const char* b32) {
  unsigned char fin = 0, bits;
  unsigned int scnt = 0, bcnt = 0, buff = 0;
  while (bcnt < BASE32_BUFFER_BYTES) {
    bits = *(b32 + bcnt++);
    if (!bits || bits == '=') break;
    bits -= bits > 0x40 ? 0x41 : 0x18;
    buff <<= 5;
    buff |= bits;
    fin += 5;
    if (fin >= 8) {
      fin -= 8;
      *(str + scnt++) = 0xFF & (buff >> fin);
    }
  }
  while (scnt < RAWSTR_BUFFER_BYTES) *(str + scnt++) = 0;
}

There is no error handling during decoding. :expressionless:
Lowercase Base32 is not accepted.
If you need it, you can add it yourself. :wink:

is it obvious, i'm asking, if the data is actually copied when using "&" or if it's really no different than a pointer and it's junk compiler symantics?

There are some C++ things that can only be done with pointers and some that can only be done with references. There are also areas where their applicability overlap. In those cases, you can choose between them based on preferred syntax, error-proofness, etc.

example?

i don't think this answers the question regarding beahvior

from what i've tried, there's no different (i.e. just semantics). the data is not copied, any value change is persistent in the calling function

Operator Overloading
Class Instance Function Chaining

you couldn't provide links ?

https://isocpp.org/wiki/faq/references#overview-refs

thank you

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.