Что такое "статическая функция"?
вопрос был о простых функциях c, а не c++ static методы, как уточняется в комментариях.
Ок, я понимаю, что такое static переменная есть, но что такое ?
а почему, если я объявляю функцию, скажем void print_matrix, скажем так a.c (без a.h) и "a.c" - Я "print_matrix@@....) already defined in a.obj", но если я объявлю его как static void print_matrix затем он компилирует?
обновление просто чтобы прояснить ситуацию - я знаю в том числе .c плохо, как многие из вас заметили. Я просто делаю это, чтобы временно очистить пространство в main.c пока у меня нет лучшего представления о том, как сгруппировать все эти функции в правильные .h и .c файлы. Просто временное, быстрое решение.
11 ответов:
staticфункции-это функции, которые видны только другим функциям в том же файле (точнее тот же ЕП).EDIT: для тех, кто подумал, что автор вопроса имел в виду метод класса: как вопрос с тегами
CОн имеет в виду простую старую функцию C. For (C++ / Java/...) методы класса,staticозначает, что этот метод может быть вызван на самого класса, а не экземпляра этого класса необходимый.
существует большая разница между статическими функциями в C и статическими функциями-членами в C++. В C статическая функция не видна за пределами своей единицы перевода, которая является объектным файлом, в который она скомпилирована. Другими словами, статичность функции ограничивает ее область действия. Вы можете думать о статической функции как о" частной " для ее *.C файл (хотя это не совсем правильно).
в C++ "статический" может также применяться к функциям-членам и членам данных классов. Один статический элемент данных также называется "переменной класса", в то время как нестатический элемент данных является"переменной экземпляра". Это терминология Smalltalk. Это означает, что существует только одна копия статического члена данных, которые используются всеми объектами класса, в то время как каждый объект имеет собственную копию нестатический член данных. Таким образом, статический член данных по существу является глобальной переменной, то есть членом класса.
нестатические функции-члены могут получить доступ ко всем данным-членам класса: статические и нестатический. Статические функции-члены могут работать только со статическими элементами данных.
один из способов подумать об этом заключается в том, что в C++ статические члены данных и статические функции-члены принадлежат не какому-либо объекту, а всему классу.
есть два варианта использования ключевого слова static, когда речь заходит о функциях в C++.
во-первых, необходимо отметить функцию как имеющую внутреннюю связь, чтобы на нее нельзя было ссылаться в других единицах перевода. Его использование не рекомендуется в C++. Для этого использования предпочтительны безымянные пространства имен.
// inside some .cpp file: static void foo(); // old "C" way of having internal linkage // C++ way: namespace { void this_function_has_internal_linkage() { // ... } }второе использование находится в контексте класса. Если класс имеет статическую функцию-член, это означает, что функция является членом класса (и имеет обычный доступ к другие члены), но его не нужно вызывать через определенный объект. Другими словами, внутри этой функции нет указателя "this".
минимальный запускаемый многофайловый пример
а.с:
#include <stdio.h> /* Undefined behavior: already defined in main. Binutils 2.24 gives an error and refuses to link. https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c */ /*void f() { puts("a f"); }*/ /* OK: only declared, not defined. Will use the one in main. */ void f(void); /* OK: only visible to this file. */ static void sf() { puts("a sf"); } void a() { f(); sf(); }главная.c:
#include <stdio.h> void a(void); void f() { puts("main f"); } static void sf() { puts("main sf"); } void m() { f(); sf(); } int main() { m(); a(); return 0; }сборник:
gcc -c a.c -o a.o gcc -c main.c -o main.o gcc -o main main.o a.oвыход:
main f main sf main f a sfтолкование
- Есть две отдельные функции
sf, по одному для каждого файла- Есть одна общая функция
fкак обычно, чем меньше объем, тем лучше, поэтому всегда объявляйте функции
staticесли вы можете.в программировании на C файлы часто используются для представления "классов" и
staticфункции представляют собой "частные" методы класса.общий шаблон C должен передать a
thisструктура вокруг как первый аргумент "метода", который в основном то, что C++ делает под капотом.о чем говорят стандарты это
С99 проект N1256 6.7.1 "спецификаторы класса хранения" говорит, что
staticявляется "спецификатором класса хранения".6.2.2 / 3" связи идентификаторов " говорит
staticподразумеваетinternal linkage:если объявление идентификатора области видимости файла для объекта или функции содержит описатель класса хранения static, идентификатор имеет внутреннюю связь.
и 6.2.2/2 говорит, что
internal linkageведет себя как в наш пример:в наборе единиц перевода и библиотек, составляющих целую программу, каждое объявление определенного идентификатора с внешней связью обозначает один и тот же объект или функцию. В пределах одной единицы трансляции каждое объявление идентификатора с внутренней связью обозначает один и тот же объект или функцию.
где "единица перевода" - это исходный файл после предварительной обработки.
как GCC реализует его для ELF (Linux)?
С
STB_LOCALпривязка.если мы компилируем:
int f() { return 0; } static int sf() { return 0; }и разберите таблицу символов с помощью:
readelf -s main.oвывод содержит:
Num: Value Size Type Bind Vis Ndx Name 5: 000000000000000b 11 FUNC LOCAL DEFAULT 1 sf 9: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 fтаким образом, привязка является единственным существенным различием между ними.
Valueпросто их смещение в.bssраздел, поэтому мы ожидаем, что он будет отличаться.
STB_LOCALописана в спецификации эльфов http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html:локальные символы STB_LOCAL не видны за пределами объектного файла, содержащего их определение. Локальные символы с одинаковым именем могут существовать в нескольких файлах, не мешая друг другу
что делает его идеальным выбором для представления
static.функции без статики
STB_GLOBAL, а спец говорит:когда редактор ссылок объединяет несколько перемещаемых объектных файлов, он не позволяет использовать несколько определений stb_global символов с одинаковым именем.
что согласуется с ошибками связи на нескольких нестатических определениях.
если мы провернем оптимизацию с
-O3наsfсимвол полностью удаляется из таблицы символов: он не может быть использован извне в любом случае. TODO зачем вообще сохранять статические функции в таблице символов, когда их нет оптимизация? Могут ли они быть использованы для чего-нибудь?см. также
- то же самое для переменных:https://stackoverflow.com/a/14339047/895245
externнапротивstatic, а функции ужеexternпо умолчанию: как использовать extern для обмена переменными между исходными файлами?попробуйте сами
пример GitHub для вас, чтобы играть.
ниже приведены простые функции C - в классе C++ модификатор 'static' имеет другое значение.
Если у вас есть только один файл, то этот модификатор не имеет абсолютно никакого значения. Разница заключается в больших проектах с несколькими файлами:
В C, каждый "модуль" (комбинация образца.C и образец.h) компилируется независимо, а затем каждый из этих скомпилированных объектных файлов (пример.o) связаны вместе с исполняемым файлом компоновщиком.
допустим, у вас есть несколько файлов, которые вы включаете в свой основной файл и два из них имеют функцию, которая используется только внутри для удобства называется
add(int a, b)- компилятор легко создаст объектные файлы для этих двух модулей, но компоновщик выдаст ошибку, потому что он находит две функции с одинаковым именем и не знает, какую из них следует использовать (даже если нет ничего, чтобы связать, потому что они не используются где-то еще, но в своем собственном папка.)вот почему вы делаете эту функцию, которая используется только внутри, статической функцией. В этом случае компилятор не создает типичный флаг"вы можете связать эту вещь" для компоновщика, так что компоновщик не видит эту функцию и не будет генерировать ошибку.
во-первых: это вообще плохая идея, чтобы включить
.cppфайл в другом файле-это приводит к таким проблемам :-) обычный способ заключается в создании отдельных блоков компиляции и добавлении файла заголовка для включенного файла.во-вторых:
В C++ есть какая - то запутанная терминология здесь-я не знал об этом, пока не указал в комментариях.
a)
static functions- унаследовано от C, и о чем вы здесь говорите. Вне любого класса. Статика функции означает, что он не виден за пределами текущего блока компиляции - поэтому в вашем случае a.obj имеет копию, а ваш другой код имеет независимую копию. (Раздувание окончательного исполняемого файла с несколькими копиями кода).б)
static member function- какие термины объектной ориентации статические метод. Живет внутри класса. Вы вызываете это с помощью класса, а не через экземпляр объекта.эти две различные статические функции определения совершенно разные. Будьте осторожны - здесь будут драконы.
определения статических функций помечают этот символ как внутренний. Таким образом, он не будет виден для связывания извне, а только для функций в том же блоке компиляции, обычно в том же файле.
статическая функция-это функция, которая может быть вызвана для самого класса, в отличие от экземпляра класса.
например нестатический будет такой:
Person* tom = new Person(); tom->setName("Tom");этот метод работает на экземпляре класса, а не на самом классе. Однако вы можете иметь статический метод, который может работать без экземпляра. Это иногда используется в Заводском шаблоне:
Person* tom = Person::createNewPerson();
Minor nit: статические функции видны единице перевода, которая для большинства практических случаев является файлом, в котором определена функция. Ошибка, которую вы получаете, обычно называется нарушением правила одного определения.
стандарт, вероятно, говорит что-то вроде:
" каждая программа должна содержать ровно одно определение каждой неинлайн функция или объект, который используется в этой программе; диагностики требуемый."
Это способ C смотреть на статические функции. Это, однако, рекомендуется использовать в C++.
В C++, кроме того, можно объявить функции-члены, статические. Это в основном метафункции, т. е. они не описывают/изменяют поведение/состояние конкретного объекта, а действуют на весь класс. Кроме того, это означает, что вам не нужно создавать объект для вызова статической функции-члена. Кроме того, это также означает, что вы получаете доступ только к статическим членам переменные в рамках такой функции.
Я бы добавил к примеру Parrot одноэлементный шаблон, который основан на такого рода статической функции-члена, чтобы получить/использовать один объект в течение всего срока службы программы.
ответ на статическую функцию зависит от языка:
1) в языках без OOPS, таких как C, это означает, что функция доступна только в файле, где она определена.
2) в языках с OOPS , таких как C++, это означает, что функция может быть вызвана непосредственно в классе, не создавая его экземпляр.
для статической функции в" c " compiller не будет создавать свои внутренние переменные в стеке, поэтому вызов статической функции выполняется быстрее, и, как следствие, вы не можете использовать инициализаторы, такие как: char c='A'.
Comments