Ayuda para entender este código.

Hola!! Estoy modificando una pila TCP/IP para adaptarla a un microcontrolador. El caso es que he encontrado una que tiene buena pinta, pero necesito que me echéis una mano para entenderla.
//----------------------------------------------------------------------------
//Check Packet and call Stack for TCP or UDP
#define ETHER_OFFSET         0x00
#define IP_OFFSET            0x0E
#define MTU_SIZE 600

unsigned char eth_buffer[MTU_SIZE+1];

void check_packet (void)
{
    struct Ethernet_Header *ethernet;    //Pointer auf Ethernet_Header
    struct IP_Header       *ip;          //Pointer auf IP_Header

    ethernet = (struct Ethernet_Header *)&eth_buffer[ETHER_OFFSET];
    ip       = (struct IP_Header       *)&eth_buffer[IP_OFFSET];
   
    if(ethernet->EnetPacketType == HTONS(0x0806) )     //ARP
    {
        arp_reply(); // check arp packet request/reply
    }
    else
    ...

Tengo unas estructuras con una serie de registros. Lo que hace es definir un puntero a cada una de mis estructuras, luego no sé que hace y después compruebo si uno de mis registros cumple una cosa.
GRACIAS!!!
No entiendo la pregunta... que es lo que quieres saber? Que hace en la linea en la que comprueba si la trama Ethernet contiene una peticion ARP?
O que son las estructuras?
La pregunta es, ¿qué hace esta linea?
ethernet = (struct Ethernet_Header *)&eth_buffer[ETHER_OFFSET];
manugarrote escribió:La pregunta es, ¿qué hace esta linea?
ethernet = (struct Ethernet_Header *)&eth_buffer[ETHER_OFFSET];


Aparentemente hace que la estructura que tienes, llamada "ethernet", apunte a la direccion de memoria del array de chars llamado eth_buffer, en su posicion inicial (porque ETHER_OFFSET esta definido como 0);
En la siguiente linea repite, pero como es la estructura del paquete IP, apunta a una posicion mas avanzada de ese mismo array, donde empieza el paquete IP dentro de la trama Ethernet.
Jan@work escribió:
manugarrote escribió:La pregunta es, ¿qué hace esta linea?
ethernet = (struct Ethernet_Header *)&eth_buffer[ETHER_OFFSET];


Aparentemente hace que la estructura que tienes, llamada "ethernet", apunte a la direccion de memoria del array de chars llamado eth_buffer, en su posicion inicial (porque ETHER_OFFSET esta definido como 0);
En la siguiente linea repite, pero como es la estructura del paquete IP, apunta a una posicion mas avanzada de ese mismo array, donde empieza el paquete IP dentro de la trama Ethernet.


Efectivamente. Toma la dirección de memoria de eth_buffer[ETHER_OFFSET] (el modificador & es la dirección en memoria de lo que referencia). Luego esa dirección se asigna al puntero de una estructura tipo Ethernet_Header llamada ethernet.
Otra cuestión. Si yo voy rellenando las distintas variables de la estructura, por ejemplo utilizando los punteros a estructuras así:
ethernet->EnetPacketType=(0xFFFF);
ethernet->EnetPacketSrc[0]='A';

¿Cómo se ordenarían en memoria? Es decir, si el puntero ethernet apunta a la primera posición del vector eth_buffer, ¿dónde se meterían el resto de campos de la estructura? Me imagino que sea en las posiciones de memoria contiguas (ocupando cada una dependiendo de su tipo de variable).

GRACIAS!!!
manugarrote escribió:Otra cuestión. Si yo voy rellenando las distintas variables de la estructura, por ejemplo utilizando los punteros a estructuras así:
ethernet->EnetPacketType=(0xFFFF);
ethernet->EnetPacketSrc[0]='A';

¿Cómo se ordenarían en memoria? Es decir, si el puntero ethernet apunta a la primera posición del vector eth_buffer, ¿dónde se meterían el resto de campos de la estructura? Me imagino que sea en las posiciones de memoria contiguas (ocupando cada una dependiendo de su tipo de variable).

GRACIAS!!!

Se "ordenan" en el mismo orden en el que están definidas en la estructura.
He estado haciendo pruebas con este código, para ver si lo entendía, pero no soy capaz:
#include <stdio.h>

struct miestructura   {
   char caracter;
   int entero;
} prueba;

#define INICIO         0x00

unsigned char vector[10];

void funcion (void)
{
    struct miestructura *prueba;    //Puntero a una variable estructura tipo "miestructura"
   
    prueba = (struct miestructura *)&vector[INICIO];//Apunta a la dirección 0 de mi vector
       
    prueba->caracter='A'; //relleno los campos
    prueba->entero=6; //relleno los campos
}

int main ()
{
    funcion();
   
    for (int i=0;i<10;i++)
        printf("%i ",vector[i]);//Imprimo mi vector 
   
}


Tras compilar y ejecutar me sale ésto:
65 0 0 0 6 0 0 0 0 0

¿No me deberían salir el 65 y el 6 pegados?
manugarrote escribió:He estado haciendo pruebas con este código, para ver si lo entendía, pero no soy capaz:
#include <stdio.h>

struct miestructura   {
   char caracter;
   int entero;
} prueba;

#define INICIO         0x00

unsigned char vector[10];

void funcion (void)
{
    struct miestructura *prueba;    //Puntero a una variable estructura tipo "miestructura"
   
    prueba = (struct miestructura *)&vector[INICIO];//Apunta a la dirección 0 de mi vector
       
    prueba->caracter='A'; //relleno los campos
    prueba->entero=6; //relleno los campos
}

int main ()
{
    funcion();
   
    for (int i=0;i<10;i++)
        printf("%i ",vector[i]);//Imprimo mi vector 
   
}


Tras compilar y ejecutar me sale ésto:
65 0 0 0 6 0 0 0 0 0

¿No me deberían salir el 65 y el 6 pegados?


En teoria si, pero en la practica el compilador alinea la estructura que estas declarando con un padding de 4 bytes (osea que alinea las variables para que empiezen en posiciones de memoria multiplos de 4) para que tenga un mejor rendimiento al acceder a las variables en memoria. Esto nunca lo vas a notar a menos que intentes hacer un cast como el que acabas de hacer. En fin, la solución para que el compilador no ponga el padding es diciendole mediante una opción de preporcesador que no haga (o mejor dicho que lo haga con un padding de 1 byte):

#pragma pack(push,1)
struct miestructura   {
   char caracter;
   int entero;
} prueba;
#pragma pack(pop)


Esto es usado mucho por ejemplo cuando tienes que leer/escribir vectores de bytes con/en una estrcutura. De hecho me imagino que la estructura "Ethernet_Header" que pones más arriba debe tener los modificadores de padding que menciono si usa campos de tipo int, char, etc.
En teoria si, pero en la practica el compilador alinea la estructura que estas declarando con un padding de 4 bytes (osea que alinea las variables para que empiezen en posiciones de memoria multiplos de 4) para que tenga un mejor rendimiento al acceder a las variables en memoria. Esto nunca lo vas a notar a menos que intentes hacer un cast como el que acabas de hacer. En fin, la solución para que el compilador no ponga el padding es diciendole mediante una opción de preporcesador que no haga (o mejor dicho que lo haga con un padding de 1 byte):

#pragma pack(push,1)
struct miestructura   {
   char caracter;
   int entero;
} prueba;
#pragma pack(pop)


Esto es usado mucho por ejemplo cuando tienes que leer/escribir vectores de bytes con/en una estrcutura. De hecho me imagino que la estructura "Ethernet_Header" que pones más arriba debe tener los modificadores de padding que menciono si usa campos de tipo int, char, etc.

En ese ejemplo vale, pero he probado a meter otra variable en la estructura (una tipo long para tener 8, 16 y 32 bits). He puesto la instrucción para el preprocesador que me has dicho, pero no funciona.

Nuevo código:
#include <stdio.h>

#pragma pack(push,1)
struct miestructura   {
   unsigned char caracter;
   unsigned int entero;
   unsigned long largo;
} prueba;
#pragma pack(pop)

#define INICIO         0x00

unsigned char vector[10];

void funcion (void)
{
    struct miestructura *prueba;    //Puntero a una variable estructura tipo "miestructura"
   
    prueba = (struct miestructura *)&vector[INICIO];//
       
    prueba->caracter=0xFF;
    prueba->entero=0xFFFF;
    prueba->largo=0xFFFFFFFF;
}

int main ()
{
    funcion();
   
    for (int i=0;i<10;i++)
        printf("%i ",vector[i]);   
   
}

Ahora lo que me sale es esto:
255 255 255 0 0 255 255 255 255 0

El primer dato (el tipo char) sale bien.
El tipo int sale pegado al char.
Pero el tipo long no lo hace.

GRACIAS!!!
manugarrote escribió:En ese ejemplo vale, pero he probado a meter otra variable en la estructura (una tipo long para tener 8, 16 y 32 bits). He puesto la instrucción para el preprocesador que me has dicho, pero no funciona.


Un int no es siempre 16 bits ni el long de 32 bits, eso ya depende de la arquitectura a la cual estés compilando (imprime los valores de sizeof(int) y sizeof(long) para que te des cuenta). Por ejemplo en un x86 el int y el long es de 32 bits, pero en amd64 el int sigue siendo de 32 bits mientras que el long es de 64 bits. Viniendo por ese camino tus asignaciones del valor maximo al int y long no siempre van a ser las correctas dependiendo de la arquitectura a la cual compiles.
codestation escribió:
manugarrote escribió:En ese ejemplo vale, pero he probado a meter otra variable en la estructura (una tipo long para tener 8, 16 y 32 bits). He puesto la instrucción para el preprocesador que me has dicho, pero no funciona.


Un int no es siempre 16 bits ni el long de 32 bits, eso ya depende de la arquitectura a la cual estés compilando (imprime los valores de sizeof(int) y sizeof(long) para que te des cuenta). Por ejemplo en un x86 el int y el long es de 32 bits, pero en amd64 el int sigue siendo de 32 bits mientras que el long es de 64 bits. Viniendo por ese camino tus asignaciones del valor maximo al int y long no siempre van a ser las correctas dependiendo de la arquitectura a la cual compiles.

Ok!! Mi programa es para una arquitectura muy concreta (un microcontrolador), pero lo tendré en cuenta a la hora de hacer la pila, para que sea compatible con los que tengan distinto tamaño de palabra.

De todas formas, ¿por qué no ha funcionado la instrucción del preprocesador?
manugarrote escribió:Ok!! Mi programa es para una arquitectura muy concreta (un microcontrolador), pero lo tendré en cuenta a la hora de hacer la pila, para que sea compatible con los que tengan distinto tamaño de palabra.

De todas formas, ¿por qué no ha funcionado la instrucción del preprocesador?


La salida que estas posteando es del código compilado para el microcontrolador o compilando genericamente con el compilador de tu SO?

Si es lo segundo: la instrucción de preprocesador ha funcionado, pero lo que pasa es que no has "llenado" completamente el int:
prueba->entero=0xFFFF;

En esa parte solo llenas 16 bits, lo cual puede funcionar en tu microcontrolador (asumiendo que el int tenga 16 bits allí), pero no si lo estás compilando para correrlo en tu SO, en el cual el int es de 32 bits.
   255    255 255 0 0   255 255 255 255   0
| char |      int     |       long       |

(asumiendo que estás compilando codigo para amd64)

Ten el tamaño de las variables muy en cuenta si quieres hacer codigo portable entre tu pc y tu microcontrolador.
codestation escribió:La salida que estas posteando es del código compilado para el microcontrolador o compilando genericamente con el compilador de tu SO?

Si es lo segundo: la instrucción de preprocesador ha funcionado, pero lo que pasa es que no has "llenado" completamente el int:
prueba->entero=0xFFFF;

En esa parte solo llenas 16 bits, lo cual puede funcionar en tu microcontrolador (asumiendo que el int tenga 16 bits allí), pero no si lo estás compilando para correrlo en tu SO, en el cual el int es de 32 bits.

Cierto, antes de ller tu respuesta he estado "jugando" y he visto que en mi PC, tanto el int, como el long ocupan 32 bits.

Una pregunta más, y creo que te dejo en paz por hoy. El tamaño de las variables viene impuesto por la arquitectura del micro, ¿no se puede hacer dada al respecto?

PD: muchísimas gracias por tu paciencia me has sido de una GRAN ayuda!!
PD2: para hacer pruebas en mi PC cambiaré int por short.
manugarrote escribió:Cierto, antes de ller tu respuesta he estado "jugando" y he visto que en mi PC, tanto el int, como el long ocupan 32 bits.

Una pregunta más, y creo que te dejo en paz por hoy. El tamaño de las variables viene impuesto por la arquitectura del micro, ¿no se puede hacer dada al respecto?

PD: muchísimas gracias por tu paciencia me has sido de una GRAN ayuda!!

El tamaño viene impuesto por la arquitectura que le digas al compilador que debe usar, generalmente el compilador que uses va a usar la arquitectura del micro que estés usando (probablemente no se cumpla para todos los casos). En todo caso si necesitas usar variables de un tamaño en especifico puedes usar las definidas en <stdint.h>, por ejemplo en tu estructura anterior:
struct miestructura   {
   unsigned char caracter;
   uint16_t entero;
   uint32_t largo;
} prueba;

Allí tienes un carácter de 1 byte, un unsigned int de 16 bits y otro de 32 bits. Lo cual debería mantenerse para cualquier arquitectura que implementes.
Sigo teniendo problemas. Pensaba que lo tenía todo claro, por lo que me he puesto a hacer un ejercicio de ejemplo (para comprobar que lo había entendido), pero no me sale...
#include <stdio.h>
#include <stdlib.h>//Para generar el nº aleatorio
#include <stdint.h>//Para tipos de datos raros

#pragma pack(push,1)
struct IP_Header   {
   unsigned char   IP_Vers_Len;   //8 Bits (Versión + Tamaño cabecera)
   unsigned char   IP_Tos;         //8 Bits Type of Service
   uint16_t   IP_Pktlen;      //16 Bits
   uint16_t   IP_Id;         //16 Bits
   uint16_t   IP_Frag_Offset;   //16 Bits (Flags + Posición del fragmento)
    unsigned char   IP_ttl;         //8 Bits
   unsigned char   IP_Proto;      //8 Bits
   uint16_t   IP_Hdr_Cksum;   //16 Bits Checksum
   uint32_t   IP_Srcaddr;      //32 Bits IP Fuente
   uint32_t   IP_Destaddr;   //32 Bits IP Destino
};
#pragma pack(pop)

#define IP_OFFSET            0x00
//#define MTU_SIZE              600 //(Maximum Transfer Unit) unidad máxima de transferencia
#define MTU_SIZE               10 //Para pruebas
#define RAND_MAX              255 //Para pruebas

unsigned char buffer[MTU_SIZE+1];

void check_packet (void)
{
    struct IP_Header       *ip; //Puntero a tipo IP_Header
    ip = (struct IP_Header *)&buffer[IP_OFFSET];//Puentero en la Posición IP de la trama
   
    printf("%c ",ip->IP_Vers_Len);
    printf("%c ",ip->IP_Tos);
    printf("%c ",ip->IP_Pktlen);
    printf("%c ",ip->IP_Id);
    printf("%c ",ip->IP_Frag_Offset);
    printf("%c ",ip->IP_ttl);
    printf("%c ",ip->IP_Proto);
    printf("%c ",ip->IP_Hdr_Cksum);
    printf("%c ",ip->IP_Srcaddr);
    printf("%c ",ip->IP_Destaddr);
}

int main ()
{
    for (int i=0;i<(MTU_SIZE);i++){ //-----------------------------------------------
        buffer[i]=rand();             // Generamos y mostramos una cabecera aleatoria
        printf("%c ",buffer[i]);}     //-----------------------------------------------
   
    printf("\n");
    check_packet();
}

A la salida tengo:
) # ¥ ä ß l Í « R É
) # ¥ ß Í R É

