Lösung für "dereferenzieren" void * "- Zeiger" - Warnung in struct in C?
Ich habe versucht, erstellen Sie eine pseudo-super-struct drucken array von structs. Mein basic
Strukturen sind wie folgt.
/* Type 10 Count */
typedef struct _T10CNT
{
int _cnt[20];
} T10CNT;
...
/* Type 20 Count */
typedef struct _T20CNT
{
long _cnt[20];
} T20CNT;
...
Habe ich die unten struct drucken Sie das array von oben genannten Strukturen. Ich habe dereferenzieren void-Zeiger Fehler beim kompilieren des folgenden code-snippet.
typedef struct _CMNCNT
{
long _cnt[3];
} CMNCNT;
static int printCommonStatistics(void *cmncntin, int cmncnt_nelem, int cmncnt_elmsize)
{
int ii;
for(ii=0; ii<cmncnt_nelem; ii++)
{
CMNCNT *cmncnt = (CMNCNT *)&cmncntin[ii*cmncnt_elmsize];
fprintf(stout,"STATISTICS_INP: %d\n",cmncnt->_cnt[0]);
fprintf(stout,"STATISTICS_OUT: %d\n",cmncnt->_cnt[1]);
fprintf(stout,"STATISTICS_ERR: %d\n",cmncnt->_cnt[2]);
}
return SUCCESS;
}
T10CNT struct_array[10];
...
printCommonStatistics(struct_array, NELEM(struct_array), sizeof(struct_array[0]);
...
Meine Absicht ist es, eine gemeinsame Funktion drucken Sie alle arrays. Bitte lassen Sie mich wissen, den richtigen Weg, es zu benutzen.
Dankbar für die Hilfe im Voraus.
Edit: Der name des Parameters wird geändert, um cmncntin von cmncnt. Sorry, es war Tippfehler Fehler.
Dank,
Mathew Liju
Man sollte Sie nur verwenden, Gewerkschaften, wäre es viel einfacher: typedef union { long cnt_long; int cnt_int; } CNT; CNT zählt[20];
Erklären Sie bitte, was meinen Sie mit super Struktur und überprüfen Sie die Beispiel-code, den Sie geschrieben haben. Meinst du das wirklich: typedef struct _T10CNT { int _cnt[20]; }
Super Struktur ist die Struktur, die auf ähnliche Strukturen mit ähnlichen Datentypen. Im obigen Beispiel TL10CNT, TL20CNT sind ähnliche Typen. Meine Absicht ist, für den Druck die Struktur, die ich brauche, um zu schreiben-Funktionen für jede Struktur. Stattdessen kann ich verwenden Sie ein einzelnes struct-pointer um die Daten zu erhalten.
Symbol Namen beginnen mit"_", gefolgt von einem Großbuchstaben vorbehalten sind, durch die Implementierung von C/C++ - standard-Bibliotheken. Sollten Sie wirklich ändern Sie Ihre Namenskonvention.
Vielleicht solltest du uns sagen, was Sie versuchen zu tun? Es ist unmöglich, zu versuchen, zu drucken, aus jedem struct in C. Das ist nicht C++
Erklären Sie bitte, was meinen Sie mit super Struktur und überprüfen Sie die Beispiel-code, den Sie geschrieben haben. Meinst du das wirklich: typedef struct _T10CNT { int _cnt[20]; }
Super Struktur ist die Struktur, die auf ähnliche Strukturen mit ähnlichen Datentypen. Im obigen Beispiel TL10CNT, TL20CNT sind ähnliche Typen. Meine Absicht ist, für den Druck die Struktur, die ich brauche, um zu schreiben-Funktionen für jede Struktur. Stattdessen kann ich verwenden Sie ein einzelnes struct-pointer um die Daten zu erhalten.
Symbol Namen beginnen mit"_", gefolgt von einem Großbuchstaben vorbehalten sind, durch die Implementierung von C/C++ - standard-Bibliotheken. Sollten Sie wirklich ändern Sie Ihre Namenskonvention.
Vielleicht solltest du uns sagen, was Sie versuchen zu tun? Es ist unmöglich, zu versuchen, zu drucken, aus jedem struct in C. Das ist nicht C++
InformationsquelleAutor Liju Mathew | 2008-11-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, Ihr design ist zum scheitern verurteilt, aber ich bin auch nicht überzeugt, dass die anderen Antworten sehe ich, voll befassen sich mit der tieferen Gründe, warum.
Scheint es, dass Sie versuchen, verwenden Sie C, um den Umgang mit generischen Typen, etwas, das immer bekommt haarige. Sie können es tun, wenn Sie vorsichtig sind, aber es ist nicht einfach, und in diesem Fall habe ich Zweifel, ob es lohnenswert wäre.
Tieferen Grund: nehmen wir an, wir bekommen Vergangenheit die bloße syntaktische (oder kaum mehr als syntaktische) Probleme. Dein code zeigt, dass T10CNT enthält 20
int
und T20CNT enthält 20long
. Auf modernen 64-bit-Maschinen - andere als unter Win64 -sizeof(long) != sizeof(int)
. Also, der code, der in Ihrem Druck-Funktion sollte die Unterscheidung zwischen array-Dereferenzierungint
arrays undlong
arrays. In C++ gibt es eine Regel, dass Sie sollten nicht versuchen, die Behandlung von arrays, polymorph, und diese Art der Sache ist, warum. Die CMNCNT Typ enthält 3long
Werte sind, anders als die T10CNT und T20CNT Strukturen in der Anzahl, wenn der Basistyp des Arrays entspricht T20CNT.Stil Empfehlung: ich empfehle die Vermeidung führende Unterstriche auf Namen. In allgemein, Namen beginnend mit Unterstrich beginnen, sind reserviert für die Umsetzung zu nutzen und zu verwenden, wie Makros. Makros haben keinen Respekt für den Anwendungsbereich, wenn die Durchführung definiert ein makro _cnt es würde ruinieren Ihre code. Es sind Nuancen, welche Namen sind reserviert; ich bin nicht about to gehen Sie in diese Nuancen. Es ist viel einfacher zu denken 'beginnen im Namen mit Unterstrich beginnen, sind reserviert', und Steuern Sie klar von Schwierigkeiten.
Stil Vorschlag: Ihre print-Funktion gibt Erfolg bedingungslos. Das ist nicht sinnvoll; Ihre Funktion sollte nichts zurück, so dass der Anrufer nicht haben, um zu testen, die für Erfolg oder Misserfolg (da kann es nie nicht). Eine sorgfältige Programmierer, der stellt fest, dass die Funktion einen status testen immer die return-status und error-handling-code. Dieser code wird nie ausgeführt werden, so ist es tot, aber es ist schwer für alle, die (oder der compiler) zu bestimmen.
Oberfläche Beheben: Vorübergehend, können wir davon ausgehen, dass Sie behandeln können
int
undlong
als Synonyme; aber Sie müssen raus aus der Gewohnheit zu denken, dass Sie sind Synonyme, obwohl. Dievoid *
argument ist der richtige Weg, zu sagen: "diese Funktion nimmt einen Zeiger von unbestimmter Art". Jedoch, innerhalb der Funktion, die Sie benötigen, zu konvertieren von einemvoid *
auf einen bestimmten Typ, bevor Sie die Indizierung.(Ich mag die Idee von einem Datei-stream genannt
stout
zu. Vorschlag: verwenden Sie cut ' N ' Paste auf den echten source code--es ist sicherer! Ich bin in der Regel verwenden "sed 's/^/ /' file.c
" vorzubereiten code für cut ' N ' Paste in ein SO Antwort.)Was bedeutet, dass cast line tun? Ich bin froh, dass Sie gefragt...
const void *
in eineconst char *
; dies können Sie tun, byte-Größe, die Operationen auf die Adresse. In den Tagen vor der Standard Cchar *
verwendet wurde anstelle vonvoid *
als die Universelle Adressierung Mechanismus.i
te element des array von Objekten der Größeelemsize
.Von dort, der code ist einfach genug. Beachten Sie, dass seit dem CMNCNT Struktur enthält
long
Wert, den ich verwendet%ld
die Wahrheit zu sagen,fprintf()
.Da Sie nicht über die zum ändern der Daten in dieser Funktion, ist es nicht eine schlechte Idee, verwenden Sie die
const
qualifier wie ich es Tat.Beachten Sie, dass, wenn Sie gehen, um treu sein zu
sizeof(long) != sizeof(int)
, dann müssen Sie zwei separate code-Blöcke (ich würde vorschlagen, getrennte Funktionen) mit dem deal Reihe vonint
' und 'array vonlong
' Struktur-Typen.InformationsquelleAutor Jonathan Leffler
Den Typ void ist bewusst unvollständig gelassen. Aus diesem Grund folgt Sie nicht dereferenzieren void-Zeiger, und weder können Sie den sizeof. Dies bedeutet, Sie können verwenden den subskript-operator verwenden es wie ein array.
Dem moment zuweisen, was zu einem void-Zeiger, jede Art von Informationen von der original-wies auf eine Art verloren, so können Sie nur zu dereferenzieren, wenn Sie zuerst warf es wieder auf den ursprünglichen Typ Zeiger.
Erste und das wichtigste, Sie passieren
T10CNT*
auf die Funktion, aber Sie versuchen zu festgelegten (und dereferenzieren), die zuCMNCNT*
in Ihrer Funktion. Dieser ist nicht gültig und wird nicht definiertes Verhalten.Müssen Sie eine Funktion printCommonStatistics für jeden Typ der array-Elemente. So, habe eine
printCommonStatisticsInt
,printCommonStatisticsLong
,printCommonStatisticsChar
die sich alle unterscheiden, indem Sie Ihr erstes argument (eine Einnahmeint*
, die anderen nehmenlong*
, und so weiter). Sie erstellen Sie Makros verwenden, um zu vermeiden, redundanten code.Übergeben, die struct selbst ist nicht eine gute Idee, denn dann muss man eine neue Funktion definieren, die für jede unterschiedliche Größe der enthaltenen array innerhalb der Struktur (da Sie alle verschiedene Arten). Also besser passieren das enthaltene array direkt (
struct_array[0]._cnt
, rufen Sie die Funktion für jeden index)InformationsquelleAutor Johannes Schaub - litb
Ändern Sie die Deklaration der Funktion char * etwa so:
den void-Typ nicht davon ausgehen, keine Besondere Größe in der Erwägung, dass ein char, nehmen eine byte-Größe.
Gut, ich denke, Sie müssen gegossen, wenn Sie die Funktion aufrufen zB. printCommonStatistics((char )mydata, Elemente, elementsize), aber den Start chaotisch jetzt. Warum müssen Sie geben Ihre Struktur als void ?
void * Typ gecastet zu jedem Datentyp. Die Funktion müssen sich nicht die Mühe, ob der parameter vom Typ char oder int-Typ oder den benutzerdefinierten Typ.
Ja, aber Sie müssen nicht werfen Sie Ihre void* , jeder Typ, der ist, warum der compiler verwirrt.
Obwohl die Verwendung von 'char *' ist Teil der Lösung, die 'void *' ist die bessere Wahl in der Funktion-Schnittstelle.
InformationsquelleAutor Adam Pierce
Können Sie nicht tun:
wenn cmnct ist ein void-Zeiger.
Müssen Sie den Typ angeben. Möglicherweise müssen Sie überdenken Ihre Umsetzung.
InformationsquelleAutor Klathzazt
Die Funktion
Funktioniert für mich.
Das Problem ist, dass auf der Linie, sagte: "Ptr-Line" fügt der code einen Zeiger auf eine Ganzzahl. Da unser pointer ist ein "char *" wir bewegen uns in Erinnerung sizeof(char) * ii * cmncnt_elemsize, das ist, was wir wollen, da ein char ist ein byte. Ihr code versucht, eine gleichwertige Sache voran sizeof(void) * ii * cmncnt_elemsize, aber leere nicht eine Größe haben, damit der compiler gab Sie den Fehler.
Würd ich ändern T10CNT und T20CNT sowohl mit int oder long anstelle von einer mit jedem. Sie sind abhängig von sizeof(int) == sizeof(long)
InformationsquelleAutor David Norman
In dieser Zeile:
Sie versuchen, deklarieren Sie eine neue variable namens cmncnt, aber eine variable mit diesem Namen existiert bereits als parameter an die Funktion. Sie möchten möglicherweise verwenden Sie einen anderen Variablennamen zu lösen.
Außerdem können Sie wollen, übergeben Sie einen Zeiger auf eine CMNCNT an die Funktion anstelle von einem void-Zeiger, weil dann der compiler den Zeiger-Arithmetik für Sie und Sie nicht haben, um Sie zu wirken. Ich sehe nicht den Punkt der übergabe eines void-Zeiger, wenn alles, was Sie tun ist, werfen Sie es zu einem CMNCNT. (Das ist keine sehr aussagekräftigen Namen für ein Daten-Typ, übrigens.)
InformationsquelleAutor Jeremy Ruten
Ihren Ausdruck
versucht, die Adresse von cmncntin[ii*cmncnt_elmsize] und dann die Besetzung, die Zeiger auf Typ (CMNCNT *). Es kann nicht die Adresse von cmncntin[ii*cmncnt_elmsize] weil cmncntin hat den Typ void*.
Studie C-operator prš und einfügen von Klammern, wo nötig.
Du hast Recht. Ich habe den Fehler gemacht, zu erklären, um das original-poster, warum der compiler gab "dereferenzieren void-pointer-Fehler" anstelle von "Meine Absicht ist es, eine gemeinsame Funktion drucken Sie alle arrays. Bitte lassen Sie mich wissen, den richtigen Weg, es zu benutzen." Hast u senden teh-codes?
InformationsquelleAutor Windows programmer
Point-of-Information: Interne Polsterung kann wirklich Schrauben.
Betrachten struct { char c[6]; }; -- Es hat sizeof()=6. Aber wenn Sie hatte eine Reihe von diesen, jedes element kann aufgefüllt werden, aus, um ein 8-byte-Ausrichtung.
Bestimmten Montagearbeiten nicht behandeln, mis-aligned Daten anmutig. (Zum Beispiel, wenn eine int-erstreckt sich über zwei Speicher-Worte.) (JA, ich habe gebissen worden von diesem vor.)
.
Zweitens: In der Vergangenheit habe ich verwendet, variabel große arrays. (Ich war dumm damals...) Es funktioniert, wenn Sie ändern sich nicht geben. (Oder, wenn Sie eine union der Arten.)
E. g.:
Verteilt sich wie
(Obwohl Polsterung/Ausrichtung kann noch Schrauben.)
.
Dritte: Erwägen:
Löst es die Probleme mit dem wissen, wie drucken Sie die Daten.
.
Viertens: Sie könnten nur pass in der int - /long-array, um Ihre Funktion eher als die Struktur. E. g:
Aufgerufen über:
Oder:
So viel besser funktioniert als das verstecken von Daten in Strukturen. Als Sie mit dem hinzufügen von Mitgliedern zu einer Ihrer Struktur, das layout kann sich ändern, zwischen Ihrem struct ' s und keine mehr im Einklang. (Das bedeutet die Adresse von _cnt relativ zum start der Struktur kann sich ändern, für _T10CNT und nicht für _T20CNT. Spaß debugging-Zeiten. Eine einzelne Struktur mit einer union ' ed _cnt Nutzlast würde dies vermeiden.)
E. g.:
.
Fünften:
Wenn Sie verwenden müssen Strukturen... C++ iostreams und templating wäre viel sauberer zu implementieren.
E. g.:
Aber das ist wahrscheinlich nicht das was du suchst...
InformationsquelleAutor Mr.Ree
C ist nicht meine Tasse o'java, aber ich glaube, dein problem ist, dass "void *cmncnt" sollte CMNCNT *cmncnt.
Fühlen Sie sich frei, mich zu korrigieren, jetzt C-Programmierer, und Sag mir, das ist der Grund, warum java-Programmierer können nicht schöne Dinge haben.
InformationsquelleAutor Ari Ronen
Diese Zeile ist eine Art gefoltert, don ' Tcha denken?
Wie wäre es mit etwas mehr wie
Oder noch besser, wenn cmncnt_elmsize = sizeof(CMNCNT)
Sollten auch loszuwerden, die Warnung, da Sie nicht mehr Dereferenzierung eines void *.
BTW: ich bin nicht wirklich sicher, warum Sie tun es auf diese Weise, aber wenn cmncnt_elmsize ist manchmal nicht sizeof(CMNCNT), und kann in der Tat unterscheiden sich von Anruf zu Anruf, würde ich vorschlagen, dass ein Umdenken in diesem design. Ich nehme an, es könnte ein guter Grund dafür, aber es sieht wirklich wackelig auf mich zu. Ich kann fast garantieren, dass es einen besseren Weg, um design Dinge.
Nein ist es nicht. Hast du eigentlich testen?
Visual C++ strahlt "Fehler C2036: 'void *' : unbekannte Größe", wenn Sie versuchen zu tun, Zeiger-Arithmetik mit void-Zeigern. GCC warnt vor dieser, wenn Sie -Wpointer-arith-oder -pedantic.
InformationsquelleAutor T.E.D.