Forum: PC-Programmierung Spass mit C Code


von Mike M. (mikeii)


Lesenswert?

Mir hat letztens jemand Obfuscated Code gezeigt, und ich wollte es 
selber mal Probieren.
Zum Compilieren muss -ansi gesetzt sein.
1
#include <stdio.h>
2
main(_,__,s)char*s;??<{char j??(2??);{}j??(_+_??)=__;return _??!_? main(0,104,"l"):printf("HANS%c%s%c%s%so",13,j,__-7,s,s);??>}


Wer errät ohne compilieren, was das Programm macht?


Gruß Mike

von Jörg E. (jackfritt)


Lesenswert?

Ohne Nachfrage die gesamten Festplatten des Universums löschen?

;)

Gruß,

Jörg

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

hallo

: Wiederhergestellt durch User
von Mike M. (mikeii)


Lesenswert?

Mist... jetzt isses raus ;)

von Jan (Gast)


Lesenswert?

kann das wer erklären? xD

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was jetzt im einzelnen?

von Mike M. (mikeii)


Lesenswert?

Einfach mal nach Trigraphs googeln, dann Code nochmal ansehen, dann 
sollte es relativ einfach zum lösen sein.

von Lukas K. (carrotindustries)


Lesenswert?

Ich hab' mal den Quelltext ein wenig 'aufbereitet'
- mit gcc -E -trigraphs die Trigraphen aufgelöst
- _ und  durch lesbare bezeichner ersetzt
- Zeilenumbrüche eingefügt
- das return foo|foo durch return foo ersetzt
1
#include <stdio.h>
2
main(foo,bar,s)
3
char*s;{{
4
  char j[2];
5
  j[foo+foo]=bar;
6
  return foo? main(0,104,"l"):printf("HANS%c%s%c%s%so",13,j,bar-7,s,s);
7
  }}
Doch ist die Ausgabe bei jedem Aufruf anders, auch beim unmodifizierten 
Quelltext.
Mein Compiler ist gcc (GCC) 4.6.2 20111125 (prerelease)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Deine Übersetzung ist nicht korrekt.
1
#include <stdio.h>
2
main(_,__,s)char*s;??<{char j??(2??);{}j??(_+_??)=__;return _??!_? main(0,104,"l"):printf("HANS%c%s%c%s%so",13,j,__-7,s,s);??>}

enthält folgende trigraphs:
??< {
??> }
??( [
??) ]

??! |

Deren Ersatz und der Ersatz von '__' und '_' durch foo und bar ergibt
1
#include <stdio.h>
2
main(bar,foo,s)char*s;{{char j[2];{}j[bar+bar]=foo;return bar|bar? main(0,104,"l"):printf("HANS%c%s%c%s%so",13,j,foo-7,s,s);}}

was etwas lesbarer formatiert zu
1
#include <stdio.h>
2
main(bar,foo,s)
3
 char*s;
4
{
5
  {
6
    char j[2];
7
    {}
8
    j[bar+bar] = foo;
9
10
    return bar | bar ? main(0, 104, "l") : printf("HANS%c%s%c%s%so", 13, j, foo - 7, s, s);
11
  }
12
}

wird. Jetzt muss man nur noch überlegen, was 104 ist ...

[Nachtrag:]
Ich habe natürlich foo und bar miteinander vertauscht, warum sollte 
sowas ausgerechnet mir nicht passieren?

von Mike M. (mikeii)


Lesenswert?

Lukas K. schrieb:

> Doch ist die Ausgabe bei jedem Aufruf anders, auch beim unmodifizierten
> Quelltext.
> Mein Compiler ist gcc (GCC) 4.6.2 20111125 (prerelease)

Hab ich auch schon bemerkt gerade, zwischen dem h und allo steht 
irgendein Mist, aber mit gcc (mingw32) 4.4.1 gehts.

Mach einfach aus dem char j??(2??) ein char j??(1??), dann ist der Wert 
nicht uninitialisiert

von Lukas K. (carrotindustries)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Deine Übersetzung ist nicht korrekt.
Der Unterschied will mir nicht recht klar werden...
Das Eliminieren des leeren Blocks {} sollte eigentlich folgenlos 
bleiben.
1
(foo | foo) == foo
oder habe ich da was falsch verstanden?

