2016-12-09 6 views
0
int add(int a, int b) 
{ 
    return (int)&(((char *)a)[b]); 
} 

unterzeichnen Warum soll ich a zu einem char * und nicht int * werfen?Addition ohne Verwendung eines +

Ich versuche diesen Code vollständig zu verstehen, aber ich kann nicht, also, wenn es Ihnen leicht ist, bitte, geben Sie eine einfache englische Erklärung.

+0

Dieser Code wird nicht auf GCC und Clang kompiliert. – NathanOliver

+0

Woher hast du diesen Code? – user463035818

+7

Das Beste an diesem Code, dass Sie tun können - werfen Sie es in den Müll und nie wieder erwähnen. – Starl1ght

Antwort

0

Warum soll ich ein zu einem char * und nicht zu einem * umwandeln?

für die Leser, die Frage zu klären, sind Sie nicht soll dies verwenden, um Code wie überhaupt. Aber nehmen wir an, dass Sie in der ioccc konkurrieren (gibt es eine C++ Variante dieser Konkurrenz?), In diesem Fall kann genau das sein, was Sie tun sollen.

Also, um die Frage zu beantworten, ist es, weil Zeigerarithmetik durch die Größe des spitzen Gegenstandes skaliert wird. Wenn Sie int* verwenden, wird b durch sizeof(int) skaliert. Da Sie keinen der beiden Operanden einer Addition skalieren wollen, skalieren Sie mit 1 (die multiplikative Identität), die auftritt, wenn der spitze Typ die Größe 1 hat - was per Definition char hat.

P.S. Das Programm ist schlecht ausgebildet und kann möglicherweise nicht mit standardkompatiblen Compilern kompilieren.

+1

Es gibt kein ioC++ cc. Es würde keine Herausforderung beim Schreiben von unlesbarem C++ geben. –

+0

Danke für die Erklärung. Ich habe diese Frage nicht von meinem Hauptantrag gestellt, weil ich wusste, dass die Reaktion sein würde. Aber du hast recht, das ist für einen Wettbewerb. –

+0

@Tracy Ich denke, dass die Aussage, dass die Absicht ist, verschleierten Code zu schreiben, und dass dies nicht für den produktiven Einsatz geeignet ist, die Reaktion möglicherweise gemildert hat. Nicht alle Leser dieser Seite werden implizit verstehen. Einige von ihnen (und Menschen, die nicht wollen, dass solche Leute verwirrt werden) mögen wünschen, dass dies in Vergessenheit geraten würde. – user2079303

6

Die Idee ist, dass ein Array einfach eine Addition eines Zeigers mit einem Index ist. Wenn a ein char [] (oder char *) und b eine Ganzzahl ist, dann ist a[b] der Wert unter der Adresse a+b. Dieser Code gibt a als Zeiger aus, indiziert es mit b und findet die Adresse, die gleich a+b sein sollte.

Aber in der realen Welt, niemals jemals dies tun.

+0

... und der Code verwendet ein verstecktes '+', nämlich dass 'a [b]' '' (a + b) 'bedeutet. –

+1

Also? Die ursprüngliche Frage war "ohne Verwendung eines + -Zeichens". Der Code verwendet kein + Zeichen. –

+0

@GraemePerrow warum wird es hinzugefügt? Ich meine, ein [b], Beispiel, 100 [103] == 100 + 103. –

0

Um es kompilieren zu lassen, müssen Sie es in gültiges C++ umwandeln. Zeiger sind unvereinbar mit ganzen Zahlen, aber der Abstand zwischen zwei Zeigern ist ein Integer-Typ:

#include <iterator> 

int add(int a, int b) 
{ 
    auto p = (char *)0; 
    auto p2 = &(&p[a])[b]; 

    return static_cast<int>(std::distance(p, p2)); 
} 

Haftungsausschluss: Ich habe nicht dieses Produkt oder eine Dienstleistung unterstützen.

+0

FYI der Code in der ursprünglichen Frage kompiliert (wie C) und arbeitet mit Visual Studio 2013. –

+0

In der Berechnung von 'p2' haben Sie den Ausdruck' p [a] '. Das ist undefiniertes Verhalten, weil 'p' ein Nullzeiger ist. –

+0

@MartinBonner der Ausdruck ist '& p [a]' - Nach dem C-Stil-Cast, p ist kein Null-Zeiger, es ist einfach ein Zeiger auf char. Ob ich die Adresse von p [a] nehme, ist UB oder nicht. Ich fürchte, ich kenne den Standard nicht tief genug, um einen Kommentar abzugeben. –

0

Lassen Sie uns mit ein, wie 100 und b als 103

  1. (char *)a ein Beispiel nehmen -> diese Typumwandlungen ein als Zeiger. Also wird ein Zeiger als Zeiger betrachtet.
  2. ((char *)a)[b] -> das ist 100 [103], dh den Wert an der Stelle gibt (100 + 103)
  3. &(((char *)a)[b] -> dies die Adresse des obigen Wert gibt, das heißt es gibt 203
  4. (int)&(((char *)a)[b] -> Die endgültige Typumwandlung in int konvertiert die oben angegebene Adresse in einen ganzzahligen Wert, wie vom Rückgabewert der Funktion gefordert.

Dies wird nur mit char* Typumwandlung in Schritt 2 arbeitet Wenn Sie dort eine int* Typumwandlung verwenden, die Summe, die Sie in Schritt 3 erhalten 100 + 4*103 sein werden, das heißt512

+2

"das ist 100 [103]" sollte "das ist undefiniertes Verhalten" sein. – Lundin

+0

'a' ist ein Zeichenzeiger in diesem Stadium. So ist 'a [b]' gut definiert. –

+0

Rishikesh, bitte ein bisschen genauer sein. In Punkt 2 wird der Wert nie genommen (würde segfault); In Punkt 4 gibt es keinen "char-Wert", nur eine Adresse. –