Ответ 1
Нет, это не так, но это происходит только потому, что память была выделена и записана в использование типа символа.
Память выделяется с помощью malloc. Этот объект не объявил тип 1 потому что он был назначен с помощью malloc. Таким образом, у объекта нет эффективного типа.
Затем код обращается и изменяет объект, используя тип char
. Поскольку тип 2char
и объект с эффективным типом не скопирован 5 копирование не устанавливает эффективный тип char
для этого и последующего доступа, но устанавливает эффективный тип char
, только на время доступа 3. После доступа объект больше не имеет эффективного типа.
Затем тип int
используется для доступа и только чтения этого объекта. Поскольку объект не имеет эффективного типа, он становится 3int
, на время чтения. После доступа объект больше не имеет эффективного типа. Поскольку int
был явно совместим с эффективным типом int
, поведение определяется.
(Предполагая, что считанные значения не являются ловушками для int
.)
Если вы получили доступ и изменили объект, используя несимвольный тип, который также несовместим с int
, поведение будет undefined.
Скажем, ваш пример был (предполагая sizeof(float)==sizeof(int)
):
int i;
void *buf = calloc(5, sizeof(float)); // buf initialized to 0
{
float *ptr1 = buf;
for(i = 0; i < 5*sizeof(float); ++i)
ptr1[i] = (float)i;
}
int *ptr2 = buf;
for(i = 0; i < 5; ++i)
printf("%d", ptr2[i]);
Эффективный тип объекта, когда float
записывается в, становится типа float
, на время записи и всех последующих обращений к объекту, который его не модифицирует 2. Когда эти объекты затем обращаются к int
, эффективный тип остается float
, так как значения только считаются не модифицированными. Предыдущая запись с использованием float
постоянно устанавливает эффективный тип float
, пока следующая запись в этот объект (что в этом случае не произошло). Типы int
и float
не совместимы 4 поэтому поведение undefined.
(Весь текст приведен ниже: ISO: IEC 9899: 201x)
1 (6.5 Выражения 6)
Эффективным типом объекта для доступа к его сохраненному значению является объявленный тип объекта, если таковой имеется. 87) Выделенные объекты не имеют объявленного типа.
2 (6.5 Выражения 6)
Если значение хранится в объекте, не имеющем объявленного типа, через lvalue, имеющем тип, который не является типом символа, тогда тип lvalue становится эффективным типом объекта для этого доступа и для последующих обращений, которые не изменяют сохраненное значение.
3 (6.5 Выражения 6)
Для всех других доступов к объекту, не имеющему объявленного типа, эффективным типом объекта является просто тип lvalue, используемый для доступа.
4 (6.5 Выражения 8)
Объект должен иметь сохраненное значение, доступ к которому имеет только выражение lvalue, которое имеет один из
следующие типы: 88)
- тип, совместимый с эффективным типом объекта,
- квалифицированная версия типа, совместимая с эффективным типом объекта,
- тип, который является подписанным или неподписанным типом, соответствующим эффективному типу
объект,
- тип, который является подписанным или неподписанным типом, соответствующим квалифицированной версии
эффективный тип объекта,
- совокупный или объединенный тип, который включает один из вышеупомянутых типов среди его
членов (включая рекурсивно, члена подгруппы или объединенного союза) или
- тип символа.
5 (6.5 Выражения 6)
Если значение копируется в объект, не имеющий объявленного типа с использованием memcpy или memmove, или копируется как массив типа символа, тогда эффективный тип измененного объекта для этого доступа и для последующих обращений, которые не изменяют значение, является эффективный тип объекта, из которого копируется значение, если оно есть.