IT

이런 C/C++ 농담은 이해가 안 돼요.

itgroup 2023. 9. 20. 20:15
반응형

이런 C/C++ 농담은 이해가 안 돼요.

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/C++에 익숙하지 않아서 이런 농담을 들을 수 있지만, 이상하게 보이는 것은 두 번째 코드 목록이 적어도 학교에서 들은 바로는 "깨끗한" 것처럼 보인다는 것입니다. (변수를 초기화하는 것이 나쁜 것이 아니라 좋은 것이라는 것입니다.)

OIC, 이것은 소스-코드-턴 문제입니다.

언뜻 보기에는 두 양식이 동등합니다.두 번째 것은 더 멋져 보이지만 그들은 같은 일을 합니다.

하지만 인용된 페이지를 읽었습니다.

문제는 신입이 소스 나무를 마구 휘저었다는 것입니다.거대한 소스 트리를 트롤링해서 무의미한 변화를 만드는 것은 나쁜 형태입니다.물론, 한 가지 스타일이 다른 스타일보다 약간 낫겠지만, 실제로는 사람들이 영원토록 헤쳐 나갈 수 있도록 1,000 델타를 소스 코드 제어 시스템에 넣는 것이 정당화되기 전에 훨씬나을 것입니다.

소스 릴리스였거나, 언급되지 않은 다른 복잡성으로 인해 많은 파일이 편집되어 배포가 확장된 것은 아닌지 의심됩니다.그 사이트에 기고한 글들은 꽤 많이 편집되어 있지만, 기본적으로 그 문제는 구체적인 내용 없이 이해할 수 있습니다.

스타일 변경을 위해 수많은 파일을 편집할 때 발생하는 문제점 중 하나는 의도치 않은 오류가 발생할 가능성이 높아진다는 것입니다.이 기회는 후배 개발자가 할 때 크게 증가합니다.경험자들에게도 머피의 법칙이 있습니다.그것이 출시 직전에 일어난다면 그것은 정말로 교수형 위반입니다.

컴파일러와 컴파일러 옵션에 따라서 이렇게 초기화를 합니다.

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

결과적으로 리터럴 데이터를 스택에 복사하는 이동 명령이 많이 발생합니다.

부르기strcpy명령이 덜 필요합니다.

대규모 코드베이스 전체에서 이와 같은 작업을 수행하면 이진 크기가 크게 증가할 수 있습니다.

그리고 물론, 그는 가치를 더하는 데 시간을 쓰지 않았습니다.

두 번째 코드는 정말로 "cleaner"이지만, 기사가 대략적인 크기의 프로젝트로, 그렇게 리팩터링하는 것이 기껏해야 쓸모가 없고, 최악의 오류가 발생하기 쉽다고 생각하는 것은 말도 안 됩니다.

그러나 이러한 종류의 리팩토링은 a를 부풀리지 않습니다.exe 사이즈 양식 1~2 cds

여기서 다른 행동을 할 수가 없어요.LLVM으로 시도해 봤습니다. 반환 값에서 약간의 크라우프트만 추가하면 LLVM이 어떤 것도 최적화하지 않지만 생성된 코드는 다음과 같습니다.wtf그리고.wtf2완전히 똑같습니다.는 BAAAAD wtf는 BAAAD다입니다.

인풋

#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

음, 기사 읽어보세요 :)

진짜 WTF는 그가 메모리 누수를 고치려고 할 때 이런 종류의 변화로 전체 솔루션을 건드린 것입니다.

또한 이와 같이 변경하는 것은 예제 파일보다 더 복잡한 다른 파일에서 버그를 수정/도입하는 것 외에는 큰 문제가 되지 않습니다.

네, 두 번째 코드가 더 깨끗하지만 컴파일러에 따라 더 많은 머신 코드가 나올 수 있습니다.이것은 전적으로 컴파일러에 의존적이지만, WTF 기사의 요점은 두 번째 경우에 컴파일러가 각 코드 조각에 대해 문자열/정수 값의 복사본을 할당하고 첫 번째 경우에는 프로그램당 한 번만 할당한다는 것입니다.

언급URL : https://stackoverflow.com/questions/1420009/i-dont-get-this-c-c-joke

반응형