EDIT:
Wenn man die Deklaration von j global macht, ist j[1] auch wie 
vorgesehen mit 0 befüllt und das Programm funktioniert.
1
#include <stdio.h>
2
char j[2];
3
main(foo,bar,s)
4
char*s;{{
5
  j[foo+foo]=bar;
6
  return foo? main(0,104,"l"):printf("HANS%c%s%c%s%so",13,j,bar-7,s,s);
7
  }}

von Wilhelm,DK4TJ (Gast)


Lesenswert?

Hallo Leute,

in jeder Programmiersprache kann man unleserlichen Code schreiben.

Irgendwer bezeichnete C mal als Gürteltiesprache...
Der Quellcode sieht nämlich so aus, als sei ein Gürteltier über die
Tastatur gerollt.

Ich hoffe, Ihr könnt darüber lachen?

Nix für Ungut.

73
Wilhelm

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Lukas K. schrieb:
> Der Unterschied will mir nicht recht klar werden...

Der Unterschied liegt hier:
1
  return foo? main(0,104,"l"):printf("HANS%c%s%c%s%so",13,j,bar-7,s,s);
1
    return foo | foo ? main(0, 104, "l") : printf("HANS%c%s%c%s%so", 13, j, bar - 7, s, s);

Nochmal zum Vergleich die betreffende Stelle im Original:
1
return _??!_? main(etc) ...

Mit leserlichkeitssteigernden Leerzeichen:
1
return _ ??! _ ? main(etc) ...


Du hast anscheinend die Trigraph-Sequenz ??! als ? interpretiert, und 
nicht als |.

von Sven P. (Gast)


Lesenswert?

Mike Mike schrieb:
> Wer errät ohne compilieren, was das Programm macht?

Also bei mir macht das Segfaults, oder hab ich da was verpasst?

von Lukas K. (carrotindustries)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Du hast anscheinend die Trigraph-Sequenz ??! als ? interpretiert, und
> nicht als |.

Ich hab keine Trigraphs interpretiert, das hat der gcc für mich gemacht 
;)
Das aus dem foo|foo eine foo wurde, war eine von mir vorgenommene 
Vereinfachung.
siehe Beitrag "Re: Spass mit C Code"

Sven P. schrieb:
> Also bei mir macht das Segfaults, oder hab ich da was verpasst?
Mit dem Code aus dem Ursprungspost kann das durchaus passieren, wenn 
printf nach der 0 sucht und keine 'früh genug' im Speicher findet.
Mit der Definition von j außerhalb von main hat man dieses Problem nicht 
mehr.

von mike (Gast)


Lesenswert?

Nein das array auf die grösse 1 setzen. Somit ist es unnötig das array 
global zu setzen, weil damit der unitialisierte wert wegfällt. Das war 
noch auf 2, weil vorher noch zwei zeichen drin sein sollten

von Lukas K. (carrotindustries)


Lesenswert?

Und was passiert dann mit printf, das nach der 0 sucht?

von Rolf M. (rmagnus)


Lesenswert?

mike schrieb:
> Nein das array auf die grösse 1 setzen. Somit ist es unnötig das array
> global zu setzen, weil damit der unitialisierte wert wegfällt. Das war
> noch auf 2, weil vorher noch zwei zeichen drin sein sollten

Du schreibst im äußeren Aufruf von main aber auf jeden Fall hinter das 
Ende des Arrays und hast somit einen Buffer Overflow.

Zehn Aufrufe des Programms geben bei mir übrigens folgende zehn Texte 
aus:

h��allo
h�allo
hߜallo
h�allo
h�zallo
h��allo
hkallo
h_�allo
hOIallo
h��allo

Und wenn man dann noch beim Start Kommandozeilenparameter übergibt, 
wird's bizarr.

von PHP <3 (Gast)


Lesenswert?

Also mit gcc 4.5.2 gehts ohne Probleme. Auch weitere Parameter machen 
dem ganzen nix.

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht sollte man erst C lernen, bevor man mit obfuscated 
weitermacht.
Dann weiß man nämlich auch, was man schreiben muß, damit es nicht nur 
zufällig funktioniert.

