elglin: (Default)
[personal profile] elglin
https://habr.com/company/pvs-studio/blog/418023/

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;
}


И в статье (переводной) задаются вопросом, почему этот код странно работает? Ответ простой - потому что он мудацкий. То есть обычно оно все даже прокатит и заработает, потому что в архитектуре x86 a и b лягут последовательно в стек, причем, поскольку компилятор читает слева направо, именно в нужном порядке.
Но, е-мое, a и b могут лежать вообще где и как угодно, и никто не гарантирует, как именно.
Хотите устраивать подобную указательную магию, используйте int a[2], а вот тогда стандарт гарантирует, что &(a[1]) == a + 1, потому что a[n] можно считать синтаксическим сахаром для *(a + n).

Вот отсюда, блин, и идет дурная слава Си - от товарищей, которые устраивают пляски с указателями по принципу "прокатило". Умные люди вообще советуют не использовать указательную арифметику, несмотря на элегантность всяких *p++ = *q++.

Что до печальки на тему того, что компилятор вольно трактует сравнение неизвестных ему extern int* start и extern int* end - так кошерно передавать не начало и конец буфера, а начало и длину. Разница между for(p = start; p < end; p++) и end = start + n; for(p = start; p < end; p++) в одно слово и один-два такта (ADD или ADD + TFR/XCHG) - я могу представить себе случаи, когда это критично, но даже 20 лет назад в этом уже большого смысла не было.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org

Page generated Jan. 23rd, 2026 07:10 am
Powered by Dreamwidth Studios