Hay algunos caracteres que no se representan y no sé por qué.

GRACIAS!!!
manugarrote escribió:A la salida tengo:
) # ¥ ä ß l Í « R É
) # ¥ ß Í R É

Hay algunos caracteres que no se representan y no sé por qué.

GRACIAS!!!


Bueno, estás llenando el vector de datos "aleatorios" y luego los imprimes a caracteres, me sorprendería lo contrario :-| . Mucho mejor seria que mostraras la data en HEX por lo menos para que pudieras ver los datos y comparar mejor. Mirate mejor "man 3 printf" o busca por internet como dar un mejor formato a lo que intentas mostrar por consola.
codestation escribió:Bueno, estás llenando el vector de datos "aleatorios" y luego los imprimes a caracteres, me sorprendería lo contrario :-| . Mucho mejor seria que mostraras la data en HEX por lo menos para que pudieras ver los datos y comparar mejor. Mirate mejor "man 3 printf" o busca por internet como dar un mejor formato a lo que intentas mostrar por consola.

Ayer busqué los argumentos que se le podían pasar a printf porque me olía que el problema podría ser de eso, pero no encontré tanta información como la que tu me has dicho.

He probado con el identificador x y algo hemos avanzado. Ahora la salida es ésta:
29 23 be 84 e1 6c d6 ae 52 90
29 23 84be 6ce1 aed6 52 90 0 0 0