Nicht jedes verkorkste Programm ist automatisch interessanter obfuscated 
code.

von Robert L. (lrlr)


Lesenswert?

C Code ist doch generell obfuscated ;-)

von Rolf M. (rmagnus)


Lesenswert?

PHP <3 schrieb:
> Also mit gcc 4.5.2 gehts ohne Probleme. Auch weitere Parameter machen
> dem ganzen nix.

Mit oder ohne eingeschaltete Optimierungen?

von Mike M. (mikeii)


Lesenswert?

Vielleicht sollte man erstmal lernen im Leben nicht alles so Tod ernst 
zu nehmen und jeden runterzustufen ;)

von PHP <3 (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Mit oder ohne eingeschaltete Optimierungen?

Gute Frage. Habs grad nochmal ausprobiert und ich erhalte nur ohne 
Optimierungen oder Optimierungen vom Grad 1 und 2 die richtige Ausgabe. 
Ab 3 wirds zufällig.

von Sam .. (sam1994)


Lesenswert?

Ohne Zahlen:
1
int a,b,j,i;main(){j=++j*++j;i=j+j;b=j=i|i<<--j;a=i+i<<i/i|i^++b;j|=a<<i;printf(&j);j%=++i;b=i<<++j^a|a^b+a/a;a=b^i/++j;b=b<<--i<<i|a<<i|a;printf(&b);}

von Rolf M. (rmagnus)


Lesenswert?

Mike Mike schrieb:
> Vielleicht sollte man erstmal lernen im Leben nicht alles so Tod ernst
> zu nehmen und jeden runterzustufen ;)

So ist das auch nicht gemeint gewesen, aber unleserlichen Code, der nur 
mit Glück funktioniert, kann jeder schreiben. Das ist ja quasi das 
erste, was man lernt ;-). Klaus Wachtler hat's gut formuliert:

> Nicht jedes verkorkste Programm ist automatisch interessanter obfuscated
> code.

Samuel K. schrieb:
> int a,b,j,i;main(){j=++j*++j;i=j+j;b=j=i|i<<--j;a=i+i<<i/i|i^++b;j|=a<<i;pri 
ntf(&j);j%=++i;b=i<<++j^a|a^b+a/a;a=b^i/++j;b=b<<--i<<i|a<<i|a;printf(&b );}

Das Programm wiederum funktioniert bei mir nur mit eingeschalteten 
Optimierungen, was ungewöhnlich ist. Aber ich glaub nicht, daß das auf 
meiner Dockstar auch tut ;-)

von Sam .. (sam1994)


Lesenswert?

Bei mir tut es in DevC++ auch ohne Optimierung. Seltsam, dass es ohne 
bei manchen nicht funktioniert.

Um den "Fehler" zu finden, könnte die Zwischenergebnisse des Codes 
vergleichen.
1
int a,b,j,i;
2
main()
3
{
4
    j=++j*++j;          //j=4
5
    i=j+j;              //i=8
6
    b=j=i|i<<--j;       //b=j=72='H'
7
    a=i+i<<i/i|i^++b;   //a=40^73=97='a'; b=73
8
    j|=a<<i;            //j='H'|'a'<<8
9
    printf(&j);         //"Ha"
10
    j%=++i;             //j=1; i=9
11
    b=i<<++j^a|a^b+a/a; //b=36^97|97^74=111='o'; j=2
12
    a=b^i/++j;          //a=111^3=108='l'; j=3
13
    b=b<<--i<<i|a<<i|a; //'l'|'l'<<8|'o'<<16
14
    printf(&b);         //"llo"
15
}

von Klaus W. (mfgkw)


Lesenswert?

- wieso soll j am Anfang 4 sein?
- wo kommen für die printf die abschließenden Nullen her? Nur weil eine 
int immer mindestens vier Byte hat? Irgendwo in diesem Forum wurden auch 
schon mal andere Größen für int genannt.
- Dank der genauen Vorgaben seit K&R ist bestimmt jeder Rechner little 
endian :-)

von Rolf M. (rmagnus)


Lesenswert?

Samuel K. schrieb:
> Bei mir tut es in DevC++ auch ohne Optimierung. Seltsam, dass es ohne
> bei manchen nicht funktioniert.

