Няшная / Говнокод #25781 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
#include <stdio.h>

#define my_type unsigned short

int main(void) 
{
    my_type a = 0;

    printf("%d\n", a);

    return 0;
}

Экое извращение

Запостил: Ksyrx Ksyrx, (Updated )

Комментарии (43) RSS

  • сегодня на уроке информатики прошли дефайн
    Ответить
    • А завтра они пройдут typedef, и у нас появится ещё один говнокод.
      Ответить
        • В общем, так: хороший программист обязан знать Си. Хороший программист может знать C++, но это не обязательно уже. Главное, чтоб C и C++ не были единственными доступными программисту инструментами - иначе это адски паршивый программист.
          Ответить
          • В общем, так: хороший программист обязан знать "PHP". Хороший программист может знать "JS", но это не обязательно уже. Главное, чтоб "PHP" и "JS" не были единственными доступными программисту инструментами - иначе это адски паршивый программист.
            Ответить
            • В общем, так: хороший программист обязан знать "Ассемблер". Хороший программист может знать "машинные коды", но это не обязательно уже. Главное, чтоб "Ассемблер" и "машинные коды" не были единственными доступными программисту инструментами - иначе это адски паршивый программист.
              Ответить
              • В общем, так: хороший программист обязан знать "Машинные коды". Хороший программист может знать "Verilog", но это не обязательно уже.
                Ответить
            • В общем, так: хороший программист обязан незнать "PHP". Хороший программист может незнать "JS", но это не обязательно уже. Главное, чтоб "PHP" и "JS" не были единственными доступными программисту инструментами - иначе это адски паршивый программист.
              Ответить
              • В общем, так: хороший программист обязан не знать "AWK". Хороший программист может не знать "Perl", но это не обязательно уже. Главное, чтоб "AWK" и "Perl" не были единственными доступными программисту инструментами - иначе это адски паршивый программист.
                Ответить
    • Прикола нет, и автокаста никакого нет. Если ты о 9-й строчке, то там ushort всегда при передаче в любую функцию займёт минимум одну ячейку в стеке или один регистр, что равно размеру инта, ну или лонга. (кстати, почему на 64-битах инт остался 32-битным?)

      Именно поэтому я за "Си".
      Ответить
      • >минимум одну ячейку в стеке или один регистр, что равно размеру инта
        Это какое-то очень смелое утверждение.
        С спецификации сшечки нет ячеек стека, да и размер регистра не оговорен. Самый маленький кирпичик это char.

        Хотя для большинства имплементаций ты прав.
        > (кстати, почему на 64-битах инт остался 32-битным?
        Смотря на каких. на x32-64 -- да. Может, потму что гамадриллы завязались на его размер, хотя уже очент давно есть uint8_t всякие
        Ответить
        • >> С спецификации сшечки нет ячеек стека

          Именно поэтому я за «Си».

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

              А чот такое автоматическая переменная я не совсем понял, ты про сишный auto? Назуй он вообще нужен и как это отменяте существовование стека*+?
              Ответить
              • >А чот такое автоматическая переменная я не совсем понял
                почитай стандарт. *
                Это переменная, которая автоматически удаляется при выходе из блока.

                >ты про сишный auto?
                вообще нет


                * кроме статьи в вики, есть даже видос
                https://www.youtube.com/watch?v=63AM19ZYCYU
                Ответить
                • Значит я правильно понел, что я тебя не понел.

                  > Это переменная, которая автоматически удаляется при выходе из блока.
                  Ок, как такое делать без стека?

                  Видосы и индусы не нужны.
                  Ответить
                  • > индусы не нужны.
                    Ты случайно не из PHP конференции в Дрездене?

                    >Ок, как такое делать без стека?
                    Ну например явно удаляя что-то при выходе из блока:)

                    Стек тут это деталь реализации. Что не отменяет того факта, что примерно все реализации си используют именно стек
                    Ответить
      • На x86 минимальный размер данных, который можно запушить в стек, равен 16 битам (двум байтам), причём даже в 64-битном режиме.

        Сколько пушит сишка, зависит от коллконвеншона.
        Ответить
        • а как пушнуть туда слово в x64?
          типа push ax?
          Ответить
          • Да, именно так. В x64 дофига префиксов размера, так что многие инструкции можно сделать 32-битными или 16-битными. Вот инструкции для 8-битных данных идут отдельно.
            Ответить
        • А как я тогда узнаю, сколько байт из стека доставать? или va_arg должен эту ситуацию разрулить? Просто мне вспоминается, что с va_arg(va, char) какие-то проблемы возникают, что он один байт вместо двух вытаскивает...
          Ответить
          • Какой багор )))

            Прочитал я про вариадические функции в сишке. Какое же говно...

            В общем, если у функции в заголовке есть многоточие, то для всех неперечисленных аргументов вызывающий код производит повышение:
            1. Все целые питухи, которые меньше инта, кастуются к инту.
            2. Все плавающие питухи, которые меньше дабла (а их аж одна штука, а именно float), кастуются к даблу.

            Т. е. при вызове макроса va_arg нельзя указывать типы char, short, float, int8_t и тому подобные. Можно указывать только типы, которые по размеру не меньше, чем int и double, а также указатели.

            Какой размер имеет этот самый int, зависит от конкретного компилятора. Можно попасть в ситуацию, когда для какой-нибудь платформы есть несколько компиляторов и слинковать вместе сгенерированный ими код не получится.
            Ответить
            • Что-то хуйня какая-то. Структуры нельзя передавать что-ли?
              Ответить
              • Надо копать.

                Точно нельзя на x86 передавать структуру размером один байт, потому что вызывающий код запушит как минимум два байта, а тупой макрос va_arg прибавит к указателю единицу. Чтобы принять такую структуру, придётся дополнительно объявлять фиктивный тип размером в два байта.

                Да вообще для всех структур нечётного размера придётся вводить фиктивный тип, округлённый до ближайшего чётного.
                Ответить
                • либо это может сделать за тебя копулятор
                  Ответить
                  • Проверял, по умолчанию sizeof(struct{int8_t field;}) == 1. Дебильный макрос va_arg увеличит адрес на единицу и в качестве следующего параметра прочитает мусор.

                    Если размер структуры нечётный, нужно явно объявить вспомогательный тип данных. Вручную мусорное поле можно и не добавлять, а прописать прагму для выравнивания (хотя нужно проверить).
                    Ответить
                    • Хотя в «MINGW» вот что нашёл:
                      #if defined(_M_IX86)
                      
                      #define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
                      #define _crt_va_start(v,l)	((v) = (va_list)_ADDRESSOF(l) + _INTSIZEOF(l))
                      #define _crt_va_arg(v,l)	(*(l *)(((v) += _INTSIZEOF(l)) - _INTSIZEOF(l)))
                      #define _crt_va_end(v)		((v) = (va_list)0)
                      #define _crt_va_copy(d,s)	((d) = (s))
                      
                      #elif defined(_M_AMD64)
                      
                      #define _PTRSIZEOF(n) ((sizeof(n) + sizeof(void*) - 1) & ~(sizeof(void*) - 1))
                      #define _ISSTRUCT(t)  ((sizeof(t) > sizeof(void*)) || (sizeof(t) & (sizeof(t) - 1)) != 0)
                      #define _crt_va_start(v,l)	((v) = (va_list)_ADDRESSOF(l) + _PTRSIZEOF(l))
                      #define _crt_va_arg(v,t)	_ISSTRUCT(t) ?						\
                      				 (**(t**)(((v) += sizeof(void*)) - sizeof(void*))) :	\
                      				 ( *(t *)(((v) += sizeof(void*)) - sizeof(void*)))
                      #define _crt_va_end(v)		((v) = (va_list)0)
                      #define _crt_va_copy(d,s)	((d) = (s))
                      
                      #elif defined(_M_IA64)
                      
                      #error VARARGS not implemented for IA64
                      
                      #else
                      
                      #error VARARGS not implemented for this TARGET
                      
                      #endif /* cpu ifdefs */


                      Для X86 он округлит sizeof до размера, кратного инту; для AMD64 он округлит до размера, кратного void*; на остальных платформах пошлёт напитон.
                      Ответить
              • Чем старше стандарт - тем хуже язык. Закопайте уже его и переходите на делфи.
                Ответить
                • Кстати, в Delphi есть array of const — это массив не сырых данных, а данных с метаданными, а также open arrays и динамические массивы, когда при вызове функций рядом с данными пушится их размер. В сишке то же самое придётся делать вручную (поэтому у функций с вариативными параметрами обычно явно первым параметром передают размер или строку формата, как у printf).
                  Ответить
                • Проблем дельфи в том, что он никому не нужен
                  ну кроме того одного гомика из Осетии
                  Ответить
              • Проверил на x86-32 (gcc на x86-64 игнорирует cdecl и хочет ms_abi или sysv_abi):
                #include <stdio.h>
                #include <stdint.h>
                typedef struct __attribute__ ((__packed__)) {uint8_t field;} TPituh;
                
                void __attribute__ ((cdecl)) Dump(TPituh pituh1, TPituh pituh2) {
                    printf("pituh1       = %08x\n", pituh1); // ffffff55
                    printf("pituh2       = %08x\n", pituh2); // ffffffaa
                    printf("pituh1.field = %08x\n", pituh1.field); // 00000055
                    printf("pituh2.field = %08x\n", pituh2.field); // 000000aa
                    printf("raw data 1   = %08x\n", *(uint32_t *)&pituh1); // 00404155
                    printf("raw data 2   = %08x\n", *(uint32_t *)&pituh2); // 000000aa
                    printf("__builtin_frame_address(0)+8    = %08x\n", *(uint32_t *)(__builtin_frame_address(0)+8)); // 00404155
                    printf("__builtin_frame_address(0)+12   = %08x\n", *(uint32_t *)(__builtin_frame_address(0)+12)); // 000000aa
                    printf("__builtin_frame_address(1)-10   = %08x\n", *(uint32_t *)(__builtin_frame_address(1)-10)); // 000655aa -- это код из main, в main они лежат плотно
                }
                
                int main(){
                    TPituh pituh1 = {.field=0x55};
                    TPituh pituh2 = {.field=0xAA};
                    printf("sizeof(pituh1) = %d\n", sizeof(pituh1)); // sizeof(pituh1) = 1
                    Dump(pituh1, pituh2);
                    return 0;
                }


                В общем, gcc на x86-32 структуры хранит плотно, но когда пушит, дополняет случайным мусором до четырёх байтов.
                Ответить

Добавить комментарий

Семь раз отмерь — один отрежь, guest!

    А не использовать ли нам bbcode?


    8