2016-03-29 13 views
3

Vielleicht habe ich die Leute mit meinem Beispiel verwechselt. Ich habe versucht, einen Teil des Codes zu verstehen und vereinfacht. Hier ist ein Teil des ursprünglichen Codes (nochmal vereinfacht ... :)) (siehe Original Post unten).Warum den Zeiger werfen?

uint16_t hal_nrf_read_multibyte_reg(uint8_t *pbuf) 
{ 
    uint8_t memtype; 

    memtype = *(uint8_t*)(&pbuf); 

    if (memtype == 0x00U) 
    { 
     uint8_t data *buf = (uint8_t data *)pbuf; 
     DOTHIS 
    } 

    if (memtype == 0x01U) 
    { 
     uint8_t xdata *buf = (uint8_t data *)pbuf; 
     DOTHAT 
    } 

    if (memtype == 0xFEU) 
    { 
     uint8_t pdata *buf = (uint8_t data *)pbuf; 
     DOSOMETHING 
    } 

    return SOMETHING; 
} 

void main() 
{ 
    uint8_t payload[3]; 

    hal_nrf_read_multibyte_reg(payload); 

    while(1) { } 
} 

Also habe ich mich gefragt, warum werfen sie pbuf, die bereits von uint8_t ist. Aber ich denke, ich habe jetzt meine Antwort.

------------ ALTE POST -------------

Ich erforsche Nordic Semiconductors nRF24LE1.

Wenn ich den folgenden Testcode habe.

void tempF(int *test) 
{ 
    int varA; 
    int varB; 
    int varC; 

    varA = *(int*)(&test); // The way it is done in the source code 
    varB = *(&test); 
    varC = test; 

    printf("A: %x\n", varA); 
    printf("B: %x\n", varB); 
    printf("C: %x\n", varC); 
    printf("C1: %x\n", test); 

    if (test == 0x00) 
     printf("equals 0x00"); 
} 

int main(void) { 
    int myArray[3]; 

    tempF(myArray); 
    return 0; 
} 

Die printfs geben alle die gleiche Antwort. Was ist der Grund dafür, es "varA-style" zu machen? Beispiele wo es notwendig ist?

Wenn ich den Weg in varA ich nicht bekommen, die Warnung „C260 Warnung:‚=‘: Zeiger Abschneiden

+1

Sind Sie sicher, Typ von 'var?' Ist nicht 'int *'? –

+2

Keiner Ihrer 3 Fälle ergibt einen Sinn. Wenn Sie die Adresse drucken möchten, ist es besser und sicherer, dies einfach mit dem% p-Spezifizierer zu tun, ohne dass dazwischen Konvertierungen vorgenommen werden müssen. – Lundin

+0

Verwenden Sie kein int, um einen Zeiger zu speichern, wenn Sie einen Zeiger als Ganzzahl speichern möchten, us (u) intptr_t – 12431234123412341234123

Antwort

1

Das Problem ist, dass jeder Zeigertyp nicht von derselben Größe wie ein int zu sein braucht.. der Compiler truies warnen Sie über diese Tatsache.

(int *)(&test) Mit wirft die Adresse des Tests einen Zeiger auf seinen in int. Dereferenzierung dies ein int ergibt, die gerne zu einer int variablen zugewiesen werden kann. Es kann sei immer noch echt Wenn Pointer mehr Bits benötigen, als ein int halten kann, haben Sie den Compiler davon überzeugt, dass Sie wissen, was Sie tun, und das geschieht absichtlich.

1

Da Ihr Beispiel Zugriffe auf Variablen tatsächlich int sind:

int varA; 
int varB; 
int varC; 

Ohne die GCC Compiler-Versionen 4.4.7 oder neuer zu verwenden und mit stdio.h wie in den Kommentaren erwähnt, wird der Code nicht kompilieren, die zweite zwei Ihrer Aussagen wird wegen illegaler Typen ‚int‘ Fehler aus und

varA = *(int*)(&test); // The way it is done in the source code 
varB = *(&test);//error 
varC = test; //error 

Wenn sie int *

waren ‚Zeiger auf int‘
int *varA; 
int *varB; 
int *varC; 

Dann die erste Aussage: varA = *(int*)(&test); würde Fehler aus.