Por lo que se puede apreciar que algo falla, que estoy cerca de dar con la solución pero no termino de entender por qué falla (sólo con mis datos de 16bits) ni como solucionarlo.

PD: gracias por tu paciencia.
manugarrote escribió:
codestation escribió:Bueno, estás llenando el vector de datos "aleatorios" y luego los imprimes a caracteres, me sorprendería lo contrario :-| . Mucho mejor seria que mostraras la data en HEX por lo menos para que pudieras ver los datos y comparar mejor. Mirate mejor "man 3 printf" o busca por internet como dar un mejor formato a lo que intentas mostrar por consola.

Ayer busqué los argumentos que se le podían pasar a printf porque me olía que el problema podría ser de eso, pero no encontré tanta información como la que tu me has dicho.

He probado con el identificador x y algo hemos avanzado. Ahora la salida es ésta:
29 23 be 84 e1 6c d6 ae 52 90
29 23 84be 6ce1 aed6 52 90 0 0 0

Por lo que se puede apreciar que algo falla, que estoy cerca de dar con la solución pero no termino de entender por qué falla (sólo con mis datos de 16bits) ni como solucionarlo.

PD: gracias por tu paciencia.


El 29 y el 23 se imprimen "bien" porque son los atributos IP_Vers_Len e IP_Tos (que son, de acuerdo a su definición, de tipo char que ocupa un byte).

