__restrict

Тема в разделе "LANGS.C", создана пользователем osox, 16 май 2010.

  1. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Всех приветствую
    есть сигнатура такого вида
    Код (Text):
    1. CHAR *
    2. StringReplace(String *Obj,
    3.               const CHAR * __restrict fToken,
    4.               const CHAR * __restrict rToken);
    вопрос вот в чем fToken может перекрыватся с rToken
    но ни один из них не должен перекрыватся с Obj->Str
    внутренним представлением строки в объекте
    как правильно __restrict применить как в примере выше или так
    Код (Text):
    1. CHAR *
    2. StringReplace(String * __restrict Obj,
    3.               const CHAR * fToken,
    4.               const CHAR * rToken);
    //...
     
  2. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    osox
    Второй вариант.
    Только нужно учесть, что __restrict распространяется только на память, непосредственно адресуемую указателем, т.е. если у Вас Obj->Str является указателем, то он не наследует __restrict.
     
  3. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    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 :)
     
  4. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    green

    вот определение функции находит все вхождения fToken(findToken) в Obj и заменяет каждое вхождение на rToken(replaceToken)

    Код (Text):
    1. CHAR *
    2. StringReplace(String *Obj,
    3.               const CHAR * __restrict fToken,
    4.               const CHAR * __restrict rToken)
    5. {
    6.     CHAR *it;
    7.     size_t ResizeLen, rTokenLen, fTokenLen;
    8.     ptrdiff_t Offset;
    9.    
    10.     if (!Obj->Str || !*fToken)
    11.         return NULL;
    12.    
    13.     Offset = 0;
    14.     rTokenLen = strlen(rToken);
    15.     fTokenLen = strlen(fToken);
    16.    
    17.     if (rTokenLen > fTokenLen)
    18.     {
    19.         size_t Shift;
    20.         ResizeLen = rTokenLen - fTokenLen;
    21.         while (it = strstr(Obj->Str + Offset, fToken))
    22.         {
    23.             if (Obj->Length + ResizeLen + 1 > Obj->Size)
    24.             {
    25.                 if (!StringRealloc(Obj, ResizeLen))
    26.                     return NULL;
    27.                 it = strstr(Obj->Str + Offset, fToken);
    28.             }
    29.             Shift = strlen(it + fTokenLen) + 1;
    30.             memmove(it + rTokenLen, it + fTokenLen, Shift);
    31.             memmove(it, rToken, rTokenLen);
    32.             Obj->Length += ResizeLen;
    33.             Offset = &it[rTokenLen] - Obj->Str;
    34.         }
    35.     }
    36.     else
    37.     {
    38.         size_t Shift;
    39.         ResizeLen = fTokenLen - rTokenLen;
    40.         if (ResizeLen && rTokenLen)
    41.         {
    42.             while (it = strstr(Obj->Str + Offset, fToken))
    43.             {
    44.                 Shift = strlen(it + fTokenLen) + 1;
    45.                 memmove(it + rTokenLen, it + fTokenLen, Shift);
    46.                 memmove(it, rToken, rTokenLen);
    47.                 Obj->Length -= ResizeLen;
    48.                 Offset = &it[rTokenLen] - Obj->Str;
    49.             }
    50.         }
    51.         else if (ResizeLen && !rTokenLen)
    52.         {
    53.             while (it = strstr(Obj->Str, fToken))
    54.             {
    55.                 Shift = strlen(it + fTokenLen) + 1;
    56.                 memmove(it, it + fTokenLen, Shift);
    57.                 Obj->Length -= ResizeLen;
    58.             }
    59.         }
    60.         else
    61.         {
    62.             while (it = strstr(Obj->Str + Offset, fToken))
    63.             {
    64.                 memmove(it, rToken, rTokenLen);
    65.                 Offset = &it[rTokenLen] - Obj->Str;
    66.             }
    67.         }
    68.     }
    69.     return Obj->Str;
    70. }
     
  5. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    green
    переделал
    Код (Text):
    1. CHAR *
    2. StringReplace(String *Obj,
    3.               const CHAR * __restrict fToken,
    4.               const CHAR * __restrict rToken);
    на
    Код (Text):
    1. CHAR *
    2. StringReplace(String * __restrict Obj,
    3.               const CHAR *fToken,
    4.               const CHAR *rToken);
    но в выборе остался не уверен :)
    String * __restrict Obj, у нас же заявляет только на память
    занимаемую структурой ?
    а надо Obj->Str != fToken && Obj->Str != rToken
    как бы так указать или только комментарии спасут ?
    можно конечно дампить 2 и 3 аргументы в кучу тогда и с перекрывающимися будет работать но хорошо если 2 и 3 это короткие аргументы а если огромные то на такой дампинг просядет вся производительность :)
    или просто сделать два варианта одна способная обрабатывать перекрывающиеся она будет дампить 2 и 3 и другая версия быстрая но не способная работать с перекрытием просто прокомментировать интерфейс что нельзя перекрывать :)
     
  6. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    osox
    Тогда нужно атрибут __restrict давать указателю Str, a не Obj.
    Т.е. для Obj использовать структуру
    Код (Text):
    1. typedef struct
    2. {
    3.     CHAR * __restrict  Str;
    4.     SIZE_T Length;
    5.     SIZE_T Size;
    6. } String;
     
  7. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    green
    но тогда при использовании интерфейса будет не очевидно что перекрытие не допустимо придется все равно читать документацию или как минимум смотреть определение структуры основная идея была в том чтоб используя интерфейс по прототипу было видно что можно а что нет а так __restrict получится скрыт в заголовочном файле в определении структуры придется сначала почитать комментарии посмотреть определение чтоб ошибок не понаделать :)
     
  8. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    osox
    1. Опишите это в комментариях к декларации ф-ции - чем это не устраивает?
    2. Измените прототип StringReplace - передавайте Str прямым аргументом ф-ции.
     
  9. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    green
    да комментарий в заголовочном файле к декларации написать это наверно самое нормальное :)
     
  10. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    __restrict это хинт для компилятора, не для программиста.