Выстрелить себе в ногу в С
Jul. 25th, 2018 10:15 amhttps://habr.com/company/pvs-studio/blog/418023/
И в статье (переводной) задаются вопросом, почему этот код странно работает? Ответ простой - потому что он мудацкий. То есть обычно оно все даже прокатит и заработает, потому что в архитектуре x86 a и b лягут последовательно в стек, причем, поскольку компилятор читает слева направо, именно в нужном порядке.
Но, е-мое, a и b могут лежать вообще где и как угодно, и никто не гарантирует, как именно.
Хотите устраивать подобную указательную магию, используйте
Вот отсюда, блин, и идет дурная слава Си - от товарищей, которые устраивают пляски с указателями по принципу "прокатило". Умные люди вообще советуют не использовать указательную арифметику, несмотря на элегантность всяких
Что до печальки на тему того, что компилятор вольно трактует сравнение неизвестных ему
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 лет назад в этом уже большого смысла не было.