El 84b6 se te imprime así por dos motivos. Uno porque es el atributo IP_Pktlen de la estructura IP_Header, que tiene 16 bits -> ocupa 2 bytes. El otro motivo es porque la arquitectura del equipo en el que estás ejecutando el programa es little-endian, y los datos se te almacenan "al revés" de lo que diría el sentido común. Pero esto es solo un tema de almacenamiento en memoria, e intuyo que será más rápido para la CPU el hacer esto. Lo importante es que NO se produzcan "mezclas de datos" (por esto, el printf (%c) te salían distintas líneas, porque hacías printf de char en elementos de tipo int16)

Con el 6ce1 y el aed6 pasa lo mismo, las estructuras IP_Id e IP_Frag_Offset ocupan 16 bits.

El 52 se corresponde con IP_ttl, de tipo char.

El 90 se corresponde con IP_Proto, que también es de tipo char.

Los 3 últimos valores son cero porque no has asignado ningún valor aleatorio a las estructuras IP_Hdr_Cksum, IP_Srcaddr e IP_Destaddr. Es decir, el bucle del main te rellena 10 bytes, peeeeero tu estructura "ip" te ocupa más de 10 bytes (concretamente, sumando salen 1 + 1 + 2 + 2 +2 + 1 + 1 + 2 + 4 + 4 = 20 bytes).

