Ответ 1
C++ имеет следующее правило:
Если объект не является битовым полем или подобъектом нулевого размера, адрес этого объекта является адресом первого байта, который он занимает. Два объекта с перекрывающимися временами жизни, которые не являются битовыми полями, могут иметь один и тот же адрес, если один вложен в другой, или если хотя бы один является подобъектом нулевого размера, и они имеют разные типы; в противном случае они имеют разные адреса и занимают непересекающиеся байты памяти.
Теперь проверьте этот код:
#include <stdio.h>
void c();
void b(const char *a) {
static const char *p = 0;
if (!p) {
p = a;
c();
} else {
if (a==p) {
printf("problem!\n");
}
}
}
void c() {
const char a[] = { 0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf };
b(a);
}
int main() {
c();
}
Здесь c
вызывается рекурсивно один раз, поэтому в соответствии с правилом массив a
должен иметь разные адреса на каждом уровне рекурсии. b
сохраняет a
при первом вызове и при втором вызове проверяет, является ли он тем же или нет. С соответствующим компилятором он не должен печатать "проблема!". Но на самом деле, со старым компилятором (GCC 4.1, clang 6.0) он выдает "проблему!", Поэтому эти компиляторы нарушают стандарт.
Компилятор разрешено делать статический только в том случае, если оно может быть доказано, что это изменение не a
наблюдаемо:
В соответствии с правилом "как если бы" реализации разрешается хранить два объекта по одному и тому же машинному адресу или не сохранять объект вообще, если программа не может наблюдать разницу