Naja, das Programm enthält Code, der undefiniertes Verhalten hervorruft. 
Allerdings tendiert so ein Programm meist eher bei eingeschalteten 
Optimierungen zu Fehlverhalten.

> Um den "Fehler" zu finden, könnte die Zwischenergebnisse des Codes
> vergleichen.int a,b,j,i;
> main()
> {
>     j=++j*++j;          //j=4

Undefiniertes Verhalten. Du veränderst j mehr als einmal ohne 
dazwischenliegenden Sequenzpunkt.
Bei mir ist es an dieser Stelle ohne Optimierungen 2, mit Optimierungen 
4.

Daß du printf ohne vorherige Deklaration nutzt, ihm dann noch den 
falschen Zeigertyp übergibst und Annahmen darüber machst, wie groß ein 
int ist und in welcher Reihenfolge die Bytes da drin liegen, kommt noch 
dazu.

von Sam .. (sam1994)


Lesenswert?

Klaus Wachtler schrieb:
> - wieso soll j am Anfang 4 sein?
Weil für die übernächste Zuweisung eine 3 = --j gebraucht wird.

> - wo kommen für die printf die abschließenden Nullen her? Nur weil eine
> int immer mindestens vier Byte hat? Irgendwo in diesem Forum wurden auch
> schon mal andere Größen für int genannt.
Ich denke nicht, dass jemand den Code für eine <= 16bit Maschine 
kompilieren wird. Man kann es auch durch long ersetzen.

> - Dank der genauen Vorgaben seit K&R ist bestimmt jeder Rechner little
> endian :-)
Es könnte ein Problem mit dem Lesen des &int Pointers geben, das habe 
ich einfacherhalber ignoriert.

Rolf Magnus schrieb:
> Undefiniertes Verhalten.
Ich finde es definiert: Nach der Operatorenpriorität ist ++ höherwertig 
als *. j muss erst 2 mal inkrementiert und erst dann darf multipliziert 
werden. Oder habe ich jetzt einen Denkfehler?

Den Zeiger kann man auch casten, aber das macht nur einen Unterschied 
für den Compiler. Zeiger selbst sind alle gleich, egal auf welches 
Objekt sie zeigen.

von Klaus W. (mfgkw)


Lesenswert?

Samuel K. schrieb:
> Klaus Wachtler schrieb:
>> - wieso soll j am Anfang 4 sein?
> Weil für die übernächste Zuweisung eine 3 = --j gebraucht wird.

Ich wollte nicht darauf hinaus, warum DU die 4 haben willst, sondern 
warum sich die 4 ergeben soll.

Schließlich steht j anfangs auf 0 (weil global, ok - nicht bei AVR).
Es steht dem Compiler durchaus frei, mit dem ersten ++ um 1 zu erhöhen, 
ergibt also 1 für den Term links vom Sternchen, dann och einmal zu 
erhöhen - das gibt 2 für den Term rechts. 1*2 macht 2, das wird 
zugewiesen.

Wenn bei dir 4 herauskommt, ist das nett für dich, aber beileibe nicht 
verlässlich.

Samuel K. schrieb:
>> - Dank der genauen Vorgaben seit K&R ist bestimmt jeder Rechner little
>> endian :-)
> Es könnte ein Problem mit dem Lesen des &int Pointers geben, das habe
> ich einfacherhalber ignoriert.

Auch ignoriert hast du, daß bei eine BE-Maschine die ASCII-Werte dann 
bei höheren Adressen im Speicher stehen und die abschließende 0 unten.
Da wird printf nicht mehr viel retten können.

Daß du dich auf ASCII verlässt, meckere ich gar nicht an, viele Systeme 
gibt es wirklich nicht mehr ohne.

von Klaus W. (mfgkw)


Lesenswert?

Samuel K. schrieb:
> Zeiger selbst sind alle gleich, egal auf welches
> Objekt sie zeigen.

Das ist eine gewagte Aussage.
In dieser Richtung wird es tatsächlich in aller Regel gut gehen (int* 
als char* interpretieren), aber andersrum geht es schnell schief, wenn 
ein char an einer ungeraden Adresse liegt und seine Adresse als int* 
verwendet wird, was je nach System wahrscheinlich auf einer durch 2 oder 
4 teilbaren Adresse liegen muß.

