Punteros

Saludos, estoy tratando de crear una libreria, pero el problema me da cuando trato de pasar la direccion de una cadena. Me da error y no se como se debe poner.Ejemplo:

int cadena[3] ;

void setup() {


}

void loop() {
 
 rtc.prueba(hora[0]) ;
 

}
/////////////
en el archivo de cabecera:
#ifndef RTC3231_h
#define RTC3231_h
#include <Arduino.h>


class RTC3231
{
  public: 
   
    RTC3231(void);            // constructor
    void prueba(byte &);     //  funciones
  
  private:
    
    byte *puntero ;
};
#endif
/////////////////////// en el archivo cpp

#include "RTC3231.h"

#include <Arduino.h>

RTC3231::RTC3231()
{
  
}

void RTC3231::prueba(byte &prueba1)
{
  puntero = &prueba1 ;
  *puntero = 5 ;
  

}

con una variable si funciona, pero no con una cadena. Saludos

Por favor edita tu título (usa uno que indique lo que consultas sin Saludos y sin la palabra ayuda, ambas inútiles para un título).
Si quieres solo pon punteros y luego edita el post usando etiquetas. Ya te envié privado.

[Off-Topic]

ArduMyth:
void prueba(byte &); <== ¿Y este ampersand cómo si fuese una referencia y sin variable? Piensa que esto es el parámetro que pones FUERA de la clase.

En C y C++ existe la posibilidad de declarar la existencia de funciones normales y funciones miembro de la clase antes de poner su implementación (definición completa de la función). Cuando sólo se declara no se pone “el cuerpo” de la función y en tal caso no es necesario poner el nombre de los parámetros, sólo se requiere poner el tipo. Y en este caso
** **void prueba(byte &);** **
es un claro ejemplo. Se está declarando la clase y lo que contiene. Y como en este caso se está sólo declarando la función miembro

prueba

podemos prescindir de poner un nombre de variable para el parámetro que va a recibir.

Para ilustrar lo que digo se puede compilar el siguiente ejemplo y ver que el compilador no se queja y funciona perfectamente.

void incrementa(byte &); // Declaramos que existe la función "incrementa" que tiene un parámetro de tipo "referencia a byte". Como sólo la estamos declarando no es necesario indicar el nombre del parámetro.

void setup() {
    Serial.begin(9600);
    byte b = 1;
    Serial.print(F("Valor de b antes de incrementar: "));
    Serial.println(b);
    incrementa(b); // Invocamos a la función que hemos declarado al principio.
    Serial.print(F("Valor de b despues de incrementar: "));
    Serial.println(b);
}

void loop() {
}

// A continuación implementamos la función "incrementa" que habíamos declarado al principio.
void incrementa(byte &b) {
    b++;
}

El entorno de Arduino tiene la peculiaridad de preprocesar el código antes de “enviarlo” al compilador. En “su preprocesado” detecta la necesidad de ciertas librerías y le informa al compilador de ello. A la vez que también detecta el uso de funciones en el programa antes de su implementación y antepone la declaración antes de pasarle el programa al compilador. Sin embargo, si se una alguna herramienta de compilación que no haga este trabajo, o bien implementamos la función antes de usarla (digamos que habría que ponerla al principio) o bien la dejamos “al final” pero ponemos la declaración al principio.

Como cosa curiosa y demostración de que en la declaración de la función de nada sirven los nombres de los parámetros, salvo a título informativo para el programador, se puede poner un nombre de parámetro en la declaración que nada tiene que ver con el de la implementación. Se puede cambiar sólo la primera línea del ejemplo anterior poniendo como nombre del parámetro

este_nombre_no_se_usa

quedando así:

void incrementa(byte &este_nombre_no_se_usa); // Declaramos que existe la función "incrementa" que tiene un parámetro de tipo "referencia a byte". Como sólo la estamos declarando no es necesario indicar el nombre del parámetro.

Y sin cambiar nada más podemos ver que compila y funciona exactamente igual que antes.

Recordar que, si ponemos la declaración de la función, en el código se ha de poner más tarde la implementación de la función. En el caso de
** **void prueba(byte &);** **
su implementación aparece un poco más abajo de la declaración. La implementación es:

void RTC3231::prueba(byte &prueba1)
{
   puntero = &prueba1 ;
   *puntero = 5 ;
}

Y por último, ya para liar más al personal (o para despertar la curiosidad de algunos). También podemos implementar una función con parámetros sin nombre. Esto sirve para sobrecargar las funciones y discernir cual se usa. Por ejemplo: podemos implementar la funcíón

incremento

dos veces más. Pero esta vez con dos parámetros. El primero es la variable a incrementar y el segundo sólo es para indicar (mediante su tipo) qué función se ha de invocar:

