2012-01-13 1 views
12

Я интересно об этом образце кусок кода:ли `* - p` фактически правовые (хорошо сформированы) в C++ 03

int main() 
{ 
    char *p ; 
    char arr[100] = "Hello"; 
    if ((p=arr)[0] == 'H') // do stuffs 
} 

этот код на самом деле хорошо сформированы в C++ 03 ?

Моего аргумента, что побочный эффект = завершаются только после следующей точки последовательности, и поскольку мы доступ результата p=arr код не может быть хорошо сформирован, нет упорядоченности между = и [] операциями.

Правильно ли я?

Поведение хорошо определено в C и на C++ 11. Этот код фактически получен из MySQL.

+19

Код в заголовке не указан в приведенном вами образце кода. – porges

+3

Является ли '((a = b) + x)' корректным? Если он корректно определен, то также будет корректно определен '(p = arr) [0]', поскольку он эквивалентен '* ((p = arr) + 0)' – Nawaz

+1

@Prasoon: согласно вашему аргумент, 'int x = ++ i + n' вызывает UB? Потому что, по вашему мнению, причина должна быть: побочный эффект '++' завершается только после следующей точки последовательности, и поскольку мы получаем результат «++ i», код может быть не совсем корректным. Это? – Nawaz

ответ

24

Конечно, это четко определено.

Не имеет значения, когда имеет место задание 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, и в этом случае он должен стоять отдельно между точками последовательности, а пост-приращение можно использовать inste объявление. Не было бы никакого преимущества иметь как предварительный приращение, так и пост-прирост в языке.

+2

Для любых будущих читателей см. этот мета-пост: http://meta.stackexchange.com/questions/118996/where-did -all-the-comments-go-on-is-p-really-legalwell-generated-in-c03 – Mysticial

+1

Кроме того, расшифровку удаленных комментариев можно найти здесь: http://i.stack.imgur.com/ f4rIE.png –

Смежные вопросы