Espero haberte aclarado las cosas!
Muchísimas gracias. He trabajado con 4 micros y tienen arquitecturas distintas.
x86 es little endian
I8085 es little endian
MC68000 es big endian
ATMEGA32 es big endian

Eso me lo imaginaba, pero no pillaba lo de los números que no me salían y fue una cagada echando cuentas (en versiones anteriores de mi archivo de prueba sí que tenía puesto los 20 valores).

Pues ahora lo tengo claro, ya he entendido completamente el código original, ahora me toca cambiarlo y adecuarlo a mi cometido.

GRACIAS a todos!!!
Ya que tengo el hilo abierto y es una duda de C lo pregunto aquí.
Tengo 2 arrays de caracteres, pongamos que son:
unsigned char EnetPacketDest[6];
unsigned char EnetPacketSrc[6];

Quiero intercambiar sus valores, es decir, que EnetPacketDest tenga los valores de EnetPacketSrc y viceversa. He intentado hacerlo utilizando un puntero como temporal para almacenar la dirección de memoria, pero el compilador me ha dicho que soy un borrico, literalmente "ISO C++ forbids assignment of arrays".

Una forma que se me ocurre de hacerlo es crean un array auxiliar, utilizar un bucle para copiar los valores del EnetPacketDest y luego otro bucle para copiar del auxiliar al EnetPacketSrc.

