#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. Передача дополнительных параметров обычно требует (немного) дополнительного времени, чтобы поместить параметры в стек (или в регистры), которые будут приняты в качестве параметров. Однако верхняя страница стека почти всегда будет находиться в кэше, поэтому затраты обычно чрезвычайно минимальны.