Здравствуйте, DirtyGarry, Вы писали:
DG>Т.е. параметр с одновременно является и константой и не константой. Могут ли в этой ситуации возникнуть какие-нибудь "грабли"?
Здравствуйте, Alexander G, Вы писали:
AG>Ну так это в данном случае корректный alias
согласен, на эти грабли тут не наступим
имелся в виду aliasing в широком смысле : http://en.wikipedia.org/wiki/Aliasing_(computing)
хотел обратить внимание на такой вариант: у функции f могут быть неявные предположения как соотносятся входные указатели. то есть могут ли они указывать на одну память или обязаны не иметь пересекающихся участков
const/non const здесь неважен
я сталкивался с такой ситуацией
есть функция double f(double& a, double& b)
если ее вызвать, как
double a = 0;
double b = 0;
double x = f(a, b); <-- здесь корректное x
а при вызове
double a = 0;
double x = f(a, a); <-- здесь некорректное x
связано это было, по видимому, с тем, что входящие аргументы использовались для манипуляций (то есть использовались, как рабочие переменные) внутри функции
пример:
double Return1And2(double& a, double& b)
{
a = 1.0;
b = 2.0;
return a;
}
эта функция возвращает 1, если входные параметры лежат в разных областях памяти. иначе возвращает 2.0
Здравствуйте, DirtyGarry, Вы писали:
DG>Т.е. параметр с одновременно является и константой и не константой. Могут ли в этой ситуации возникнуть какие-нибудь "грабли"?
void func(unsigned int *c, const unsigned int *a)
{
printf("%d\n",a[0]); // 8888
c[0] = 9999;
printf("%d\n",a[0]); // why 9999 ? a is const unsigned int* , how a[0] was changed ?
}
int _tmain(int argc, _TCHAR* argv[])
{
unsigned c[] = {8888};
func(c,c);
return 0;
}
With best regards
Pavel Dvorkin
Re: [plain c] Параметр функции как const и не const при вызове.
Здравствуйте, DirtyGarry, Вы писали:
DG>Т.е. параметр с одновременно является и константой и не константой. Могут ли в этой ситуации возникнуть какие-нибудь "грабли"?
void* memcpy( void* dest, const void* src, std::size_t count );
// If the objects overlap, the behavior is undefined.
После оптимизации glibc одно UB#1 заменилось другим UB#2. Но некоторый код закладывался на то что у memcpy UB#1, хотя этого делать не должен был, и был совершенно не готов работать с UB#2.
Re[2]: [plain c] Параметр функции как const и не const при вызове.
Здравствуйте, DirtyGarry, Вы писали:
EP>> Но опять таки — помимо кода нужно смотреть контракт. DG>Не могли бы Вы пояснить, что именно Вы понимаете под "контрактом"? Как и в каких условиях функция func вызывается?
Контракт функции включает:
1. Условия, называемые предусловиями, которые должны быть выполнены перед вызовом функции (включая ограничения накладываемые на аргументы, а возможно и на глобальное состояние). Если эти условия не выполнены, то наступает undefined behaviour — может произойти что угодно.
Например одно из предусловий двоичного поиска звучит как "входной массив должен быть отсортирован".
2. Постусловия — задают то, в какое состояние функция обещает перевести систему/данные/etc в том случае, если предусловия были выполнены. Например двоичный поиск, при входных данных удовлетворяющих предусловию, обязуется найти соответствующий элемент.
Если же брать вышеописанный пример сложения векторов — то даже если текущая реализация корректно работает для func(c, c, b), но в контракте записано что все три диапазона не должны пересекаться — то автор функции имеет право, согласно контракту, поменять код функции таким образом, что func(c, c, b) уже работать не будет.
Аналогичная ситуация произошла с memcpy — её реализацию поменяли, не изменяя при этом контракт — но как оказалось были такие программы, которые закладывались на детали реализации memcpy не относящиеся к контракту, что привело к undefined behaviour.
Re[4]: [plain c] Параметр функции как const и не const при в