¿Hay alguna forma más elegante de hacer esto? Gracias!!!
manugarrote escribió:Ya que tengo el hilo abierto y es una duda de C lo pregunto aquí.
Tengo 2 arrays de caracteres, pongamos que son:
unsigned char EnetPacketDest[6];
unsigned char EnetPacketSrc[6];

Quiero intercambiar sus valores, es decir, que EnetPacketDest tenga los valores de EnetPacketSrc y viceversa. He intentado hacerlo utilizando un puntero como temporal para almacenar la dirección de memoria, pero el compilador me ha dicho que soy un borrico, literalmente "ISO C++ forbids assignment of arrays".

Una forma que se me ocurre de hacerlo es crean un array auxiliar, utilizar un bucle para copiar los valores del EnetPacketDest y luego otro bucle para copiar del auxiliar al EnetPacketSrc.

¿Hay alguna forma más elegante de hacer esto? Gracias!!!


Pues no sé como lo habrás hecho, pero a mi sí me deja asignar un vector a un puntero. De hecho la manera que tiene C de tratar apuntadores y vectores es bastante similar, de manera que puedes trabajar con arrays como si fueran punteros y viceversa. El nombre del vector equivaldría a la primera posición del vector a la que le puedes ir sumando un desplazamiento para acceder a los demás elementos, etc => v[i] == *(v + i)

char *p;
char v[3] = {'a', 'b','c'};
p = v;


Saludos:).
Yog-Sothoth escribió:Pues no sé como lo habrás hecho, pero a mi sí me deja asignar un vector a un puntero. De hecho la manera que tiene C de tratar apuntadores y vectores es bastante similar, de manera que puedes trabajar con arrays como si fueran punteros y viceversa. El nombre del vector equivaldría a la primera posición del vector a la que le puedes ir sumando un desplazamiento para acceder a los demás elementos, etc => v[i] == *(v + i)

char *p;
char v[3] = {'a', 'b','c'};
p = v;


Saludos:).

Eso sí que puedo hacerlo... [+risas]
El problema viene a la hora de asignar al vector la dirección del puntero
manugarrote escribió:El problema viene a la hora de asignar al vector la dirección del puntero

