1

My goal is to create a function that concatenate 2 chars into 1, and return it as MQTT subscribe. I get a difference between the results inside and outside the function ( I'm new to Arduino ), and I can't find why:

Code:

// Update variable below:
const char *direction = "up";
const char* clientID = "Sonoff";

//Consts
const char *client_temp = "HomePi/Dvir/Windows/";
const char* outTopic = "HomePi/Dvir/Messages";
//const char* outTopic2 = "HomePi/Dvir/Windows/ESP32";
const char* inTopic2 = "HomePi/Dvir/Windows/All";
char *inTopic;

void setup() {
  Serial.begin(9600);
//  len(create_topic(client_temp, clientID));
  inTopic = create_topic(client_temp, clientID);
  Serial.println(inTopic);
}

char *create_topic(char *chr1, char *chr2){ .   // added *
  char topic[strlen(chr1) +strlen(chr2)+1];
  sprintf(topic,"%s%s",chr1,chr2);
  Serial.println(topic);
  return topic;
}

void loop() {
  // put your main code here, to run repeatedly:

}

Result ( both line should have been same):

HomePi/Dvir/Windows/Sonoff
⸮⸮,茗⸮;⸮_⸮%⸮l?⸮az⸮z⸮%⸮⸮⸮\;⸮m⸮
  • You cannot return a local string (e.g. topic) in C. Either use a global variable or a parameter with a reference to a local string in the caller context or use malloc()/strdup(). – Mikael Patel Aug 17 '18 at 6:58
4

The concatenation is working fine in both instances.

What is wrong, though, is that you can't return a pointer to a locally declared array from a function. That array no longer exists when you leave the function.

The thing to remember with arrays is that you never pass the actual array to or from a function. All you pass is a pointer to the memory address where the array is. If you allocate an array in a function that memory is allocated on the stack. When you return the array from the function you return an address that is (currently) within the stack. When you leave the function all memory allocated on the stack by that function is removed, and that includes your array.

There are four ways of solving the problem - all of them have their pitfalls.

  1. Use a global "scratch pad" array that is big enough for any concatenating you may want to do. Do your concatenation in there.
  2. Declare your array static, which means it's allocated only once and can be returned from the function - but like the global one you have to have a fixed size.
  3. Pass a pointer to a suitably sized array to your function to have that array used for the concatenation, and
  4. Allocate memory on the heap using malloc().

My normal method is number 3. It's the safest and most flexible:

const char *a = "part a";
const char *b = " part b";

char all[14];
doConcat(a, b, all);

void doConcat(const char *a, const char *b, char *out) {
    strcpy(out, a);
    strcat(out, b);
}
  • can you be more specific for solution 3 ? – Guy . D Aug 14 '18 at 14:10
  • And he's using char as the return type instead of char *. – KIIV Aug 14 '18 at 14:10
  • Even worse, OP tries to return a char from a char*. Your solution suggestions are on point, although malloc should b avoided on tiny Arduinos. – mystery Aug 14 '18 at 14:10
  • @Guy.D , create an array of suitable size before calling the function and just pass a pointer to it. Also look up strcat cplusplus.com/reference/cstring/strcat – mystery Aug 14 '18 at 14:14
  • I tried also with char * - fixing my code – Guy . D Aug 14 '18 at 14:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.