34 Stimmen

Ich verstehe diesen C/C++-Witz nicht

Nach der Lektüre dieses Artikel auf thedailywtf.com, bin ich mir nicht sicher, ob ich den Witz wirklich verstanden habe.

Dort steht, dass ein Typ den Code von

int function() 
{ 
  int x;
  char data_string[15];
  ...
  x = 2;
  strcpy(data_string,"data data data");
  ...
}

a

int function() 
{
  int x = 2;
  char data_string[15] = "data data data";
  ...
}

überall im Code und das hat aus irgendeinem Grund die Größe der ausführbaren Datei von 1 auf 2 CDs erhöht (oder vielleicht auch nicht?).

Natürlich kenne ich mich mit C/C++ nicht gut genug aus, um diesen Witz zu verstehen, aber am merkwürdigsten ist, dass das zweite Code-Listing "sauberer" zu sein scheint - zumindest nach dem, was man mir in der Schule beigebracht hat (nämlich, dass das Initialisieren von Variablen eine gute Sache ist, keine schlechte).

31voto

DigitalRoss Punkte 138823

OIC, dies ist ein Problem der Quellcode-Veränderung

Auf den ersten Blick sind die beiden Formen gleichwertig. Die zweite sieht zwar schöner aus, aber sie tun das Gleiche.

Aber dann habe ich die zitierte Seite gelesen.

Das Problem ist, dass der neue Mann den Quellbaum durcheinander gewirbelt hat, und zwar jede Menge. Es ist eine schlechte Angewohnheit, einen riesigen Source-Tree zu durchforsten und eine sinnlose Änderung vorzunehmen. Sicher, vielleicht ist der eine Stil etwas besser als der andere, aber in der Praxis sollte es so sein viel besser bevor man 1.000 Deltas in ein Quellcode-Kontrollsystem einspeist, durch das man sich ewig wühlen muss.

Ich vermute, dass dies eine eine Quellenfreigabe oder eine andere, nicht erwähnte Komplexität hat dazu geführt, dass die Bearbeitung so vieler Dateien deren Verteilung erweitert hat. Die Beiträge auf dieser Website werden ziemlich viel bearbeitet, aber im Grunde ist das Problem auch ohne Einzelheiten verständlich.

Eines der Probleme bei der Bearbeitung von zig Dateien für eine Stiländerung ist, dass die Wahrscheinlichkeit eines unbeabsichtigten Fehlers steigt. Dieses Risiko wird noch vervielfacht, wenn ein junger Entwickler dies tut. Selbst für erfahrene Entwickler gilt das Murphy'sche Gesetz. Wenn es kurz vor einer Veröffentlichung passiert, ist es wirklich ein schweres Vergehen.

24voto

laalto Punkte 143902

Je nach Compiler und Compileroptionen kann die Initialisierung wie folgt aussehen

char data_string[15] = "data data data";

führt zu einer Vielzahl von Move-Anweisungen, um die literalen Daten auf den Stack zu kopieren.

Aufruf von strcpy erfordert weniger Anweisungen.

Wenn man dies bei einer großen Codebasis macht, kann sich die Größe der Binärdatei erheblich erhöhen.

Und natürlich hat er seine Zeit nicht damit verbracht, irgendeinen Mehrwert zu schaffen.

7voto

Clement Herreman Punkte 9956

Der zweite Code ist in der Tat "sauberer", aber bei einem Projekt von der Größe, um die es in diesem Artikel geht, ist es lächerlich zu glauben, dass eine solche Umstrukturierung bestenfalls nutzlos und schlimmstenfalls fehleranfällig ist.

Allerdings bläht diese Art der Umstrukturierung die Größe einer .Exe nicht von 1 auf 2 CDs auf.

4voto

Ich kann das Verhalten nicht ändern. Ich habe es versucht mit LLVM : Ich musste nur ein kleines Stückchen Schrott am Rückgabewert hinzufügen, damit LLVM nichts wegoptimiert, aber der generierte Code für wtf y wtf2 sind völlig identisch. Dieser WTF ist BAAAAAD

Eingabe

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int wtf(int X) {
  int x;
  char data_string[15];
  x = 2;
  strcpy(data_string,"data data data");
  return 5*X+x+ data_string[X];
}
int wtf2(int X) {
  int x = 2;
  char data_string[15]="data data data";
  return 5*X+x+ data_string[X];
}
int main(int argc, char **argv) {
  printf("%d\n", wtf(atoi(argv[1]))+wtf2(atoi(argv[1])));
}

Ausgabe:

; ModuleID = '/tmp/webcompile/_3856_0.bc'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
target triple = "i386-pc-linux-gnu"
@.str = internal constant [15 x i8] c"data data data\00"        ; <[15 x i8]*> [#uses=3]
@.str1 = internal constant [4 x i8] c"%d\0A\00"     ; <[4 x i8]*> [#uses=1]

define i32 @wtf(i32 %X) nounwind readnone {
entry:
    %0 = mul i32 %X, 5      ; <i32> [#uses=1]
    %1 = getelementptr [15 x i8]* @.str, i32 0, i32 %X      ; <i8*> [#uses=1]
    %2 = load i8* %1, align 1       ; <i8> [#uses=1]
    %3 = sext i8 %2 to i32      ; <i32> [#uses=1]
    %4 = add i32 %0, 2      ; <i32> [#uses=1]
    %5 = add i32 %4, %3     ; <i32> [#uses=1]
    ret i32 %5
}

define i32 @wtf2(i32 %X) nounwind readnone {
entry:
    %0 = mul i32 %X, 5      ; <i32> [#uses=1]
    %1 = getelementptr [15 x i8]* @.str, i32 0, i32 %X      ; <i8*> [#uses=1]
    %2 = load i8* %1, align 1       ; <i8> [#uses=1]
    %3 = sext i8 %2 to i32      ; <i32> [#uses=1]
    %4 = add i32 %0, 2      ; <i32> [#uses=1]
    %5 = add i32 %4, %3     ; <i32> [#uses=1]
    ret i32 %5
}

define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
    %0 = getelementptr i8** %argv, i32 1        ; <i8**> [#uses=1]
    %1 = load i8** %0, align 4      ; <i8*> [#uses=1]
    %2 = tail call i32 @atoi(i8* %1) nounwind readonly      ; <i32> [#uses=2]
    %3 = getelementptr [15 x i8]* @.str, i32 0, i32 %2      ; <i8*> [#uses=1]
    %4 = load i8* %3, align 1       ; <i8> [#uses=1]
    %5 = sext i8 %4 to i32      ; <i32> [#uses=1]
    %tmp2 = mul i32 %2, 10      ; <i32> [#uses=1]
    %6 = shl i32 %5, 1      ; <i32> [#uses=1]
    %7 = add i32 %6, 4      ; <i32> [#uses=1]
    %8 = add i32 %7, %tmp2      ; <i32> [#uses=1]
    %9 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr ([4 x i8]* @.str1, i32 0, i32 0), i32 %8) nounwind     ; <i32> [#uses=0]
    ret i32 undef
}

declare i32 @atoi(i8*) nounwind readonly

declare i32 @printf(i8*, ...) nounwind

2voto

Makach Punkte 7140

Ähm, lesen Sie den Artikel noch einmal :)

Der eigentliche WTF war, dass er die gesamte Lösung mit dieser Art von Änderungen berührt hat, obwohl er eigentlich ein Speicherleck beheben sollte.

Auch eine Änderung wie diese würde nicht viel ausmachen, außer dass sie möglicherweise Fehler in anderen, vielleicht komplizierteren Dateien als der Beispieldatei verursacht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X