Я не получаю эту Шутку C/C++

На Win32/64 существует способ сделать это. Попытайтесь считать указатель и поймать получающийся SEH exeception, который будет брошен на отказ. Если это не бросает, то это - допустимый указатель.

проблема с этим методом, хотя то, что это просто возвращается, можно ли считать данные с указателя. Это не делает гарантии о безопасности типов или любом количестве других инвариантов. В целом этот метод еще хорош для мало кроме сказать "да, я могу читать, что конкретное место в памяти за один раз, которая теперь передала".

Короче говоря, не делайте этого ;)

, у Raymond Chen есть сообщение в блоге на этом предмете: http://blogs.msdn.com/oldnewthing/archive/2007/06/25/3507294.aspx

34
задан LittleBobbyTables 28 June 2013 в 14:46
поделиться

6 ответов

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

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

приводит к большому количеству инструкций перемещения для копирования литеральных данных в стек.

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

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

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

24
ответ дан 27 November 2019 в 16:40
поделиться

Эээ, перечитайте статью :)

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

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

2
ответ дан 27 November 2019 в 16:40
поделиться

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

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

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

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

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

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

31
ответ дан 27 November 2019 в 16:40
поделиться

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

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

7
ответ дан 27 November 2019 в 16:40
поделиться

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

Input

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

Output:

; 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
4
ответ дан 27 November 2019 в 16:40
поделиться

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

-1
ответ дан 27 November 2019 в 16:40
поделиться