Convertire indirizzo di memoria (ptr) to int e viceversa, è possibile?

Buongiorno,
come da oggetto, è possibile fare qualcosa del genere?

  int i = 1;

  int a[3];
  a[0] = 48;
  a[1] = 99;
  a[2] = (int)&i;  //<== è corretto?

  i = 2;

  int *p = (int *)a[2]; //<== è corretto?

naturalmente ho provato, ma visto che *p mi torna 00000002, la cosa non mi convince!

Giustamente vi chiederete perchè :slight_smile:
Uso una matrice per definire, in funzione di una determinata azione (indice ella matrice), una serie di valori da assegnare ad alcuni pin oggetti.
Tutti i valori sono costanti, ad eccezione di uno che è variabile quindi il suo valore deve essere letto al momento!
Naturalmente potrei risolvere, codificando le variabili e poi con uno switch leggere la corrispondente variabile, ma siccome sono testardo cercavo un medoto all-inclusive :wink:

Quindi prima di abbandonare, vi chiedo, è possibile?

Spero di essere stato chiaro!

TIA
Federico

Non ti seguo molto bene
Usare direttamente l'operatore ampersand per avere l'indirizzo non funziona?
Forse, dato che in cpp l'operatore ampersand viene sovraccaricato nelle chiamate di funzione, forse serve passare per una variabile intermedia
Non ho qui il pc, non posso provare
Nella prima edizione del K&R puntatori e interi erano considerati equivalenti
Adesso non più, sono confuso...

Standardoil:
Usare direttamente l’operatore ampersand per avere l’indirizzo non funziona?

Mi sono riletto, non sono stato chiaro, chiedo venia :frowning:

Il problema è che la variabile non è sempre la stessa, e che può essere diversa da riga a riga della matrice, in pratica:

  ...

  int x = 1;
  int y = 2;

  int a[2][3];

  a[0][0] = 48;
  a[0][1] = 99;
  a[0][2] = (int)&x;

  a[1][0] = 47;
  a[1][1] = 98;
  a[1][2] = (int)&y;

ma forse mi sto perdendo in bicchier d’acqua

Federico

Tu di solito non cerchi farfalle in fondo al mare...
(Sarebbe un complimento..)
Quindi se mi descrivi il tuo problema, non il tentativo di soluzione, forse posso essere utile

Standardoil:
Tu di solito non cerchi farfalle in fondo al mare…

avevo capito, grazie :slight_smile:

Dopo pranzo ti posto la situazione attuale e come vorrei semplificare.

F

Ho provato! Non mi funziona si può salvare un indirizzo in un intero, l'intero contiene esattamente il numero di indirizzo,
ma assegnando la variabile intera al puntatore non compila! Ho provato con "ideone" online.

Eccomi qua.
Ti posto una semplificazione esplicativa di come funziona adesso; il programma completo di circa 900 righe, per il momento te lo risparmio, ma quando sarà completo, lo condividerò con piacere, anche perchè mi piacerebbe avere un vostro parere, visto che scrivo in C solo da poco più di un mese!

Stato attuale:

//...
int readedCmd  0;
int min_value = 10;
int current_value = 0;

void setup() {
  //...
}

void loop() {
  //leggo valore di readedCmd da bluetooth
  //...
  switch (readedCmd) {
    case CMD_NONE: {
        setNone();
        break;
      }
    case CMD_STOP: {
        setStop();
        break;
      }
    case CMD_SWC1: {
        setSwitch1(0);
        break;
      }
    case CMD_SWC2: {
        setSwitch2();
        break;
      }
    case CMD_VAL1: {
        current_value += 5;
        break;
      }
    case CMD_VAL2: {
        current_value -= 5;
        break;
      }
  }
  //...
}

void setNone() {
  digitalWrite(pin1, 0);
  digitalWrite(pin2, 0);
  analogWrite(pin3, 0);
}

void setStop() {
  digitalWrite(pin1, 0);
  digitalWrite(pin2, 0);
  analogWrite(pin3, min_value);
}

void setSwitch1() {
  digitalWrite(pin1, 1);
  digitalWrite(pin2, 0);
  analogWrite(pin3, current_value);
}

void setSwitch2() {
  digitalWrite(pin1, 0);
  digitalWrite(pin2, 1);
  analogWrite(pin3, current_value);
}

In pratica se ricevo un comando via bluetooth, a seconda del comando eseguo una determinata funzione (preferisco tenere pulito il loop principale).
Tutte queste funzioni, tendenzialmente settano dei pin (in realtà sono dei motori, ma così semplifico l'esempio).
Per i pin 1 e 2 ho sempre dei valori costanti, ma per il terzo il valore è variabile e puo' essere rilevato da due variabili (min_value, current_value), in funzione del comando ricevuto.

min_value non è costante, perchè ho intenzione di renderlo configurabile a runtime.

Naturalmente così com'è funziona benissimo e volendo potrei usare una sola funzione con uno switch, ma non semplificherebbe di molto, quindi non mi interessa particolarmente.

Ieri, mentre scarpinavo in montagna, l'aria buona mi ha instillato la malsana idea, di semplificare tutte le funzioni introducendo una matrice bidimensionale che contiene (per riga) la configurazione dei settaggi per ogni comando

So che hai capito :), ma per capirci meglio, qualcosa di questo tipo:

idx | pin1 | pin2 | pin3
 0  |  0   |   0  |   0             //setNone
 1  |  0   |   0  |   min_value     //setStop
 2  |  1   |   0  |   current_value //setSwitch1
 3  |  0   |   1  |   current_value //setSwitch2

