Char array nach Struct casten...

Zeiss

BIOS-Overclocker(in)
Servus miteinander,

irgendwie habe ich gerade einen Knoten im Hirn. Hier erstmal der Code:
Code:
#include "stdafx.h"

struct test_struct {
    char src[2];
    char dst[2];
    char msg[4];
};


char buffer[] = "abcdefgh";


int main(int argc, _TCHAR* argv[])
{
    struct test_struct *tmp_pckt = (struct test_struct *) buffer;


    printf("src: %s\n", tmp_pckt->src);
    printf("dst: %s\n", tmp_pckt->dst);
    printf("msg: %s\n", tmp_pckt->msg);


    int i = 10;


    return 0;
}

Ich habe ein char array (buffer[]), mit abcdefgh als Inhalt, diesen caste ich nach test_struct, klappt auch so weit, der Compiler wirft keine Fehler oder Warnings.

Nun, mein Problem ist aber die Ausgabe, die sieht nämlich so aus:
Code:
src: abcdefgh
dst: cdefgh
msg: efgh

Ich hätte jetzt erwartet, dass
Code:
src: ab
dst: cd
msg: efgh
sind, so wie die Feldlängen im Struct. Oder habe ich einen Denkfehler?

Getestet mit VS2013 und gcc.
 
Zuletzt bearbeitet:
Nimm vielleicht auch mal den Adressoperator &. Bietet sich an bei *. Dann braucht der Code nicht so oft am BMW Casting teilzunehmen im RAM=Hubraum :-)
 
Zuletzt bearbeitet:
Hallo Zeiss,

Die drei Zeichenketten liegen in deinem Struct quasi eng aneinander,
dh. stehen ohne ein Trennzeichen Byte für Byte hintereinander.

Printf, und alle anderen Funktionen die auf C-Strings operieren,
werten diese jedoch solange aus, bis der Null-Terminator erscheint.

Da zwischen den einzelnen Strings src, dst und msg kein Byte mit dem Wert Null steht,
wertet Printf diese immer vom Startpointer bis zur nächsten im Speicher liegenden 0 aus.
Du hast hier quasi Glück, dass nach tmp_pckt direkt eine Null steht.

Ich sehe hier zwei Möglichkeiten:

  • Dein struct um 3 Nullbytes zu erweitern,
  • Oder explizit Funktionen benutzen, bzw. erstellen, denen bekannt ist, wie lang die einzelnen Felder von test_struct sind
Die erste Möglichkeit ist etwas einfacher, wenn auch speicherhungriger:
Code:
struct test_struct { 
     char src[3]; 
     char dst[3]; 
     char msg[5]; 
}; 

char buffer[] = „ab\0cd\0efgh\0“; 
// Der Rest des Codes sollte weiterhin funktionieren
‚\0‘ ist hierbei ein Zeichen, in ASCII mit dem Wert 0, welches als Endsymbol in Nullterminierten Strings (auch C-Strings genannt) dient.

Deine Absicht hinter dem Codestück ist leider nicht ganz klar.
Falls es garnicht so sehr darum ging,
Zeichenketten hintereinander in einem Struct anzulegen,
sondern eher darum,
einen bestehenden String in Teilstrings fester Länge zu zerlegen,
kommst du um Möglichkeit 2 nicht herum:

Hier eine schnell reinkopierte Lösung von Stackoverflow:
Code:
char *buff = "this is a test string";
char subbuff[5];
memcpy( subbuff, &buff[10], 4 );
subbuff[4] = '\0';

Oder hier eine Lösung, wie man mit printf nur einen bestimmten Teil eines Strings ausgibt: Link

Hoffe ich konnte dir weiterhelfen.

Viele Grüße,
Marvin
 
Zuletzt bearbeitet:
Hey Marvin,

beim Lesen ist mir das Licht aufgegangen, danke Dir. Ich bin schon mal auf diese printf(..) Geschichte reingefallen. Klar, printf(...) gibt den String so lange aus, bis \0 kommt, dann bricht er ab.

Das mit dem "abschließenden" \0 wird nicht gehen, weil 0x00 ein gültiger Wert ist. Die Längen der einzelnen Felder sind bekannt. Mein Fehler war, dass ich eine Stringfunktion verwendet habe.

Im Debugger sieht alles richtig aus :)
 
Zuletzt bearbeitet von einem Moderator:
Ups, habe vergessen, dass es in C keinen eigenen Datentyp 'Byte' gibt, und war jetzt auf Zeichen bzw. Character gefixt.
Dabei wird aus der Namensgebung eigentlich klar, dass es sich um eine Hilfsstruktur für ein Netzwerkpaket oÄ. handelt.
Aber freut mich, dass ich dir weiterhelfen konnte.
 
Es geht um eine Kontrollbotschaft, die über den MOST-Bus verschickt wird. Sie ist zwar um einiges komplizierter und auch länger, aber das spielt hier keine Rolle.

Das 16 bzw. 17 Byte langer Puffer wird über I²C ausgelesen und dann in die Bestandteile zerpflückt.
 
Allen Denver - Serial Communications in Win32 API: Serial Communications

dann kannste auch:
include <stdio.h> weglassen, wennde die MS Windows Header includiert hast. wennde auf scheibe kommen willst, nobugz ist ein microsoft programmierer, der hat es richtig drauf.

IquadratC. Wennde ne fertige Library brauchst, weil bei dem Allen Denver ein paar Adressoperatoren '&' fehlen: Windows Serial Communication Component Library for serial port communication; modem library, virtual serial ports, usb to serial port component, serial control, RS232, RS422, RS485

Ich habe overlapped mal ähnlich Allen Denver implementiert. Ich gebe zu, das war ganz schön harter Tobak. Unter MS-DOS ist das einfach, aber in einer Multitasking Umgebung ist das echt nicht leicht. Da ist man ans Betriebssystem gebunden. Mit Timern wird das nichts. Das geht nur über Hardware und Software Interrupts, Systemtimer. Da ist dein eigentlicher Codeansatz so weit von entfernt, wie die Erde von der Sonne.

Docklight Scripting kann ich Dir empfehlen zum debuggen..
 
Zuletzt bearbeitet:
Mal wieder völlig am Thema vorbei, völlige Planlosigkeit und Lichtjahre vom Thema entfernt, aber Hauptsache was geschrieben.
Und willkommen auf meiner Igno-Liste.
 
ist es dafür nötig, printf zu nutzen? Ansonsten hast du hier ja ein Problem, dass für deine Umsetzung völlig irrelevant ist, sondern lediglich die Debug-Ausgabe verbuggt ist :P
 
Nein, natürlich nicht. Wenn man es (es = die Elemente des Structs) wirklich ausgeben wollen würde, bräuchte man eine Funktion, die auch die Anzahl der auszugebenden Bytes als Parameter bekommt. Es ist eben kein String.

Das, was ich eigentlich haben wollte, funktioniert ja richtig, sieht man im Debugger:

cast-png.1015541
 

Anhänge

  • cast.png
    cast.png
    11,7 KB · Aufrufe: 195
Zurück