mikrocontroller.net

Forum: Compiler & IDEs Ansi C: Convertierung int to string


Autor: Entwickler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, in einer Mikrocontroller Applikation soll ein Integer-Wert in ein 
String umgewandelt werden.
unsigned int ip = 0xc0a8010c
char* cip

In cip soll dan der string "192.168.1.12" drin stehen

Wie könnte sowas in Ansi C realisiert werden?

: Verschoben durch Moderator
Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit sprintf und etwas Schieberei

: Bearbeitet durch User
Autor: Frickelfritze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entwickler schrieb:
> Mikrocontroller

Entwickler schrieb:
> unsigned int

Das wird so nicht funktionieren da dein int warscheinlich
(du hast den Controller nicht genannt) nur 16 Bit breit
sein wird .....

Entwickler schrieb:
> char* cip

Das wird nicht funktionieren da du nur einen Pointer auf
einen String reserviert hast. Der reservierte Speicherbereich
dazu fehlt aber .....

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn dir die Schieberei nicht gefällt, mach eine union mit einem 
char-Array und dem unsigned int.
Zur Umwandlung der Zahl kannst du auch itoa nehmen.

itoa ist allerdings nicht in Ansi-C enthalten, aber auf den meisten 
Compilern für Mikrocontroller vorhanden.

Autor: Christopher Johnson (christopher_j23)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die passenden Suchwörter für Google wären snprintf, printf und itoa, um 
eine beliebige Ganzzahl in einen Char umzuwandeln.
Natürlich musst du deine 32bit in vier mal acht Bit zerhacken, jeweils 
in einen Char umwandeln und zwischendurch noch jeweils einen Punkt 
einfügen.

Autor: Dergute Weka (derguteweka)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Moin,

C-Libraries, die auf geheimen Microcontrollern laufen, koennten evtl. 
auch die Funktion inet_ntoa() kennen, die sowas aehnliches hinkriegt.

Gruss
WK

Autor: Christopher Johnson (christopher_j23)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meinte oben natürlich char-Array statt char

