Правильно использование static функций
- Войдите на сайт для отправки комментариев
Раз уж новички сюда не пишут, то я побуду новичком.
Есть у меня желание, следуя правилу максимального ограничения области видимости, попрятать часть функций от вызовов извне файла, в котором они реализованы. Если это ещё и компиляцию ускорит - вообще буду рад.
Пытаюсь для этого применить static функции. Сразу предупрежу, что функциональность приведённого ниже кода отсутствует. Это материал, схожий по структуре с реальным кодом, и иллюстрирующий проблему:
static_test.ino
#include "t_static.h" void setup() { Serial.begin(115200); } void loop() { int8_t rc; rc = getBMPMetric(0x76); Serial.println(rc); delay(1000); }
t_static.h
#pragma once int8_t getBMPMetric(const uint8_t);
t_static.cpp
#include <Arduino.h> #include "t_static.h" //#define READY_TESTING static uint8_t waitToBMPReady(const uint8_t _i2cAddress) { //... return _i2cAddress*2; } int8_t getBMPMetric(const uint8_t _i2cAddress) { int8_t rc = true; #if defined(READY_TESTING) rc = waitToBMPReady(_i2cAddress); #endif return rc; }
Если READY_TESTING определено, вызов waitToBMPReady() попадает в исходник и всё компилируется ОК.
Стоит READY_TESTING не определить (например - какой-то функционал в прошивке требуется отключить), вызов waitToBMPReady() в исходнике не присутсвует и компилятор обругивается: warning: 'waitToBMPReady' defined but not used. Оно, конечно, логично, но глаза мозолит.
Вопрос: как полагается делать правильно, чтобы компилятор не вываливал этот warning?
Ну так возьмите и waitToBMPReady() в #ifdef.
Я так и делаю - мой код прямо таки усеян ifdef-ами, поэтому я подумал, что делаю неправильно (ведь правильное должно быть красивое - не я же первый с таким вопросом, наверняка есть рецепт) и есть способ лучше.
а если так :
а если так:
t_static.cpp
Так не компилируется, но если атрибут вперёд перенести, то компиляция проходит, предупреждений нет, однако... в полном соответствии с описанием "This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced." жирнит результирующий код на размер невызываемых, но существующих функций.
Однако, как оказалось, рядом (https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes) валяется аттрибут "unused": "This attribute, attached to a function, means that the function is meant to be possibly unused. GCC does not produce a warning for this function.". С ним, похоже, всё ОК.
Но подожду ещё мнений - может изоляция делается проще, чем я тут наворачиваю.
sadman41 - ну ты же понял, что "я не настоящий сварщик", а этот ответ в StackOverflow нашел :) Так что извини.
Да не, я без претензий. По наводке понял, где покопать.
Кстати, оказывается gcc, за который IDE дёргает, понимает и такое:
Я не пользуюсь "unused" и любыми его "наколеночными" заменителями, а всегда честно исключаю дефайном.
То, что дефайнов много, так можно нужные функции компактно расположить (хоть в отдельном файле) и исключать чохом или сделать макрос для объявления функции и объявлять этим макросом (а дефайны в нём спрятаны).
Могу объяснить почему я не люблю "unused" и не пользуюсь отключением предупреждений в опциях компилятора. Есть несколько причин:
1. Уважаю предупреждения компилятора - пусть они работают как надо, иногда выручат. Не надо их затыкать.
2. Компилятор и/или линкер обычно выбрасывают из кода ненужные вещи, но это а) зависит от их опций и б) может не сработать в сложных случаях. А зачем мне в коде неиспользуемые функции? Лучше я их дефайном исключу.
Кстати, оказывается gcc, за который IDE дёргает, понимает и такое:
Я тоже только недавно узнал, что в чеснам С и так можно:
всю башку себе сломал, пока разбирал чо тут к чему, так до конца и не понял, три дня пил потом.
Я тоже только недавно узнал, что в чеснам С и так можно:
Честный С - он такой :)
три дня пил потом.
Это-то понятно, более интересно сколько ты пил ПЕРЕД тем, как такое написать :)
Кажется, что эта конструкция мне знакома - она где-то обсуждалась уже (что-то припоминаю про usenet) и, помнится, свела с ума не одного "прогера".
эт не я. Это алгоритм копирования Даффа. аналог while(*dst++=*src++); только не до нуля, а со счетчиком.
Кажется, что эта конструкция мне знакома - она где-то обсуждалась уже (что-то припоминаю про usenet) и, помнится, свела с ума не одного "прогера".
Ну вот у меня до сих пор от этого сколиоз головного мозга. И хочецца пить.
Нету шансов у чесного Си против двух бутылок моего срецтва.
Нет, в принципе-то я понимаю, что там происходит, однако, с бытовой точки зрения, не совсем ясно за счёт чего она работает быстрее при том, что там изначально и деление производится и остаток вычисляется, а потом один чёрт происходит бег по указателям...
Нету шансов у чесного Си против двух бутылок моего срецтва.
Воистину!
Нет, в принципе-то я понимаю, что там происходит, однако, с бытовой точки зрения, не совсем ясно за счёт чего она работает быстрее при том, что там изначально и деление производится и остаток вычисляется, а потом один чёрт происходит бег по указателям...
Быстрее за счет развернутого цикла.
Остаток от степени двойки находится без команды деления.
Вообще - красивый код. Хотя и почти с GOTO.
Я тоже только недавно узнал, что в чеснам С и так можно:
А мне иногда хотелось бы типа такой конструкции: