Обобщенные алгоритмы
Встроенные в C++ типы низкого уровня, такие как указатели и массивы, имеют соответствующие операции, поэтому мы можем записать: char vc1[200]; char vc2[500];
void f() { copy(&vc1[0],&vc1[200],&vc2[0]); }
Ну, если к делу подойти формально, то записать мы так не можем. Вот что говорит об этом д-р Страуструп:
The issue is whether taking the address of one-past-the-last element of an array is conforming C and C++. I could make the example clearly conforming by a simple rewrite: copy(vc1,vc1+200,vc2);
However, I don't want to introduce addition to pointers at this point of the book. It is a surprise to most experienced C and C++ programmers that &vc1[200] isn't completely equivalent to vc1+200. In fact, it was a surprise to the C committee also and I expect it to be fixed in the upcoming revision of the standard. (also resolved for C9x - bs 10/13/98).
Суть вопроса в том, разрешено ли в C и C++ взятие адреса элемента, следующего за последним элементом массива. Я мог сделать пример очевидно корректным простой заменой: copy(vc1,vc1+200,vc2);
Однако, я не хотел вводить сложение с указателем в этой части книги. Даже для самых опытных программистов на C и C++ большим сюрпризом является тот факт, что &vc1[200] не полностью эквивалентно vc1+200. Фактически, это оказалось неожиданностью и для C комитета, и я ожидаю, что это недоразумение будет устранено в следующих редакциях стандарта.
Так в чем же нарушается эквивалентность? По стандарту C++ мы имеем следующие эквивалентные преобразования: &vc1[200] -> &(*((vc1)+(200))) -> &*(vc1+200)
Действительно ли равенство &*(vc1+200) == vc1+200 неверно?
It is false in C89 and C++, but not in K&R C or C9x. The C89 standard simply said that &*(vc1+200) means dereference vc1+200 (which is an error) and then take the address of the result, and the C++ standard copiled the C89 wording. K&R C and C9x say that &* cancels out so that &*(vc1+200) == vc2+200.
Это неверно в С89 и C++, но не в K&R C или С9х. Стандарт С89 говорит, что &*(vc1+200) означает разыменование vc1+200 (что является ошибкой) и затем взятие адреса результата. И стандарт C++ просто взял эту формулировку из С89. Однако K&R C и С9х устанавливают, что &* взаимно уничтожаются, т.е. &*(vc1+200) == vc1+200.
Спешу вас успокоить, что на практике в выражении &*(vc1+200) некорректное разыменование *(vc1+200) практически никогда не произойдет, т.к. результатом всего выражения является адрес и ни один серьезный компилятор не станет выбирать значение по некоторому адресу (операция разыменования) чтобы потом получить тот же самый адрес с помощью операции &.