`*-p` на самом деле законно (хорошо сформировано) в C ++ 03
-
27-10-2019 - |
Вопрос
Мне интересно об этом примере кода:
int main()
{
char *p ;
char arr[100] = "Hello";
if ((p=arr)[0] == 'H') // do stuffs
}
На самом деле этот код хорошо сформирован в C ++ 03?
Мой аргумент в том, что побочный эффект =
завершается только после следующей точки последовательности, и, поскольку мы получаем доступ к результату p=arr
Код может быть плохо сформирован, нет упорядочения между =
а также []
операции.
Я прав?
Поведение хорошо определено в C и в C ++ 11. Этот код на самом деле получен из MySQL.
Решение
Конечно, это четко определен.
Не имеет значения, когда назначение p=arr
происходит. Вы не оцениваете p[0]
, вы подписываете результат (p=arr)
, которое является значением указателя, которое хранится в p
. Анкет Независимо от того, хранится ли он, пока не меняет значение, и значение известно независимо от того, как p
еще был изменен.
Точно так же в *--p
, нет неопределенного поведения. Там было бы неопределенное поведение, только если бы к одной и той же переменной была доступна дважды, включая хотя бы одну запись, между точками последовательности. Но p
доступно только один раз, как часть --p
. Анкет Это больше не читается (*p
), оператор деревьев применяется к результату --p
которое является четко определенным значением указателя.
Теперь это было бы неопределенным поведением:
void* a;
void* p = &a;
reinterpret_cast<void**>(p = &p)[0] = 0;
как это было бы
int *pi = new int[5];
int i = **&++pi;
Должно быть ясно, что результат предварительного устранения не является чтением безподобным записи, потому что утверждать, что есть раса, чтобы утверждать, что ++p
Никогда не может использоваться в качестве RValue, и в этом случае оно должно быть отделено между точками последовательности, и вместо этого может использоваться после инкента. Не было бы никаких преимуществ в том, чтобы как предварительный, так и после достижения на языке.