Die einzige Möglichkeit, die Zuweisungsanweisungen kompiliert ist mit den Variablen wie folgt deklariert:

int varA; 
int *varB; 
int *varC; 

varA = *(int*)(&test); // The way it is done in the source code 
varB = *(&test); 
varC = test; 
+1

Ich habe ein Gefühl 'varA' und andere sind tatsächlich' int * 'in OP tatsächlichen Code. – Groo

+1

@Groo, ich bin geneigt, nicht zu denken. Der Punkt scheint zu sein, den Zeigerwert in ein "int" umzuwandeln. Sie werden diesen Ansatz für Conversions in einer Vielzahl von C-Codes sehen. In diesen Fällen soll derselbe Effekt wie bei C++ 'reininterpret_cast 'auftreten, der sich von dem Effekt eines C-Cast unterscheidet. –

+0

@JohnBollinger: Du hast recht, ich wollte meinen Kommentar löschen, nachdem ich den Code nochmal angeschaut habe, aber jetzt kann ich es auch hier lassen, wenn andere die gleiche Idee bekommen. – Groo

6

Ihre drei Proben sind alle im Grunde einen Zeiger in eine int umwandelt. Technisch erfordert dies eine Besetzung in Ihren Fällen B und C, und Ihr Compiler sollte Sie davor warnen. Zum Beispiel:

int varC = (int) test; 

Mit der Besetzung, das ist völlig gültig, aber ohne, nicht. Trotzdem erzeugt Ihr Compiler wahrscheinlich den gleichen Code mit oder ohne.In Ihrem Beispielcode ist jedoch der Typ des Ausdrucks &testint **. Das Übergeben eines Ausdrucks dieses Typs an int * und das Dereferenzieren des Ergebnisses, wie es getan wird, um einen Wert varA zuzuweisen, soll die Bytes test wie die eines int wie mit einem C++ reinterpret_cast uminterpretieren. Dies ergibt nicht unbedingt den gleichen Wert wie das Konvertieren von test direkt in einen int, wie dies auch geschieht, um varC einen Wert zuzuweisen. Sie sind besonders anfällig für Unterschiede, wenn die Größe eines Zeigers nicht mit der Größe eines int auf dem Zielsystem übereinstimmt, aber sie müssen nicht das gleiche Ergebnis liefern, selbst wenn die Größen gleich sind.

Auf der anderen Seite, die * Bediener direkt auf das Ergebnis der & Bediener Anwendung hat keinen Nettoeffekt, so dass der für varB berechneten Wert wird das gleiche wie die für varC berechnet zuverlässig sein.

+0

@ryyker kompiliert für mich mit Warnungen (und mit einschließlich 'stdio.h') mit gcc 4.5.1, aber es kompiliert und läuft –

+1

@rykker, wie ich auch auf Ihre Antwort antwortete, kompiliert der Code für mich in GCC 4.4. 7 mit 'gcc -std = c99', vorausgesetzt dass ich' #include 'vorstelle. Der Compiler warnt vor den impliziten Zeigerkonvertierungen in den Zuweisungen zu 'varB' und' varC', auf die ich auch in meiner Antwort hingewiesen habe. Der Ausdruck, der "varA" zugewiesen wurde, was der Hauptpunkt ist, sieht für mich gut aus, und der GCC hat keine Beschwerden damit, selbst wenn alle Warnungen aktiviert sind. Was denkst du ist falsch damit? –

+0

@JohnBollinger - Ja, danke, ich habe deinen Kommentar unten gesehen. _Was denkst du ist falsch damit? _. Selbst wenn 'stdio.h' hinzugefügt und C99-Erweiterungen aktiviert sind, kompiliert mein Compiler den ursprünglichen OP-Code nicht. Ist es dann möglich, dass der GCC-Compiler Erweiterungen verwendet, die noch nicht in den Standard übernommen wurden? – ryyker

0

varA = *(int*)(&test); Mittel interpretieren die bitweise Darstellung test als int, dann lagern in var.

Die gegossene zeigt (int *), dass die bitweise Darstellung test sollte als int interpretiert werden, während der Bediener * es als int interpretiert.

Dies ist identisch mit memcpy(&varA, &test, sizeof varA);, wenn sizeof (int) == sizeof (int *).

Verwandte Themen