Autor Tema: Asignación global en C  (Leído 1831 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Asignación global en C
« en: 08 de Febrero de 2018, 08:05:43 »
.

Buenas.

Tengo un problema a la hora de asignar un valor a "una variable" declarada globamente. Lo he puesto entre comillas, porque realmente no se si es una variable o que diablos es (creo que es una estructura o una unión, declarada en un .h).

Esta es la declaración:
IPAddress IP_Remote(255, 255, 255, 255); // IP para Broadcast

Vale que queda declarada globalmente y se puede leer desde cualquier parte o función del programa, el problema viene cuando quiero cambiar su valor desde una función o desde el main. Es el valor de una IP Remota para enviar paquetes de datos por UDP, que el usuario puede cambiar en un fichero de configuración de texto almacenado en tarjeta SD.

Leo el archivo de la SD, depuro y trato de cambiar el valor, el resultado es que no lo hace a nivel global.

Si hago por ejemplo esto: IPAddress IP_Remote(192, 168, 1, 3); , no afecta a la variable global, parece que crea la misma variable pero a nivel local, comprobado por Debug. Con lo cual no usa el nuevo valor de IP en la función encargada de enviar los paquetes UDP.

Si hago esto: IP_Remote(192, 168, 1, 3); , me da error de compilación.

No se como cambiar esa variable a nivel global. Al final lo he resuelto con un truco, los valores de la IP en el fichero de configuración, los guardo en una matriz declarada como global, y cuando se va a utilizar en la instrucción UDP, le pongo los elementos de la matriz directamente en la instrucción así; 
Udp.beginPacket(IPAddress (ipxr[0], ipxr[1], ipxr[2], ipxr[3]), localPort);

Así me funciona, pero me gustaría saber como cambiar esa variable a nivel global, y que no me cree otra variable del mismo nombre pero local.
« Última modificación: 08 de Febrero de 2018, 08:08:32 por planeta9999 »

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Asignación global en C
« Respuesta #1 en: 08 de Febrero de 2018, 08:17:42 »

Acabo de probar esto, y compilar compila, lo que no se todavía es si lo ha asignado a la variable global, sospecho que si porque IP_Remote no está declarada a nivel local con ningún tipo. La matriz ipxr está declarada como global y ahí almaceno la configuración de IP que el usuario ha configurado en la tarjeta SD.

IP_Remote = IPAddress (ipxr[0], ipxr[1], ipxr[2], ipxr[3]);
« Última modificación: 08 de Febrero de 2018, 08:20:45 por planeta9999 »

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Asignación global en C
« Respuesta #2 en: 08 de Febrero de 2018, 13:20:53 »
Supongo estas utilizando Arduino o algo similar, el tipo de variable IPAddress puede ser la que esta (medio) documentada aqui [1].

Según esto [2] así se le cambian los valores a la variable de tipo IPAddress:
Código: [Seleccionar]
IP_Remote[0] = ipxr[0];
IP_Remote[1] = ipxr[1];
IP_Remote[2] = ipxr[2];
IP_Remote[3] = ipxr[3];

No lo puedo comprobar pero fue lo único que encontré en el foro de arduino.

[1] https://www.arduino.cc/en/Reference/EthernetIPAddress
[2] https://forum.arduino.cc/index.php?topic=54324.0

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Asignación global en C
« Respuesta #3 en: 08 de Febrero de 2018, 13:32:05 »
antes de empezar a tratar de que puede ser el problema, lo primero que deberias dar es en que lo estas haciendo, MCU, Compilador, libreria, etc.

Si es como dice Carl47D entonces es C++.
A pesar que son parecidos son totalmente distintos.

Y lo que estas haciendo aca:

Código: C++
  1. IPAddress IP_Remote(255, 255, 255, 255); // IP para Broadcast

Es utilizar un constructor de la clase IPAddress.
Ejecutar nuevamente el constructor es crear una NUEVA instancia del valor, es por eso que no tenes buenos resultados.
Dentro de la clase los valores de IP son privados, por lo cual no pueden ser accedidos directamente por alguien de forma externa, solo pueden ser cambiados por las funciones miembros de la Clase.

Revisando un par de codigos de la clase IPAddress, me encuentro que hace un overload del operador asignacion "="

Código: C++
  1. IPAddress& IPAddress::operator=(const uint8_t *address)
  2. {
  3.     memcpy(_address.bytes, address, sizeof(_address.bytes));
  4.     return *this;
  5. }

Por lo tanto opino que lo que deberias hacer es esto:

Código: C++
  1. // Declarado primero
  2. IPAddress IP_Remote(255, 255, 255, 255); // IP para Broadcast
  3.  
  4. // Para cambiarlo:
  5. uint8_t mIP[4] = {192,168,0,2};      //Creo un array con el valor de IP
  6. IP_Remote = mIP;  //Asigno el nuevo valor
« Última modificación: 08 de Febrero de 2018, 13:42:46 por KILLERJC »

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Asignación global en C
« Respuesta #4 en: 08 de Febrero de 2018, 14:51:38 »
 
Gracias a ambos, Carl y Killer, lo probaré todo.

También tengo que probar si el cambio que yo hice funciona, porque si compila:
IP_Remote = IPAddress (ipxr[0], ipxr[1], ipxr[2], ipxr[3]);

La librería es la EthernetUdp2 para Teensy (Kinetis), bajo el entorno de Arduino. He encontrado el IPAddress.h, donde se define la clase y los constructores.


#ifndef IPAddress_h
#define IPAddress_h
#include <Printable.h>
#include <WString.h>

// A class to make it easier to handle and pass around IP addresses

class IPAddress : public Printable {
private:
   union {
      uint8_t bytes[4]; // IPv4 address
      uint32_t dword;
   } _address;

   // Access the raw byte array containing the address.  Because this returns a pointer
   // to the internal structure rather than a copy of the address this function should only
   // be used when you know that the usage of the returned uint8_t* will be transient and not
   // stored.

   uint8_t * raw_address() { return _address.bytes; };

public:
   // Constructors
   IPAddress() {
      _address.dword = 0;
   }
   IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
      _address.bytes[0] = b1;
      _address.bytes[1] = b2;
      _address.bytes[2] = b3;
      _address.bytes[3] = b4;
   }
   IPAddress(uint32_t address) {
      _address.dword = address;
   }
   IPAddress(const uint8_t *address) {
      // TODO: use unaligned read on Cortex-M4
      _address.bytes[0] = *address++;
      _address.bytes[1] = *address++;
      _address.bytes[2] = *address++;
      _address.bytes[3] = *address++;
   }

   bool fromString(const char *address);
   bool fromString(const String &address) {
      return fromString(address.c_str());
   }

   // Overloaded cast operator to allow IPAddress objects to be used where a pointer
   // to a four-byte uint8_t array is expected

   operator uint32_t () {
      return _address.dword;
   }
   bool operator==(const IPAddress& addr) {
      return _address.dword == addr._address.dword;
   }
   bool operator==(const uint8_t* addr) {
      // TODO: use unaligned read on Cortex-M4
      return (_address.bytes[0] == addr[0]
         && _address.bytes[1] == addr[1]
         && _address.bytes[2] == addr[2]
         && _address.bytes[3] == addr[3]);
   }

   // Overloaded index operator to allow getting and setting individual octets of the address
   uint8_t operator[](int index) const {
      return _address.bytes[index];
   };
   uint8_t& operator[](int index) {
      return _address.bytes[index];
   };

   // Overloaded copy operators to allow initialisation of IPAddress objects from other types
   IPAddress& operator=(const uint8_t *address) {
      // TODO: use unaligned read on Cortex-M4
      _address.bytes[0] = *address++;
      _address.bytes[1] = *address++;
      _address.bytes[2] = *address++;
      _address.bytes[3] = *address++;
      return *this;
   }
   IPAddress& operator=(uint32_t address) {
      _address.dword = address;
      return *this;
   }

   virtual size_t printTo(Print& p) const;

   friend class EthernetClass;
   friend class UDP;
   friend class Client;
   friend class Server;
   friend class DhcpClass;
   friend class DNSClient;
};

const IPAddress INADDR_NONE((uint32_t)0);


#endif
« Última modificación: 08 de Febrero de 2018, 15:03:33 por planeta9999 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Asignación global en C
« Respuesta #5 en: 08 de Febrero de 2018, 15:47:46 »
Citar
También tengo que probar si el cambio que yo hice funciona, porque si compila:
IP_Remote = IPAddress (ipxr[0], ipxr[1], ipxr[2], ipxr[3]);

Pienso que debería funcionar también, ya que lo que estas haciendo es crear un objeto temporario y luego como no hay ningún overload por default del operador = entonces C++ provee por si solo una función por default de la copia del mismo, es decir esta funcion:

Código: C++
  1. IPAddress& operator=(const IPAddress& Source){}

Las otras funciones declaradas poseen otro tipo de argumento.

-------------

Ese archivo es parecido al IPAddress.cpp que encontre para Arduino por internet, nomas que este posee el overload del operador de comparacion

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Asignación global en C
« Respuesta #6 en: 10 de Febrero de 2018, 07:26:35 »

Ok, gracias Killer. Probare las dos formas de asignar nuevo valor.