Локальная синонимичная переменная для неточного типа

#c #function #gcc #constants #typedef

#c #функция #gcc #константы #typedef

Вопрос:

Я немного новичок в C, поэтому я не знаком с тем, как бы я подошел к решению этой проблемы. По мере продолжения чтения вы заметите, что не критично, что я нахожу решение, но это, несомненно, было бы неплохо для этого приложения и будущих ссылок. 🙂

У меня есть параметр int hello, и я не хочу создавать синонимичную копию не этого.

 f(int hello, structType* otherParam){  
  // I would like to have a synonom for (!hello)
}
  

Моей первой мыслью было создать локальную константу, но я не уверен, что это приведет к дополнительному потреблению памяти. Я создаю с помощью GCC, и я действительно не знаю, распознает ли он константу параметра (перед любыми изменениями) просто как синонимичную переменную. Я так не думаю, потому что параметр может (даже если он не будет) быть изменен позже в этой функции, что не повлияет на константу.

Затем я подумал о создании локального typedef, но я не уверен, какой именно синтаксис для этого нужен. Я попытался выполнить следующее:

 typedef (!hello) hi;
  

Однако я получаю следующую ошибку.

 D:/src-dir/file.c: In function 'f':
D:/src-dir/file.c: 00: error: expected identifier or '(' before '!' token
  

Приветствуется любая помощь.

Комментарии:

1. Обратите внимание, что я изначально не ожидал, что typedef будет работать таким образом. Я подумал, что это было немного рискованно… Было бы здорово иметь подобное решение, хотя!

Ответ №1:

В общем, на C вы хотите написать код, который наиболее четко выражает ваши намерения, и позволить оптимизатору найти наиболее эффективный способ реализовать это.

В вашем примере часто используемого вычисления сохранение результата в const определенной переменной является наиболее подходящим способом сделать это — что-то вроде следующего:

 void f(int hello)
{  
    const int non_hello = !hello;

    /* code that uses non_hello frequently */
}
  

или, что более вероятно:

 void x(structType *otherParam)
{  
    char * const d_name = otherParam->b->c->d->name;

    /* code that uses d_name frequently */}
}
  

Обратите внимание, что такой const переменной не обязательно должна быть выделена какая-либо память (если только вы не возьмете ее адрес с amp; где-нибудь) — оптимизатор может просто поместить ее в регистр (и имейте в виду, что даже если ей действительно будет выделена память, это, скорее всего, будет память стека).

Комментарии:

1. Хорошо сказано. Вы, кажется, достаточно ясно поняли мои намерения и немного успокоили меня в отношении выделения памяти с ограничениями const в отношении того, как компилятор «мог» обрабатывать свои оптимизации в ситуации, подобной моей. Спасибо. 🙂

Ответ №2:

Typedef определяет псевдоним для типа, это не то, что вы хотите. Итак..

  • Просто используйте !hello там, где вам это нужно

Зачем вам нужен «синоним» для !hello ? Любой программист мгновенно распознал бы !hello вместо того, чтобы искать ваш хитрый трюк для определения «синонима».

Комментарии:

1. Я надеялся, что мой пример, очевидно, будет просто примером. В этом сценарии у меня будет длинный список средств доступа для нескольких переменных на функцию (много функций). Это также приложение, критичное к производительности на устройстве с низким объемом памяти. Я не против дополнительных параметров (текущего способа, которым мы что-то делаем), однако я просто прошу посмотреть, есть ли способ получше. Ваше решение, к сожалению, неадекватно.

2. @Xoorath Я призываю вас найти лучшее решение с точки зрения производительности 🙂 Если вы можете это сделать, я призываю вас написать пример, где это показано.

3. @cnicutar Возможно, я слишком сильно беспокоюсь о массовом использовании почти мгновенных операций. Если у нас есть список из 3-5 средств доступа к указателям и ! оператор, используемый около дюжины раз в функции, вызываемой несколько сотен раз за кадр, как вы думаете, это все равно было бы быстрее, чем добавление другого параметра для каждой переменной? т.е.: f (a) if(!a->b-> c->d->e) //… // а также дополнительные переменные, к которым осуществляется доступ по цепочке от a к f (a, b, c, d, e) if(!e) ..// // а также использование других параметров.

4. @Xoorath Я не знаю ограничений вашего оборудования. Но обычно память дешевле времени. Вам действительно не хватает места для другой переменной? Вы профилировали это и обнаружили, что использование отдельного целого числа по сравнению с записью !original будет быстрее?

5. @cnicutar Я не могу обсудить ограничения моей работы. Я просто профилирую параметры позже, если это станет проблемой. Вы правы, обычно это так — и, вероятно, так и есть в том, что я делаю сейчас. Если бы существовал способ создать синоним для того, что я делал, это могло бы выглядеть так же чисто, как текущее решение, с (вероятным) преимуществом в производительности вашего предложения. Ну, если я волшебным образом не получу ответ, который позволяет делать то, на что я надеялся (что маловероятно) Я дам вам чек.

Ответ №3:

Дано:

 f(int hello, structType* otherParam){  
  // I would like to have a synonom for (!hello)
}
  

Очевидный, прямой ответ на то, что у вас есть здесь, был бы:

 f(int hello, structType *otherParam) { 
    int hi = !hello;
    // ...
}
  

Я бы не ожидал увидеть от этого какого-либо существенного (или, возможно, даже незначительного) влияния на скорость выполнения. На самом деле, вероятно, не так много возможностей для улучшения скорости выполнения.

Безусловно, иногда что-то подобное может сделать код более читаемым. Однако также обратите внимание, что когда / если вы измените значение hello , значение hi не будет изменено для соответствия (если вы не добавите код для его обновления). Это редко бывает проблемой, но, тем не менее, о чем следует помнить.

Комментарии:

1. Это было то, о чем я думал с идеей const. const работает в моей ситуации, но, очевидно, ваш ответ не предполагает, что это хорошо. Я бы сказал, что это так же разумно, как и дополнительные параметры. Вы знаете, добавит ли передача параметров дополнительные накладные расходы сверх потребления памяти копией? Я также рассмотрю это и прокомментирую свои выводы, если никто другой не сделал этого первым.

2. Передача дополнительных параметров обычно требует (немного) дополнительного времени, чтобы поместить параметры в стек (или в регистры), которые будут приняты в качестве параметров. Однако верхняя страница стека почти всегда будет находиться в кэше, поэтому затраты обычно чрезвычайно минимальны.