von Klaus W. (mfgkw)


Lesenswert?

Interessant, wie man ein so kleines Programm in der Luft zerreissen kann 
:-)

von Rolf M. (rmagnus)


Lesenswert?

Samuel K. schrieb:
>> - wo kommen für die printf die abschließenden Nullen her? Nur weil eine
>> int immer mindestens vier Byte hat? Irgendwo in diesem Forum wurden auch
>> schon mal andere Größen für int genannt.
> Ich denke nicht, dass jemand den Code für eine <= 16bit Maschine
> kompilieren wird. Man kann es auch durch long ersetzen.

Ich hatte schon überlegt, es mal spaßeshalber für AVR zu compilieren und 
zu schauen, was da rauskommt.

>> - Dank der genauen Vorgaben seit K&R ist bestimmt jeder Rechner little
>> endian :-)
> Es könnte ein Problem mit dem Lesen des &int Pointers geben, das habe
> ich einfacherhalber ignoriert.

Es gibt vor allem ein Problem mit der Reihenfolge der einzelnen Zeichen, 
wenn du das auf einem big-endian-System ausführst.

> Rolf Magnus schrieb:
>> Undefiniertes Verhalten.
> Ich finde es definiert:

ISO C++ sagt ganz klar, daß das Verhalten undefiniert ist, wenn man eine 
Variable zweimal beschreibt oder beschreibt und ausliest, ohne daß 
dazwischen ein Sequenzpunkt liegt, und ++j*++j enthält keinen 
Sequenzpunkt. Da ist es eigentlich egal, was du findest. ;-)

> Nach der Operatorenpriorität ist ++ höherwertig als *. j muss erst 2 mal
> inkrementiert und erst dann darf multipliziert werden.

Das ginge auch von links nach rechts: Für die Multiplikation wird erst 
der linke Operand ermittelt, also wird ++j ausgeführt, also ist der 
linke Operand 1. Dann wird rechts das selbe gemacht, und der Operand ist 
2. Dann kommt die Multiplikation. Ergebnis ist dann 2. Theoretisch 
dürfte der Compiler aber sogar die beiden ++j parallelisieren, sofern 
die Hardware sowas kann. Dann kommt halt irgendwas raus, das bis zu 
einer "Trap" gehen kann, also dem Abbruch der Operation wegen Fehler in 
der CPU. Das wäre alles nach ISO-C erlaubt. Ich kann dir jetzt keine 
konkrete Architektur nennen, auf der das so ist, aber das bedeutet 
nicht, daß es keine gibt.

> Den Zeiger kann man auch casten, aber das macht nur einen Unterschied
> für den Compiler. Zeiger selbst sind alle gleich, egal auf welches
> Objekt sie zeigen.

Allerdings gibt es Compiler, bei denen sich die Art der 
Parameterübergabe zwischen normalen Funktionen und solchen mit variablen 
Argumentlisten unterscheidet. Da printf vorher nicht deklariert war, 
nimmt der Compiler an, daß die Funktion keine variable Argumentliste 
hat.

von Sven P. (Gast)


Lesenswert?

Samuel K. schrieb:
> Zeiger selbst sind alle gleich, egal auf welches
> Objekt sie zeigen.
Das ist in C sogar sehr gewagt.

In C++ ist es sogar schlicht falsch, wenn es um Zeiger auf polymorphe 
Klassen geht.

von Paul B. (paul_baumann)


Lesenswert?

C ist schon eine spaßige Sprache, bei der ein und derselbe Quelltext
auf verschiedenen Rechnern und mit verschiedenen Kompilern immer neue
polymorphe Ergebnisse liefert.

Zitat Mr. Spock
"FASZINIEREND!"

;-)

MfG Paul

von Vlad T. (vlad_tepesch)


Lesenswert?

Klaus Wachtler schrieb:
> Schließlich steht j anfangs auf 0 (weil global, ok - nicht bei AVR).

doch, auch da
Bei dem Rest hast du recht

von Klaus W. (mfgkw)


Lesenswert?

ich dachte, bei AVR mit der gcc-Toolchain würden globale Variablen nicht 
zwangsläufig mit 0 initialisiert? Da lag ich wohl falsch, es scheint 
auch hier alles Globale initialisiert zu werden.
Hm, man wird alt...

