Если бы вы превращали этот код C непосредственно в простой машинный код на простой машине, то char *p2 = p1 - 3;
установит p2
для указания на три байта в памяти раньше, чем p1
, а *p2 = '\0'
будет записывать нольв неподходящее место.Мы не знаем, что находится в этом месте, поэтому мы не можем сказать, каков эффект.
Однако современные компиляторы обычно не превращают код C непосредственно в простой машинный код.Они интерпретируют код C и выполняют сложные оптимизации на нем.Поэтому для понимания того, что происходит, необходимо использовать стандарт C или документацию для используемого компилятора.
Что стандарт C говорит нам об этом коде?Для p1 - 3
применяются правила добавления с указателем в C 2018 6.5.6 8:
Когда выражение с целочисленным типом добавляется или вычитается из указателя,… Если обаоперанд указателя и результат указывают на элементы одного и того же объекта массива или одного элемента после последнего элемента объекта массива, оценка не должна вызывать переполнение;в противном случае поведение не определено.
Поскольку p1
указывает на элемент объекта (который может использоваться в качестве массива), предоставленный malloc
, а p1 - 3
не указывает наэлемент этого массива, поведение не определяется стандартом C.Поэтому, если мы используем стандарт C в качестве основы для понимания, после оценки p1 - 3
мы не можем сказать, каково поведение программы или состояние p1
и p2
.