Подтвердить что ты не робот

Я не получаю эту C/С++ Joke

После прочтения этого article на thedailywtf.com, я не уверен, что у меня действительно была шутка.

Там говорится, что какой-то парень изменил код из

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

к

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

всюду в коде и что по какой-то причине раздул размер исполняемого файла от 1 до 2 компакт-дисков (или, может быть, он этого не сделал?).

Очевидно, что я недостаточно хорошо знаком с C/С++, чтобы получить эту шутку, но что кажется странным, так это то, что 2-й список кодов кажется "чище", по крайней мере, из того, что мне сказали в школе (то есть инициализация переменных - хорошая вещь, а не плохая).

4b9b3361

Ответ 1

В зависимости от параметров компилятора и компилятора, инициализация вроде этого

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

приводит к множеству команд перемещения для копирования данных в стек.

Вызов strcpy требует меньше инструкций.

Выполнение такого рода вещей на большой базе кода может значительно увеличить размер двоичного файла.

И, конечно же, он не тратил время на добавление какой-либо ценности.

Ответ 2

OIC, это проблема с исходным кодом-отбойником

На первый взгляд две формы эквивалентны. Второй выглядит лучше, но они делают то же самое.

Но затем я прочитал процитированную страницу.

Проблема в том, что новый парень взбесил исходное дерево, много его. Это плохая форма, чтобы пробраться через гигантское дерево источников и сделать бессмысленное изменение. Конечно, возможно, один стиль немного лучше другого, но на практике это должно быть намного лучше, прежде чем положить 1000 дельт в систему управления исходным кодом для людей, пробирающихся на вечность, оправдано.

Я подозреваю, что это был исходный релиз, или какая-то другая неопределенная сложность вызвала редактирование этого большого количества файлов, чтобы расширить их распространение. Вклад в этот сайт редактируется довольно немного, но в основном проблема понятна без особых особенностей.

Одна из проблем с редактированием файлов zillion для изменения стиля заключается в том, что вероятность непреднамеренной ошибки увеличивается. Этот шанс сильно умножается, когда это делает младший разработчик. Даже для опытных, есть закон Мерфи, чтобы рассмотреть. Если это происходит прямо перед выпуском, это действительно является висящим нарушением.

Ответ 3

2-й код действительно "чище", но с проектом размера, о котором идет речь, смешно думать, что рефакторинг в лучшем случае бесполезен, в худшем случае подвержен ошибкам.

Однако такой рефакторинг не раздувает форму размера .Exe от 1 до 2 компакт-дисков

Ответ 4

Я не могу получить от этого другое поведение. Я попробовал его с помощью LLVM: мне пришлось добавить немного крутизны по возвращаемому значению, чтобы LLVM ничего не оптимизировал но сгенерированный код для wtf и wtf2 полностью идентичен. Этот wtf является BAAAAAD

Ввод

#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])));
}

Вывод:

; 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

Ответ 5

Um, прочитайте статью:)

Настоящая WTF заключалась в том, что он коснулся всего решения такими изменениями, когда он должен был исправить утечку памяти.

Кроме того, такое изменение не имеет большого значения, кроме потенциально ломающего/вводящего ошибки в другие, возможно, более сложные файлы, чем пример.

Ответ 6

Да, второй код чище, но в зависимости от компилятора он может привести к выпуску большего количества машинного кода. Это полностью зависит от компилятора, но точка статьи WTF заключается в том, что во втором случае компилятор будет выделять копию значения string/integer для каждого фрагмента кода, подобного этому, и в первом случае он будет делать это только один раз для каждой программы.