Что такое "статическая функция"?



вопрос был о простых функциях 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 файлы. Просто временное, быстрое решение.

900   11  

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 зачем вообще сохранять статические функции в таблице символов, когда их нет оптимизация? Могут ли они быть использованы для чего-нибудь?

см. также

попробуйте сами

пример 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

    Ничего не найдено.