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

    −2

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    9. 9
    #include <stdio.h>
    
    int main(void) {
        int a, b;
        int *p = &a;
        int *q = &b + 1;
        printf("%p %p %d\n", (void *)p, (void *)q, p == q);
        return 0;
    }

    https://habr.com/company/pvs-studio/blog/418023/

    0x7fff4a35b19c 0x7fff4a35b19c 0

    кто понимает почему?

    Запостил: guestinxo, 25 Июля 2018

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

    • показать все, что скрытоvanished
      Ответить
    • Што.

      https://wandbox.org/permlink/MF1L8CRAkYsZbuZg
      https://wandbox.org/permlink/WYDI2qedK3TRvGSj <--
      https://wandbox.org/permlink/NiuxKgk23SR2f37N
      https://wandbox.org/permlink/AFcT9cU6Rn8W9bMC
      Ответить
    • А то шо неинициализированная переменная - это ок?
      Ответить
    • Переведи на "PHP".
      Ответить
    • НЕБАГ в гцц: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502

      ~ » clang --version
      clang version 3.8.1-24 (tags/RELEASE_381/final)
      ~ » clang -O1 --std=c11 poo.c -o poo
      ~ » ./poo 
      0x7ffeb45595b4 0x7ffeb45595b4 1
      
      ~ » gcc --version
      gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
      ~ » gcc -O1 --std=c11 poo.c -o poo
      ~ » ./poo                         
      0x7ffd7be73f6c 0x7ffd7be73f6c 0
      Ответить
    • Начал читать и сразу же не понял: во-первых схуя вообще &b + 1 должно быть равно == &a, во-вторых представление поинтера через %p это одно, а физическое значение это другое. Забыли что-ли три сорта поинтеров в борланд си под реальный режим с сегментацией?

      %p -- writes an implementation defined character sequence defining a pointer. Там можно написать "pituz" и это будет по стандарту.

      Стандарт вообще ничего не говорит про то какие там числа.
      Он лишь говорит что у поинтеров бывает арифметрика внутри массивов. Все.
      Ответить
      • показать все, что скрытоvanished
        Ответить
      • показать все, что скрытоvanished
        Ответить
        • Я не парле ву франсэ, мон шэр

          Порядок -- личное дело компилятора, не надо закладываться на то, что не написано в штандарте
          Ответить
          • показать все, что скрытоvanished
            Ответить
            • Вроде недавно обсуждали это, да:) Копелятор может вырванивать поля структур (если их явно не пакнуть) потому что удобнее иметь массив структур по 32 байта каждая, чем по 31 байт, правда?

              Кстати, x86 умеет невыровненный доступ, но с пенальти (делая за программиста всю грязную работу). некоторые CPU не умеют и дают exception.

              Некоторые умеют менять поведение в зависимости от регистра (кажется чуть-ли не в x86 когда-то такое или было или хотели сделать).

              Тяжелое наследие 8088 в котором шЫрина всех шЫн была 1 байт, и можно было ничо не выравнивать

              Но вот уже 286 читал 0,1 куда лучше чем 1,2 бо в ему приходилось делать ДВА чтения и половину выкидывать.

              Тут бы и дать пизды программистам, включить exception, но intel пожалел обратную совместимость
              Ответить
          • показать все, что скрытоvanished
            Ответить
            • >>Это ж не куча, а стек, тут все предсказуемо.
              А мне кажется что в стандарте Си нету понятия "стек". Там есть "автоматические переменные"
              Ответить
              • показать все, что скрытоvanished
                Ответить
                • Гарвардская же отличается только тем, что у нее отдельные шины для данных и кода, верно?
                  Ну и адресация разная видимо. Вот как у PC есть две дорожки (IO и MEM) так и у них есть MEM-DATA и MEM-CODE.

                  Или я что-то пута?
                  Локальные переменные вроде должны лежать в области данных, не?
                  Ответить
                  • показать все, что скрытоvanished
                    Ответить
                    • ну раздельная память, сиречь раздельная адресация, сиречь шины к ней тоже разные, не?

                      ну в любом случае если писнуть 123 в IP и в DX то там будут адреса разных ячеек
                      Ответить
                      • показать все, что скрытоvanished
                        Ответить
                      • > раздельная память
                        > раздельная адресация
                        > разные шины
                        Это 3 ортогональных хуйни, не надо их смешивать.

                        Вот у того же stm32f4 от ядра уходят 3 шины (I, D, S) и авторы его относят к гарвардской архитектуре. Но все эти шины заведены в один bus matrix и ядро вполне может читать инструкции через I-bus из того же самого блока оперативки, в которую пишет данные через S-bus (но с разными будет быстрее т.к. нет конфликтов). При этом адреса у всех железок (блоков оперативки, флешки, периферии) на всех шинах одинаковы, хотя и не все шины bus matrix роутит ко всем железкам (через I-bus, к примеру, не видно USB контроллер и один из блоков оперативки).
                        Ответить
                        • Мы говорили про нормальную гарвардку.
                          Вот тебе картинка
                          https://en.wikipedia.org/wiki/Harvard_architecture#/media/File:Harvard_architecture.svg

                          ... with physically separate storage and signal pathways for instructions and data

                          То-есть у нас и устройства и шина разные.

                          А теперь скажи, как программист может явно НЕ указать какие данные ему нужны: код или дата? Как CPU поймет на какую шыну выставлять адрес?

                          А если программист явно указывает, то у нас и адресация разная.


                          >> Но все эти шины заведены в один bus matrix
                          деталь реализации. В классическом PC тоже одна шина была и на память и на io и на адрес.

                          >>на всех шинах одинаковы,
                          нахуй тогда три шины?
                          Ответить
                          • > одна шина
                            bus matrix - не шина. Это кроссбар. Через него все мастера могут работать параллельно, лишь бы с разными слейвами.

                            > нахуй тогда три шины?
                            Пирфоманс же. Если ты работаешь в "гарвардском" режиме (юзаешь разные блоки оперативки для кода и данных) -- всё работает быстро. А конфликты возникают только во время перезаливки кода в блок с кодом. Ну и даже если ты работаешь в "фон-неймановском" режиме (с одним блоком на код и данные), то хотя бы обращения к периферии не мешают фетчить новые инструкции. Когда у тебя нет ебических кешей как у интела -- вполне актуально.

                            Короче это почти труъ гарвардская архитектура с возможностью поюзать её как фон-неймановскую если пирфоманс не поджимает.
                            Ответить
                          • > а если программист явно указывает
                            Вот интересно, а как на труъ гарварде читать или писать память кода на сишке? Скорее всего никак, только через асм отдельной инструкцией... Ну либо проц по какому-нибудь биту в адресе данных должен выбирать шину (что не особо приятно для пайплайна).
                            Ответить
                            • >> а как на труъ гарварде читать или писать память кода на сишке?
                              Ну и как пишут и читают в IO на PC? outb какой-нить может быть. Под капотом там конечно отдельная инструкция:)

                              >>проц по какому-нибудь биту в адресе
                              Тоже так подумал, в конце концов контроллер памяти же по биту может выбрать канал например, но мне не нравится мысль делить линейное прострванство на две части по биту.

                              Звучит как ад для программиста
                              Ответить
                              • > звучит как ад для программиста
                                Скорее как ад для разраба проца. От каждой записи/чтения через шину кода в любом случае конвейер пидорасит... Хоть с инструкцией хоть с битом в адресе.
                                Ответить
                                • Это понятно: ты далеко не всегда можешь спекулятивно исполнить инструкцию чтения чего-то из памяти, и особенно из I/O :)

                                  Но ты представь себе программиста у которого foo это адрес памяти, а (например) "foo & 0xF7" это адрес в I/O)
                                  Ответить
                                  • Эээ... но ведь у всех процов с mmio (даже у того же интела) часть адресов уходит в периферию. И подобные извраты над указателями могут сделать что-нибудь забавное. Причём по твоему биту хотя бы можно было понять куда уйдёт запрос, а в реальных системах ты это хуй узнаешь...
                                    Ответить
                                    • заванишил хуйню, которую написал
                                      извините

                                      ты прав: даже если у меня верхний гигабайт замаплен на видеокарту и внизу немного биоса и VGA то все равно есть такой бит в моем 64 битном указателе, повернув который я получу адрес устройства

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

                      З.Ы. А ещё у avr вроде все регистры через память видно, так что можно и адрес регистра положить если ненадолго :)
                      Ответить

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