Ah vale, es que no había entendido eso.
El nombre de un vector no es una variable, por eso no puedes hacer la asignación que propones. Yo creo que lo estás haciendo bien usando vectores y fors para recorrer los vectores y copiarlos de un sitio a otro.

Saludos:).
AL final lo he dejado así:
unsigned char temporal[6];
     for (int i=0;i<6;i++){
      temporal[i]=ethernet->EnetPacketDest[i];   
      ethernet->EnetPacketDest[i]=ethernet->EnetPacketSrc[i];
      ethernet->EnetPacketSrc[i]=temporal[i];
    }

Mi profesor dice que programando soy muy práctico pero poco elegante [+risas]
manugarrote escribió:AL final lo he dejado así:
unsigned char temporal[6];
     for (int i=0;i<6;i++){
      temporal[i]=ethernet->EnetPacketDest[i];   
      ethernet->EnetPacketDest[i]=ethernet->EnetPacketSrc[i];
      ethernet->EnetPacketSrc[i]=temporal[i];
    }

Mi profesor dice que programando soy muy práctico pero poco elegante [+risas]


Ten en cuenta que no necesitas todo un vector auxiliar para hacer el swap, de hecho con sola una variable simple bastaría.

EDIT: como alternativa, en este caso especifico también puedes omitir el usar una variable auxiliar usando la operación XOR
    for (int i=0;i<6;i++){
      ethernet->EnetPacketDest[i] ^= ethernet->EnetPacketSrc[i];
      ethernet->EnetPacketSrc[i] ^= ethernet->EnetPacketDest[i];
      ethernet->EnetPacketDest[i] ^= ethernet->EnetPacketSrc[i];
    }
codestation escribió:Ten en cuenta que no necesitas todo un vector auxiliar para hacer el swap, de hecho con sola una variable simple bastaría.

EDIT: como alternativa, en este caso especifico también puedes omitir el usar una variable auxiliar usando la operación XOR
    for (int i=0;i<6;i++){
      ethernet->EnetPacketDest[i] ^= ethernet->EnetPacketSrc[i];
      ethernet->EnetPacketSrc[i] ^= ethernet->EnetPacketDest[i];
      ethernet->EnetPacketDest[i] ^= ethernet->EnetPacketSrc[i];
    }

Es cierto, con una variable simple me apaño!! Es que en un principio pensaba hacerlo de otra forma, pero al copiar el código en el foro se me ocurrió una más efectiva y me salté ese detalle jeje, pero gracias por recordarlo.
Le echaré un vistazo con más detenimiento a esa manera, que ahorrar siempre está bien, más aún cuando hablamos de microcontroladores.
Gracias!!!
http://en.wikipedia.org/wiki/XOR_swap_algorithm

En concreto lee con detenimiento la parte de "Reasons for avoidance in practice.".

Este también es interesante: http://big-bad-al.livejournal.com/98093.html (está enlazado en la propia página de Wikipedia)

Saludos.
Ferdy escribió:http://en.wikipedia.org/wiki/XOR_swap_algorithm

En concreto lee con detenimiento la parte de "Reasons for avoidance in practice.".

Este también es interesante: http://big-bad-al.livejournal.com/98093.html (está enlazado en la propia página de Wikipedia)

Saludos.

Hoy he entrado a hace otra pregunta y me encuentro con ésto... MUCHAS GRACIAS!!! Trabajando con micros el minismalisto es muy importante ;)

Mi nueva duda:
Estoy implementando la pila TCP/IP en una librería aparte y también un programa principal sobre el que estoy haciendo pruebas. El caso es que hay 3 variables que comparten mi programa principal y mi librería. En concreto son: miMAC, miIP, buffer (donde almaceno cada paquete que me llega y luego lo proceso mi librería). El caso es que ahora mismo tengo creadas por duplicado (en el main y en la librería) miMAC, miIP en los dos sitios. La dirección del buffer la paso como parámetro cuando llamo a las función de mi librería, ¿hay alguna forma más eficiente de hacerlo?

GRACIAS!!

PD: mi librería también utiliza un archivo de cabeceras, por si puede ser útil.
28 respuestas