von walther (Gast)


Lesenswert?

Paul Baumann schrieb:
> C ist schon eine spaßige Sprache, bei der ein und derselbe Quelltext
> auf verschiedenen Rechnern und mit verschiedenen Kompilern immer neue
> polymorphe Ergebnisse liefert.

Ja, eine spaßige Sprache für lichtscheue Typen, denen vollkommen egal 
ist, ob das Kompilat das macht, was es soll. Aber aufgrund genau des 
beschriebenen Verhaltens disqualifiziert sich C aus dem Bereich 
ernstzunehmender Programmiersprachen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

walther schrieb:
> Aber aufgrund genau des
> beschriebenen Verhaltens disqualifiziert sich C aus dem Bereich
> ernstzunehmender Programmiersprachen.

Das ist quark. Wenn man lauter Programmierfehler aneinanderreiht, ist 
nicht die Sprache disqualifiziert.

von walther (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das ist quark. Wenn man lauter Programmierfehler aneinanderreiht, ist
> nicht die Sprache disqualifiziert.

Es scheint sich aber offensichtlich nicht um "Programmierfehler" zu 
handeln, da die verschiedenen Kompiler den Mist ja übersetzen! Ich kenne 
keine weitere Sprache (von noch blödsinnigeren Experimentalkrams wie 
z.B. "Brainf_ck" einmal abgesehen) wo die Syntax so un-eindeutig und 
fehlerträchtig ist, wie bei C. Sobald die Leute anfangen ihren Quellkode 
zu "optimieren" oder "Tricks zu verwenden" kommt meist nur unwartbarer 
Blödsinn bei heraus, der spätestens dann neu geschrieben werden muß, 
wenn der "Programmierer", welcher das verzapft hat, das Unternehmen 
verlassen hat oder vor versammelter Mannschaft eingestehen muß, das er 
den Sch..ß selbst nicht mehr pflegen kann... Für ernsthafte Projekt z.B. 
im Bereich Sicherheits- oder Medizintechnik ist dieses C-Gebrabbel 
vollkommen ungeeignet. Oder möchtest Du mit einem Herzschrittmacher 
durch die Gegend latschen, der je nach Kompiler nach kurzer Zeit 
aufgrund eines Integer-Überlaufs den Dienst einstellt?

Viel Spaß & frohe Festtage,

Walther

von Sven P. (Gast)


Lesenswert?

walther schrieb:
> Für ernsthafte Projekt z.B.
> im Bereich Sicherheits- oder Medizintechnik ist dieses C-Gebrabbel
> vollkommen ungeeignet. Oder möchtest Du mit einem Herzschrittmacher
> durch die Gegend latschen, der je nach Kompiler nach kurzer Zeit
> aufgrund eines Integer-Überlaufs den Dienst einstellt?

Da hab ich aber schon deutlich mehr Projekte an solch durchdachten 
Sprachen wie etwa Visual Basic, LabVIEW und FoxPro scheitern gesehen.

Du wirst überdies erstaunt sein, womit sicherheitskritische Systeme 
programmiert werden, zum Beispiel im Automotive und in der Industrie. 
Und nein, es ist nicht Basic und auch nicht C#.
1
         \|||/
2
         (o o)
3
 ,~~~ooO~~(_)~~~~~~~~~,
4
 |       Please       |
5
 |   don't feed the   |
6
 |       TROLL!       |
7
 '~~~~~~~~~~~~~~ooO~~~'
8
        |__|__|
9
         || ||
10
        ooO Ooo

von Mark B. (markbrandis)


Lesenswert?

walther schrieb:
> Sobald die Leute anfangen ihren Quellkode
> zu "optimieren" oder "Tricks zu verwenden" kommt meist nur unwartbarer
> Blödsinn bei heraus

Um genau das zu verhindern, gibt es Kodierrichtlinien, Tools zur 
statischen Codeanalyse und Code Reviews. Wenn eine Firma dumm genug ist, 
jeden nach seiner Façon programmieren zu lassen, dann wird das Ergebnis 
auch entsprechend sein - daran ist aber nicht die Programmiersprache 
schuld.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.