Autor: Der Andere (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> auf geheimen Microcontrollern

Zumindest scheint der geheime µC ein 32 Bit Typ zu sein, sonst wäre der 
"unsigned int" wahrscheinlich zu klein für den Wert.

Insofern wächst die Wahrscheinlichkeit dass libs zu IP existieren und 
Funktionen wie inet_addr(), inet_aton() und inet_ntoa() schon 
existieren.

Vieleicht mal da schauen:
http://www.gnu.org/software/libc/manual/html_node/...

Autor: Der Andere (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Dirk B. schrieb:
> Wenn dir die Schieberei nicht gefällt, mach eine union mit einem
> char-Array und dem unsigned int.

?
Das hätte ich gerne mal ausprogrammiert gesehen.

Autor: Frickelfritze (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Der Andere schrieb:
> sonst wäre der
> "unsigned int" wahrscheinlich zu klein für den Wert.

Die warscheinlichere Version ist dass der TO nicht weiss
was er da wirklich tut. Denn er hält es ja auch nicht für
nötig auf den Typ des Controllers hinzuweisen.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entwickler schrieb:
> In cip soll dan der string "192.168.1.12" drin stehen
>
> Wie könnte sowas in Ansi C realisiert werden?

Zum Beispiel so:

#include <stdint.h>
#include <stdio.h>

int main()
{
    uint32_t ip = 0xc0a8010c;
    char cip[16];
    
    sprintf(cip, "%d.%d.%d.%d", (uint8_t)(ip >> 24), (uint8_t)(ip >> 16), (uint8_t)(ip >> 8), (uint8_t)ip);
    
    printf("IP-Adresse als String: %s\n", cip);
    
    return 0;
}


IP-Adresse als String: 192.168.1.12

Autor: Amateur (Gast)
Datum:

Bewertung
-6 lesenswert
nicht lesenswert
Oder etwas übersichtlicher:

unsigned int iip = 0xc0a8010c;
unsigned int ip1;
unsigned int ip2;
unsigned int ip3;
unsigned int ip4;
char         cip [16];

ip4 = iip & 0xff;
iip = iip >> 4;
ip3 = iip & 0xff;
iip = iip >> 4;
ip2 = iip & 0xff;
iip = iip >> 4;
ip1 = iip & 0xff;
sprintf ( cip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4 );

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So?
#include <stdio.h>
#include <stdlib.h>
//#include <arpa/inet.h>
//#include <netinet/in.h>
#include <winsock.h>

int main(int argc, char *argv[])
{ 
  union {
   unsigned int ip;
   unsigned char c[4];
  } u;
  
  unsigned int ip = 0xc0a8010c;
  char cip[16];
  
  u.ip = htonl(ip);
  
  sprintf(cip, "%d.%d.%d.%d", u.c[0], u.c[1], u.c[2], u.c[3]);
  printf("%s\n", cip);
  
  system("PAUSE");  
  return 0;
}

Beim Linken "-lwsock32" nicht vergessen...

: Bearbeitet durch User
Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder eben doch geschoben:
#include <stdio.h>
#include <stdlib.h>
//#include <arpa/inet.h>
//#include <netinet/in.h>
#include <winsock.h>


int main(int argc, char *argv[])
{
  unsigned int ip = 0xc0a8010c;
  char cip[16];
  
  ip = htonl(ip);
  
  sprintf(cip, "%d.%d.%d.%d\n", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
  printf("%s\n", cip);
  
  system("PAUSE");  
  return 0;
}

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entwickler schrieb:
> In cip soll dan der string "192.168.1.12" drin stehen

Heute noch IPv6 inkompatibel programmieren ?

Amateur schrieb:
> Oder etwas übersichtlicher:

Kaum.

Tim T. schrieb:
> So?

Eher nicht, die byte-order der int auf char[4] ist maschinenabhängig.

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MaWin schrieb:
> Tim T. schrieb:
>> So?
>
> Eher nicht, die byte-order der int auf char[4] ist maschinenabhängig.

Dafür ist htonl doch drin...

Und bevor auch noch am int gemosert wird:

#include <stdint.h>
und
uint32_t ip = 0xc0a8010c;

nehmen

Autor: Frickelfritze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim T. schrieb:
> Und bevor auch noch am int gemosert wird:

So lernt der TO nix dazu .....

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Frickelfritze schrieb:
> Tim T. schrieb:
>> Und bevor auch noch am int gemosert wird:
>
> So lernt der TO nix dazu .....

Als ob dieses Forum dazu da ist den Leuten zu helfen, pffft.
Hier geht es nur darum an allem rumzumosern, klug zu scheissen, 
Bildformate und Rechtschreibung zu kritisieren, den TO runterzuputzen 
und möglichst weit von einer einfachen Lösung fern zu halten.

Autor: Arduino Fanboy (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frickelfritze schrieb:
> So lernt der TO nix dazu .....
Manche Aussagen sind so dermaßen abwegig, dass noch nicht einmal das 
Gegenteil richtig ist.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim T. schrieb:
> So?
Die Verwendung einer union zur Daten-Konvertierung ist undefined 
behaviour in Ansi C, und je nach Plattform ist die IP-Adresse verdreht! 
(Littie/Big Endian).

Daher ist die Lösung mit Bitshifts besser, weil sie immer funktioniert, 
wie hier:

Mark B. schrieb:
> Zum Beispiel so:

Tim T. schrieb:
> Oder eben doch geschoben:
Das ist falsch so, denn deine Bitshifts funktionieren ohne htonl 
korrekt, mit htonl gehts aber auf manchen Plattformen schief! Richtig 
gewollt aber falsch gemacht :-)

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Tim T. schrieb:
>> So?
> Die Verwendung einer union zur Daten-Konvertierung ist undefined
> behaviour in Ansi C, und je nach Plattform ist die IP-Adresse verdreht!
> (Littie/Big Endian).

Nein, das union ist sehrwohl definiert, die daten im int jedoch nicht, 
das wurde durch htonl korrigiert.

>
> Daher ist die Lösung mit Bitshifts besser, weil sie immer funktioniert,
> wie hier:

Öhm, nein.


> Mark B. schrieb:
>> Zum Beispiel so:
>
> Tim T. schrieb:
>> Oder eben doch geschoben:
> Das ist falsch so, denn deine Bitshifts funktionieren ohne htonl
> korrekt, mit htonl gehts aber auf manchen Plattformen schief! Richtig
> gewollt aber falsch gemacht :-)

Und wieder nein.

Autor: Peter II (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Tim T. schrieb:
> Öhm, nein.

kannst du das begründen?

> Und wieder nein.
das auch?

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim T. schrieb:
> Nein, das union ist sehrwohl definiert, die daten im int jedoch nicht,
> das wurde durch htonl korrigiert.
Ah stimmt, das htonl hab ich übersehen. Seltsamer Ansatz aber sollte 
funktionieren.

Tim T. schrieb:
> Öhm, nein.
Öhm, doch. z.B. "(0x12345678 >> 8) & 0xFF" liefert immer 0x56, 
unabhängig von der Byte-Reihenfolge der Plattform. Daher ist ein solcher 
Ansatz dem Umweg über eine union+htonl immer vorzuziehen...

Tim T. schrieb:
> Und wieder nein.
Doch.

Tim T. schrieb:
> ip = htonl(ip);
Verdreht auf Little-Endian Architekturen die Reihenfolge.

>   sprintf(cip, "%d.%d.%d.%d\n", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16)
> & 0xff, (ip >> 24) & 0xff);
Gibt bei gegebenem Inhalt von "ip" immer das gleiche aus unabhängig 
von der Plattform. Da du also am Anfang je nach Plattform 1x verdrehst, 
kommt auf BE/LE Systemen jeweils was anderes heraus.

Hier noch ein Ansatz mit getnameinfo. Dieser funktioniert auf 
POSIX-kompatiblen Systemen. Der Vorteil ist hier, dass der auch trivial 
auf IPv6 umgebaut werden kann (mit sockaddr_in6 statt sockaddr_in). 
getnameinfo kann direkt mit der Adresse aus z.B. accept() oder 
getaddrinfo() genutzt werden, sodass das Programm komplett unabhängig 
von IPv4 vs. IPv6 wird.
#include <stdio.h>
#include <stddef.h>

#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/ip.h>

int main (void) {
  char hostname [100];
  int res;
  struct sockaddr_in addr;

  addr.sin_family = AF_INET;
  addr.sin_port = 0;
  addr.sin_addr.s_addr = htonl (0xc0a8010c);
  
  res = getnameinfo ((struct sockaddr*) &addr, sizeof (addr), hostname, sizeof (hostname), NULL, 0, NI_NUMERICHOST);
  if (res == 0) {
    printf ("Adresse als String: %s\n", hostname);
    return 0;
  } else {
    printf ("Fehler: %s\n", gai_strerror (res));
    return 1;
  }
}

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Tim T. schrieb:
>> So?
> Die Verwendung einer union zur Daten-Konvertierung ist undefined

Er ist in guter Gesellschaft:

https://msdn.microsoft.com/en-us/library/windows/d...
typedef struct in_addr {
  union {
    struct {
      u_char s_b1,s_b2,s_b3,s_b4;
    } S_un_b;
    struct {
      u_short s_w1,s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

Nenn mal ein ABI bei dem das nicht so funktionieren kann (korrekte 
Verwendung von htonl und ntohl natürlich vorausgesetzt).

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bernd schrieb:
> Er ist in guter Gesellschaft:
Du verwendest Microsoft als Referenz bei Fragen zum C-Standard? Wo sich 
Microsoft doch so gut mit Standards zu Programmiersprachen und 
Betriebssystemen auskennt... ;-) Wie z.B. das "FAR" genau da, das sieht 
total nach C-Standard aus. In einer C Standard Library ist eine union 
aber schon besser aufgehoben, da diese onehin plattformspezifisch ist.

Bernd schrieb:
> Nenn mal ein ABI bei dem das nicht so funktionieren kann (korrekte
> Verwendung von htonl und ntohl natürlich vorausgesetzt).
Darum gehts nicht... Ich habe sogar geschrieben dass es funktionieren 
müsste. Dennoch ist es so, dass der C-Standard da einfach sagt 
"undefined". Im C-Standard steht auch nichts von ntohl. Eine 
Undefiniertheit in der Programmiersprache mit einer 
Betriebssystem-Funktion auszubügeln ist unschön. Bitshifts sind die 
bevorzugte, einfache, sichere, wohldefinierte Methode. Ich verstehe 
nicht, warum sich da alle gegen wehren?
Mark Brandis hat eine einfache, korrekte, standard-konforme, immer 
funktionierende Lösung gepostet. Diese ist den anderen Frickelein, die 
"funktionieren müssten", zu bevorzugen...

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Wie z.B. das "FAR" genau da, das sieht total nach C-Standard aus.

Was hat denn der C-Standard gegen Preprozessor Makros?

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guest schrieb:
> Was hat denn der C-Standard gegen Preprozessor Makros?
Windowsspezifische Makros für far/near pointer Unterscheidung sind nicht 
gerade portabel. Ist zum Glück nur ein Relikt ohne Bedeutung.

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> guest schrieb:
>> Was hat denn der C-Standard gegen Preprozessor Makros?
> Windowsspezifische Makros für far/near pointer Unterscheidung sind nicht
> gerade portabel. Ist zum Glück nur ein Relikt ohne Bedeutung.

far/near Pointer sind sowieso Platform-/Compilerspezifisch. Von daher 
wird das durch die Makros noch eher portabel als ohne.
Außerdem ist der Rest drum rum auch nicht portabel, nennt sich ja nicht 
Umsonst Platform SDK bzw. Windows SDK.

Das mit dem Relikt ist natürlich richtig.

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Dennoch ist es so, dass der C-Standard da einfach sagt
> "undefined".

ich meine, in diesem Fall sagt er nicht "undefined", sondern 
"implementation defined".

D.h. was dabei passiert, steht nicht im C-Standard, sondern im 
Compilerhandbuch.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.