e quindi poi, semplificare con una sola funzione, ma qui nasce il problema...
per il pin3 il valore va letto da una o più variabili, come faccio?
Quindi ho pensato di usare i puntatori delle variabili, ma avrei dovuto convertirli in int (o altro) e poi riportarli a puntatori in fase di lettura, visto che gli elementi della matrice devo essere dello stesso tipo.

aspe, ... cacchio, ho risolto! :smiling_imp:
mentre scrivevo l'ultimo paragrafo mi sono chiesto, ma come farei in net?
userei una classe, ma qui non posso, quindi... una matrice di strutture :slight_smile:
e pensare che in uno dei primi post dove ci siamo confrontati abbiamo discusso proprio di questo!

struct state_config {
  byte pin1;
  byte pin2;
  int *pin3
};

Stasera provo

Scusate la contorsione mentale e grazie per la pazienza :wink:

Federico

torn24:
Però è molto probabile che questo non sia necessario e che ci siano soluzioni diverse al problema.

Infatti, mi ero fissato, ma poi scrivendo ho trovato la soluzione :slight_smile:

Federico

[quote author=torn24 link=msg=4205082 date=156017321

[/quote]

torn24:
ma assegnando la variabile intera al puntatore non ...

devi castarla a tipo puntatore a tipo corretto
O forse basta castarla a puntatore a void ma non son sicuro

Come ho fatto ad autoquotarmi un messaggio che stavo scrivendo?

Quando si lavora coi puntatori accadono cose strane...

Federico66:
Buongiorno,
come da oggetto, è possibile fare qualcosa del genere?

  int i = 1;

int a[3];
  a[0] = 48;
  a[1] = 99;
  a[2] = (int)&i;  //<== è corretto?
  i = 2;
  int *p = (int *)a[2]; //<== è corretto?




naturalmente ho provato, ma visto che *p mi torna 00000002, la cosa non mi convince!

A me pare tutto corretto. Il valore stampato 0000002 sarebbe da capire come lo stampi a video, quel pezzo manca. Se prova int x=*p; e poi stampi x dovrebbe darti semplicemente 2.
La seconda di cui chiedi mi pare eccessiva. a essendo array viene visto da compilatore già come un puntatore
Quindi semplicemente int *p= a+2; dovrebbe accettarlo (indirizzo di a più 2).

Poi anche le funzioni possono essere chiamate attraverso dei puntatori. Ma se sbagli qualcosa… esecuzione a casaccio o crash del programma.

Comunque mi pare, da quello che scrivi e dalle tue domande, che fai confusione tra puntatore e il “cosa” punta.
Il compilatore gestisce i puntatori in base all’architettura per cui compili e quindi tutti i puntatori in un programma compilato hanno la stessa dimensione.
Diverso è dire a “cosa” punta un puntatore. *p è un puntatore. Basta.
E’ d’obbligo dire però al compilatore a “cosa” punta/punterà.
int *p1 punta a un int
long *p2 punta ad un long
Tutti e due, p1 e p2 sono di stessa dimensione (un indirizzo).
Ma uno permette di “prelevare” o leggere un int l’altro un long. Su Arduino per la Uno, p1 permette di leggere un int (2 byte) mentre p2 4 byte

torn24:
Ho provato! Non mi funziona si può salvare un indirizzo in un intero, l’intero contiene esattamente il numero di indirizzo,
ma assegnando la variabile intera al puntatore non compila! Ho provato con “ideone” online.

nid69ita:
A me pare tutto corretto. Il valore stampato 0000002 sarebbe da capire come lo stampi a video, quel pezzo manca. Se prova int x=*p; e poi stampi x dovrebbe darti semplicemente 2.

Io ho provato con VS (ricordatevi che sono nuovo di C :slight_smile: )

 char dataLine[50];

 int i = 1;
 int a[2];
 a[0] = 1;
 a[1] = (int)&i;


 int *p = (int *)a[1];
 
 sprintf_s(dataLine, "p = %p\n", p);
 cout << dataLine;
 sprintf_s(dataLine, "*p = %p\n", *p);
 cout << dataLine;
 cout << "**********************************************\n";

 i = 2;

 sprintf_s(dataLine, "p = %p\n", p);
 cout << dataLine;
 sprintf_s(dataLine, "*p = %p\n", *p);
 cout << dataLine;
 cout << "**********************************************\n";

ed ottengo questo:

p = 0038FB9C
*p = 00000001
**********************************************
p = 0038FB9C
*p = 00000002

nid69ita:
A me pare tutto corretto. Il valore stampato 0000002 sarebbe da capire come lo stampi a video, quel pezzo manca. Se prova int x=*p; e poi stampi x dovrebbe darti semplicemente 2.

Infatti colpa mia, cosi stampa esattamente 2
era %d e non %p

sprintf_s(dataLine, "*p = %d\n", *p);

Che mi sembra sia quello che cercavi
Oppure ho capito sbagliato?
Edit rispondevo al numero 11

Standardoil:
Che mi sembra sia quello che cercavi
Oppure ho capito sbagliato?
Edit rispondevo al numero 11

yes, mi aveva spaventato 00000002, per cui ho chiesto

in ogni caso, se hai letto il #6, posso risolvere anche in altro modo senza conversione (devo provare)

direi che sto imparando velocemente, sono molto soddisfatto

Grazie
Federico

PS
Aiuta molto saper cercare...

bene, son contento che tu abbia trovato una soluzione
in effetti spesso ri-guardare il problema da un differente punto di vista aiuta