Denkaufgabe: Funktion zum quadrieren einer Zahl ohne return-Wert und Übergabeparameter..



  • woist denn eine externe variable? Alles lokal 🙂
    P.S.: MFK lag schon goldrichtig 😛



  • Sportler schrieb:

    ich dachte keine externe variable?

    Welche externe Variable? a ist lokal.



  • Dann dürfte das Ergebnis aber nicht portabel sein, und eine Lösung die nicht überall das gleiche tut ist keine Lösung 😉

    P.S.: Als Ansatz würde ich mir in quad eine lokale Variable definieren und über deren Adresse im Stack rückwärts zu der Adresse von a in main() wandern...



  • So etwas ähnliches gibt es in "Maple", dort kann man Operationen auf Ergebisse aus der vorhergehenden Zeile beziehen ohne Sie nochmals explizit anzugeben.

    Aber wie bekommt man in C++ den Wert der letzten Operation?



  • Auf den ersten Blick ist die Fragestellung nicht eindeutig. Denn auf irgendeinem Weg muss man die Information, über die zu quadrierende Zahl, der Methode zur Verfügung stellen.
    Selbst wenn man in inline-Assembler mit dem Stack spielt, könnte dass laut Aufgabenstellung eine "externe Variable" sein. "Externe Variable" müsste unser anonymer Fragesteller also noch genauer spezifizieren.



  • DarthZiu schrieb:

    Auf den ersten Blick ist die Fragestellung nicht eindeutig... Selbst wenn man in inline-Assembler mit dem Stack spielt

    Das wäre eine schwache Lösung, da das ja allgemein nicht möglich wäre
    (wenn zwischen a=5 und quad() noch beliebig am Stack rumgehamplelt wird).

    Jockel



  • Na gut, hier ist sie:
    (Unter: g++ (GCC) 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)

    #include <stdio.h>
    #include <stdlib.h>
    
    void q()
    {
      static int *v = 0;
      if (v == 0)
        v = new int;
      *v *= *v;
    }
    
    int main(int argc, char** argv)
    {
      if (argc != 2)
      {
        printf("Usage: %s value\n", argv[0]);
        return 42;
      }
    
      int *a = new int, *b = new int, *d = (b + (b - a));
      /*
        wenn hier ein anderer compiler meckert, einfach q() vor der
        Zuweisung ein mal aufrufen, damit es "sauberer" ist =)
       */
      *d = atoi(argv[1]);
      q();
    
      printf("quad: %d\n", *d);
    
      return 0;
    }
    


  • Hallo,

    da fällt mir nur #define oder template ein.



  • #define QUAD(x) 
    
    void quad()
    {
    	int a;
    	__asm mov a, ebx
    	cout << a << endl;
    	a = a*a;
    	cout << a << endl;
    	__asm 
    	{
    	pop edi 
    	pop esi
    	pop ebx
    	mov ebx, a
    	push ebx
    	push esi
    	push edi
    	}
    }
    
    int main()
    {
    	int x = 5;
    	QUAD( x );
    
    }
    


  • narf schrieb:

    Na gut, hier ist sie:

    Du Held. Dass es eine "Lösung" sein soll, die vom Standard nicht abgedecktes Verhalten auf einer bestimmten Plattform ausnutzt, solltest du vorher dazuschreiben 🙄



  • narf schrieb:

    Na gut, hier ist sie:
    (Unter: g++ (GCC) 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)

    Boah ist die undefiniert und unportabel 😃

    Geht übrigens noch einfacher:

    // ...
       int *a = new int + 4;
      /*
        wenn hier ein anderer compiler meckert, einfach q() vor der
        Zuweisung ein mal aufrufen, damit es "sauberer" ist =)
       */
      *a = atoi(argv[1]);
      q();
       // ...
    

    🤡



  • Copy'n'Paste Fehler

    #define QUAD(x) __asm{ mov ebx, x } quad(); __asm{ mov x, ebx }
    //Rest wie oben
    


  • logisch ist die lösung nicht richtig oder? eher ein fehler in der programmierung??



  • Für alle die es nicht verstehen 😉

    Es wird die Tatsache ausgenutzt dass der Heap-Manager dem Programm beim new int in der Funktion quad genau den Speicherbereich gibt, der unmittelbar hinter dem int welches in main allokiert wurde liegt. Da der Heap vom Betriebssystem größere Blöcke anfordert und die häppchenweise an das Programm gibt ist dieser Bereich also vor der Allokierung schon gültig und kann mit der Basis gefüllt werden. Danach wird er in quad allokiert, aber nicht initialisiert.



  • IchKannsNichtVerstehen schrieb:

    logisch ist die lösung nicht richtig oder? eher ein fehler in der programmierung??

    Doch 🙂 Der "Trick" besteht nur darin, dass wenn du 2 int-Variablen deklarierst, dass die die Adresse des zweiten int's (oder jeden nachfolgenden int's) aus der Adresse vom ersten int + sizeof(int) berechnen kannst.

    P.S.: Was heisst hier eigentlich nicht portabel? Solange der Heap nicht randomized wird, sollte es eigentlich auf jeder Plattform laufen, bsw. mit nur einen kleinen Änderung der Berechnung der Adresse.



  • narf schrieb:

    P.S.: Was heisst hier eigentlich nicht portabel? Solange der Heap nicht randomized wird, sollte es eigentlich auf jeder Plattform laufen, bsw. mit nur einen kleinen Änderung der Berechnung der Adresse.

    Unsinn. Nirgendwo ist festgelegt, dass der Heap für neue ints Adressen mit immer gleichem Abstand ausspucken muss. Dein Ansatz basiert auf Annahmen über die Implementierung von new.

    Und spätestens wenn der Heapmanager für den dritten int einen neuen Block anfängt, scheitert dein Ansatz. Kommt halt drauf an, was vorher schon auf dem Heap passiert ist. Ich muss hier mit MSVC7.1 nur

    new int[168];
    

    am Anfang der main-Funktion angeben, damit das Programm abstürzt.



  • MFK schrieb:

    ..damit das Programm abstürzt.

    Naja, nicht wie man es coredump'en läst, sondern die Lösung war gefragt, aber grundsätzlich hast du schon recht.
    Hatte davor über eine Aufgabe mit Funktion ohne Übergabeparamter gestolpert und hatte mir mal nachts vor dem Schlafen was "grausammeres" ausgedacht und am morgen danach ging es sogar 😃



  • Igitt - das Ding sieht ja grauenhaft aus. Und wenn das auf deinem System tatsächlich funktioniert, hast du wahrscheinlich Glück gehabt.

    (btw, selbst wenn diese Funktion das macht, was sie soll - die arbeitet nur mit der Variable *d deines Hauptprogramms (bzw der Variablen, die unmittelbar VOR dem allerersten Aufruf reserviert wurde). Was machst du wenn du anderswo das Quadrat einer Zahl benötigst?)

    PS: Und außerdem verstößt du damit gegen die Anforderungen - du arbeitest auf einer externen Variable (aus Sicht der Funktion), ob diese nun global ist oder auf dem Heap liegt, ist da zweitrangig.



  • Sag ich docheine externe Variable 🙄


Anmelden zum Antworten