Всех приветствую есть сигнатура такого вида Код (Text): CHAR * StringReplace(String *Obj, const CHAR * __restrict fToken, const CHAR * __restrict rToken); вопрос вот в чем fToken может перекрыватся с rToken но ни один из них не должен перекрыватся с Obj->Str внутренним представлением строки в объекте как правильно __restrict применить как в примере выше или так Код (Text): CHAR * StringReplace(String * __restrict Obj, const CHAR * fToken, const CHAR * rToken); //...
osox Второй вариант. Только нужно учесть, что __restrict распространяется только на память, непосредственно адресуемую указателем, т.е. если у Вас Obj->Str является указателем, то он не наследует __restrict.
green Здравствуйте, да Obj->Str у меня это указатель в любое место в куче typedef struct { CHAR *Str; SIZE_T Length; SIZE_T Size; } String; вот я почему и спросил вроде как __restrict указатель у нас относится только к памяти занимаемой структурой но в прототипе подразумеваем что перекрыватся не должно именно с Obj->Str где то в куче тоесть чтоб сразу глядя на прототип было видно что нельзя писать что то вроде такого StringReplace(Obj, Obj->Str, Obj->Str); хоть это и бессмыслица но хочется чтоб было явно видно предупреждение что перекрывать 2 и 3 параметры с 1 нельзя но можно 2 с 3
green вот определение функции находит все вхождения fToken(findToken) в Obj и заменяет каждое вхождение на rToken(replaceToken) Код (Text): CHAR * StringReplace(String *Obj, const CHAR * __restrict fToken, const CHAR * __restrict rToken) { CHAR *it; size_t ResizeLen, rTokenLen, fTokenLen; ptrdiff_t Offset; if (!Obj->Str || !*fToken) return NULL; Offset = 0; rTokenLen = strlen(rToken); fTokenLen = strlen(fToken); if (rTokenLen > fTokenLen) { size_t Shift; ResizeLen = rTokenLen - fTokenLen; while (it = strstr(Obj->Str + Offset, fToken)) { if (Obj->Length + ResizeLen + 1 > Obj->Size) { if (!StringRealloc(Obj, ResizeLen)) return NULL; it = strstr(Obj->Str + Offset, fToken); } Shift = strlen(it + fTokenLen) + 1; memmove(it + rTokenLen, it + fTokenLen, Shift); memmove(it, rToken, rTokenLen); Obj->Length += ResizeLen; Offset = &it[rTokenLen] - Obj->Str; } } else { size_t Shift; ResizeLen = fTokenLen - rTokenLen; if (ResizeLen && rTokenLen) { while (it = strstr(Obj->Str + Offset, fToken)) { Shift = strlen(it + fTokenLen) + 1; memmove(it + rTokenLen, it + fTokenLen, Shift); memmove(it, rToken, rTokenLen); Obj->Length -= ResizeLen; Offset = &it[rTokenLen] - Obj->Str; } } else if (ResizeLen && !rTokenLen) { while (it = strstr(Obj->Str, fToken)) { Shift = strlen(it + fTokenLen) + 1; memmove(it, it + fTokenLen, Shift); Obj->Length -= ResizeLen; } } else { while (it = strstr(Obj->Str + Offset, fToken)) { memmove(it, rToken, rTokenLen); Offset = &it[rTokenLen] - Obj->Str; } } } return Obj->Str; }
green переделал Код (Text): CHAR * StringReplace(String *Obj, const CHAR * __restrict fToken, const CHAR * __restrict rToken); на Код (Text): CHAR * StringReplace(String * __restrict Obj, const CHAR *fToken, const CHAR *rToken); но в выборе остался не уверен String * __restrict Obj, у нас же заявляет только на память занимаемую структурой ? а надо Obj->Str != fToken && Obj->Str != rToken как бы так указать или только комментарии спасут ? можно конечно дампить 2 и 3 аргументы в кучу тогда и с перекрывающимися будет работать но хорошо если 2 и 3 это короткие аргументы а если огромные то на такой дампинг просядет вся производительность или просто сделать два варианта одна способная обрабатывать перекрывающиеся она будет дампить 2 и 3 и другая версия быстрая но не способная работать с перекрытием просто прокомментировать интерфейс что нельзя перекрывать
osox Тогда нужно атрибут __restrict давать указателю Str, a не Obj. Т.е. для Obj использовать структуру Код (Text): typedef struct { CHAR * __restrict Str; SIZE_T Length; SIZE_T Size; } String;
green но тогда при использовании интерфейса будет не очевидно что перекрытие не допустимо придется все равно читать документацию или как минимум смотреть определение структуры основная идея была в том чтоб используя интерфейс по прототипу было видно что можно а что нет а так __restrict получится скрыт в заголовочном файле в определении структуры придется сначала почитать комментарии посмотреть определение чтоб ошибок не понаделать
osox 1. Опишите это в комментариях к декларации ф-ции - чем это не устраивает? 2. Измените прототип StringReplace - передавайте Str прямым аргументом ф-ции.