void incrementa(byte &); // Declaramos que existe la función "incrementa" que tiene un parámetro de tipo "referencia a byte". Como sólo la estamos declarando no es necesario indicar el nombre del parámetro.

void incrementa(byte &b, int) { // Esta no es una declaración, es una implementación completa de la función. El segundo parámetro no tiene nombre porque sólo se utiliza para sobrecargar la función "incrementa"
    b += 10;
};

void incrementa(byte &b, char) { // Esta no es una declaración, es una implementación completa de la función. El segundo parámetro no tiene nombre porque sólo se utiliza para sobrecargar la función "incrementa"
    b += 100;
};

void setup() {
    Serial.begin(9600);
    byte b = 1;
    Serial.print(F("Valor de b antes de incrementar: "));
    Serial.println(b);
    incrementa(b); // Invocamos a la función que hemos declarado al principio.
    Serial.print(F("Valor de b despues de incrementar: "));
    Serial.println(b);
    incrementa(b, 0); // Invocamos a la función que tiene dos parámetros (el segundo parámetro es de tipo int)
    Serial.print(F("Valor de b despues volver a incrementar: "));
    Serial.println(b);
    incrementa(b, 'x'); // Invocamos a la función que tiene dos parámetros (el segundo parámetro es de tipo char)
    Serial.print(F("Valor de b despues de otro incremento: "));
    Serial.println(b);
}

void loop() {
}

// A continuación implementamos la función "incrementa" que habíamos declarado al principio.
void incrementa(byte &b) {
    b++;
}

Como se podrá observar, el segundo parámetro no se usa dentro de la función. Por lo que no es necesario ponerle un nombre.

Esto último, lo de usar parámetros sólo por su tipo para sobrecargar las funciones, es algo que sólo tiene sentido en muy pocas ocasiones y que sólo usan “programadores avanzados”. Pero lo de declarar las funciones sin poner el nombre de los parámetros para después poner su implementación es algo que sí se suele ver. Personalmente prefiero poner siempre los nombres (con algo de sentido) ya que ayudan a leer y comprender el código.

Perdón por el Off-Topic.

No creo que esto conteste a tu pregunta, más que nada porque no tengo claro cual es tu pregunta. Pero tal vez te de alguna pista de lo que buscas.

Las "cadenas de C" no son más que un array de caracteres. Pero un array "muy básico". Tienen un tamaño que has de prefijar previamente y de ese tamaño no te puedes salir. Si quieres incrementar su tamaño ya deber de asignar memoria dinámicamente. La variable que hace referencia al array no es más que un puntero al tipo char (ahí ya tienes "tu puntero"). Esta cadenas pueden resultar complicadas de manejar si se quiere manipular su contenido o cambiar de tamaño. Sin embargo no suelen dar muchos problemas si lo único que se quiere es definirlas y pasar unas u otras como valores que no se piensan cambiar mucho. Pero si se quieren alterar, concatenar, truncar, etc; en tal caso sí que son una verdadera fuente de problemas si no se saben tratar. Pero, incluso sabiendo y teniendo experiencia, no es raro que den problemas.

Un ejemplo del uso de una "cadena de C":

char cadena[5]; // La cadena va a ocupar cinco byte, no más.

void funcion(char* c) {
    c[0] = 'H'; // Valor del primer byte
    c[1] = 'o'; // Valor del segundo byte
    c[2] = 'l'; // Valor del tercer byte
    c[3] = 'a'; // Valor del cuarto byte
    c[4] = 0;   // Valor del quinto byte (el cero es para indicar el final de la cadena)
}

void setup() {
    Serial.begin(9600);
    funcion(cadena);
    Serial.println(cadena);
}

void loop() {
}

Ojo con poner tratar de asignar un valor al "presunto" sexto byte de

cadena

o cualquier otro más allá del quinto. Lo que probablemente estaría haciendo es cambiar el valor de alguna variable localizada en memoria junto a la variable

cadena

. Corrompiendo su valor y pudiendo hacer que el programa se comporte anómalamente.

Es más seguro usar

String

. Son "las cadenas del C++". Son mucho más fáciles de manejar y (en principio) más seguras. Pero por contra gastan algo más de memoria. Ejemplo:

String cadena; // La String se tomará la memoria que estime necesaria para almacenar el valor

void funcion(String &c) {
    c = "Hola mundo.";
}   

void setup() {
    Serial.begin(9600);
    funcion(cadena);
    Serial.println(cadena);
}

void loop() {
}

Con

String

no te has de preocupar de reservar memoria según el tamaño de la cadena a almacenar, ya se encarga de ello por sí solo. Incluso puedes concatenar una con otra sin complicaciones.