1. Си / Говнокод #20103

    −50

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    #include <stdio.h>
    #include <stdint.h>
    
    int main(void)
    {
    	size_t foo = -5;
    	uint8_t foo1 = -5;
    	
    	printf("%d %d", foo, foo1);
    	
    	return 0;
    }

    А почему лыжи не едут? size_t же ведь беззнаковый.
    З.Ы. и да мне стыдно

    Запостил: MiD, 31 Мая 2016

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

    • size_t беззнаковый, а вот %d - знаковый.
      Ответить
      • Да, но uint8_t тоже беззнаковый, однако же - 5
        Ответить
        • l
          Ответить
        • Оппечатался, с uint8_t =251
          Ответить
        • У тебя на пеке первые sizeof(int) байт foo выглядят, как int со значением -5 (для интелов это вроде должно быть так). А foo1 просто кастится в инт при передаче в printf. Тебе понятно, почему у foo1 значение 251?
          Ответить
          • С foo1 вопросов нету 256-5
            Но все равно не совсем догнал size_t он в stdint. h разве не как max unsigned представлен?
            Ответить
            • Хуй знает как он представлен. А какая разница? Главное, что в нем байт >= чем в инт.
              Ответить
            • printf'у похуй, как твой size_t там определён, ему важно, что ты в строке формата передашь.
              И да, size_t нужен для хранения индексов, то-бишь его размер на x86 будет 32 бита, а на x64 - 64, емнип.
              Ответить
              • с хранением индексов и размером size_t всё ясно. Вопрос то в другом, почему uint8_t через тот же формат %d распознается как unsigned, а size_t пишет -5, как signed
                Ответить
                • Потому что расширяется до 4 байт дополнением нулями, и старший бит 0
                  Ответить
                • Integer promotion.
                  Ответить
                  • Вдогонку к Integer promotion, вот тебе:

                    ~ » ./llvm/bin/clang test.c -O3 -o test
                    test.c:9:25: warning: format specifies type 'unsigned int' but the argument has type 'size_t' (aka 'unsigned long') [-Wformat]
                        printf("%08X %08X", foo, foo1);
                                ~~~~        ^~~
                                %08zX
                    1 warning generated.
                    ~ » ./test
                    FFFFFFFB 000000FB


                    Также в гцц
                    Ответить
                • printf() использует "..." для передачи аргументов. для передачи аргументов по "..." предусмотрены implicit конверсии типов.

                  float кастится в double. целочисленые типы кастятся в int/long.

                  теперь. foo = 0xfffffffffffffffbU, foo1 = 0xfbU. foo при касте может только максимум обрезатся. foo1 - будет добито нулями и станет 0x000000000000000fb.

                  то что здесь не происходит и о чём знать стоит, это sign extension. если бы foo1 был знаковым, то вместо добивания нулями (беззнаковое расширение), происходило бы знаковое расширение: "растягивание" (extension) самого верхнего (== знакового) бита в новые байты.
                  Ответить
                  • теперь понял, всем спасибо
                    Ответить
                  • > целочисленые типы кастятся в int/long.

                    [unsigned/signed] short/char promoted to int. Остальное (long/long long) передаётся как есть. Есть даже спецификатор для long long в printf.
                    Ответить
                • Нухуя там не распознаётся. Просто байты так легли. Почему - догадайся.
                  Ответить
          • size_t is an unsigned integer type used to represent the size of any object (including arrays) in the particular implementation. The sizeof operator yields a value of the type size_t. The maximum size of size_t is provided via SIZE_MAX, a macro constant which is defined in the <stdint.h> header.

            так что по идее должно быть sizeof(unsigned)
            Ответить
            • > по идее должно быть sizeof(unsigned)
              Не должно быть. Размер unsigned - ID.

              > Вопрос то в другом, почему uint8_t через тот же формат %d распознается как unsigned, а size_t пишет -5, как signed
              Ничего там не "распознается". Срочно гугли представление отрицательных чисел в памяти.
              Ответить

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