최상의 답변
파일에 정의 된 함수는 다른 파일에서 액세스 할 수 있다는 것을 알고 있습니다. 함수가 다른 파일에서 호출되지 않도록 제한하려면이를 정적으로 만들 수 있습니다.
따라서 정적 함수는 호출 가능한 함수입니다. 정의 된 동일한 파일에서 .
다음 구문을 사용하여 정적 함수를 정의 할 수 있습니다.
static return\_type function\_name(arguments)
{
function\_body;
}
주어진 숫자의 제곱근을 찾는 함수입니다.
static long int getSquare(int num){
return (num*num);
}
C 언어로 정적 함수의 예를 보여주는 프로그램
#include
//static function definition
static long int getSquare(int num){
return (num*num);
}
int main()
{
int num;
printf("Enter an integer number: ");
scanf("\%d",&num);
printf("Square of \%d is \%ld.\n",num,getSquare(num));
return 0;
}
출력
Enter an integer number: 36
Square of 36 is 1296.
정적 함수가 필요한 이유는 무엇입니까?
코드를 재사용하는 데 함수가 사용되기 때문에 (즉 작성한 코드는 함수에 넣어서 다른 파일에 액세스 할 수 있습니다 ),하지만 일부 다른 파일에서 공유 (호출)해서는 안되는 함수 .
정적 함수는 선언 충돌 문제를 처리하는데도 도움이됩니다. -같은 이름을 가진 두 개의 다른 파일에 두 개의 함수가 있으면 함수 선언이 충돌합니다. 정적으로 만들 수 있습니다.
이러한 요구 사항을 충족하기 위해 정적으로 만들 수 있습니다 .
답변
짧은 답변 : 현재 컴파일중인 파일에서만 함수 이름이 표시되고 호출 가능함을 의미합니다. 별도로 컴파일 된 다른 파일은 함수 이름을 보거나 호출 할 수 없습니다. 결과적으로 동일한 이름의 자체 정적 함수를 가질 수 있습니다. 이렇게하면 파일 포함, 개체 파일 및 바이너리 라이브러리의 연결에서 이름 충돌을 방지 할 수 있습니다.
C에는 4 가지 스토리지 클래스가 있습니다.
- auto (자동) “일반”(기본값)이고 키워드 auto 를 사용하지만 일반적으로 기본값이므로 지정되지 않습니다.
- register 는 파일을 저장하기 위해 생성 된 코드를 최적화 할 수있는 컴파일러에 대한 “힌트”입니다. 더 빠른 처리를 위해 cpu 레지스터의 값. 컴파일러는 그렇게 할 수 있으면 시도하지만 그렇지 않으면 일반과 동일합니다.
- extern external은 해당 이름의 전역 변수 하나만 extern으로 선언하는 모든 파일이 해당 저장소를 사용합니다. 하나의 파일은 컴파일시 할당 될 정규 변수로 전역 적으로 선언합니다.
- 정적 C 소스 파일의 저장소 지정자는 몇 가지 다른 점이 있습니다.
- 이름과 저장 공간은 동시에 컴파일되는 다른 파일로 내보내지지 않습니다. 이를 통해 각 파일은 충돌하지 않는 동일한 이름을 가질 수 있습니다.
- 변수에 대해 생성 된 저장소는 정적 저장소 영역에 생성되고 프로그램 시작시 또는 명시 적 값으로 0으로 초기화됩니다.
- li>
- 정적 변수의 초기화는 한 번만 수행됩니다. (컴파일 시간에). 이후에 할당 된 값은 프로그램의 수명 동안 또는 할당에 의해 변경 될 때까지 유지됩니다.
- 함수 내에서 선언 된 정적 저장소에는 함수 범위가 있지만 정적 할당이 있습니다. 이는 스토리지가 프로그램 수명 동안 영구적이며 함수 스택 프레임이 함수 호출에 할당 될 때 생성되지 않음을 의미합니다. 여러 함수 호출을 통해 그 가치를 유지합니다. 코드 블록이 반환 된 후 스택에서 복구 되더라도 저장소는 유지됩니다.
int accumulate( unsigned int x)
{
static unsigned int acc = 0;
acc = acc + x;
return acc;
}
- 위의 경우 var acc가 각 호출을 통해 값을 유지하므로 입력의 실행 집계. acc는 프로그램로드시 0으로 초기화됩니다.
- 정적 변수는 RAM에 주소가 있으며 참조 또는 값으로 함수로 보낼 수 있습니다.
- 해당 범위 밖의 정적 변수와 이름이 같은 더 작은 범위의 변수 (함수 내부에 정의 됨)는 다른 변수와 마찬가지로 정적 변수를가립니다.
- 정적 변수는 그렇지 않을 수 있습니다. 따라서 값별로 매개 변수로 명시 적으로 보내지 않으면 컴파일 도메인에서 값이 손실 될 수 있습니다. (gotcha!)
- 4와 마찬가지로 다른 파일은 extern 으로 정적 변수에 액세스 할 수 없습니다. 자동 (일반) 변수. 작동하지 않고 충돌하는 버그가있는 프로그램이 발생하고 컴파일러가 속아 놓칠 수 있습니다.
- 정적 변수는 선언시 초기화 될 수 있지만 초기화 값은 평가 가능한 상수 표현식이어야합니다. 컴파일 타임에 계산할 수없는 값이 아닙니다. 매개 변수 변수와 같은 알 수없는 값 또는 컴파일 타임에 발생하지 않은 함수 호출의 결과로 정적 변수를 초기화 할 수 없습니다.
int accumulate( unsigned int x)
{
/* ERROR x is not a compile-time constant. */
static unsigned int acc = x;
static unsigned int acc = 0; /* OK */
acc = acc + x;
return acc;
}
정적 함수
- C의 정적 함수에는 파일 범위가 있습니다 . 정적 함수는 동일한 번역 단위의 다른 파일에서 호출됩니다. 번역 단위는 한 번에 컴파일하기 위해 전처리 후 컴파일러로 들어가는 모든 소스 코드입니다. 정적 함수는 정적 변수에 액세스하거나 다른 파일에서 정적 함수를 호출 할 수 없습니다. 따라서 함수에 대한 액세스를 현재 파일로 제한하려면이를 정적으로 만들 수 있습니다. 해당 이름의 함수 하나만 해당 파일에 존재할 수 있습니다 (일반 함수에도 적용됨). 따라서 종종 유틸리티 함수가 헤더 파일에 배치되어 여러 컴파일에 포함되며 헤더는 전 처리기 명령으로 보호됩니다. 컴파일 단위에 두 번 이상 포함되어야합니다. 모든 표준 C 라이브러리 헤더는 전역 함수로 가득 차 있으며, 이러한 헤더는 컴파일에서 한 번만 컴파일되고 전역 함수가되도록 보호됩니다. 정적 기능이 없습니다. 정적 함수에는 ‘내부 연결’이 있다고합니다. 즉, 동일한 최종 프로그램 또는 라이브러리에 연결되어 있어도 다른 컴파일 된 모듈에서는 볼 수 없습니다. 함수가 정적 이 아닌 경우 C에서 해당 함수는 전역 함수이며 전체 프로그램에서 전역 적으로 사용할 수 있습니다. 즉, 전체 프로그램에서 인쇄 라는 함수를 하나만 가질 수 있습니다 . 이 문제를 해결하려면 함수와 변수를 정적으로 만드세요. 그러면 이름 충돌이 발생하지 않습니다.
- 함수는 전역이며 기본적으로 extern입니다. , 정의 된 파일을 제외합니다. 따라서 extern 은 이미 암시 적으로 존재하기 때문에 함수와 함께 C 소스에서 사용됩니다. 이것이 번역 단위의 모든 파일에서 일반 함수를 호출 할 수있는 이유입니다. 그들은 external linkage를 가지고 있다고합니다. 즉, 일단 연결되면 모듈의 모든 파일이나 연결된 프로그램의 다른 모듈에서보고 호출 할 수 있습니다.
- 함수 프로토 타입 선언은 암시 적으로 extern 인 “임시 정의”입니다 . 프로토 타입 선언이 처음으로 스캔 된 후 코드는 최종 코드에 전체 정의가 존재하는 한 함수를 호출 할 수 있습니다. 즉, “실제 정의”가 실제로 존재해야하며 그렇지 않으면 연결 단계 가 실패합니다. 이것이 C의 헤더가 일반적으로 함수의 소스 코드를 포함하지 않고 컴파일 할 필요가 없지만 연결 단계에있는 이유입니다.
- 정적 함수 프로토 타입 선언은 명시 적으로 extern이 아닌 “임시 정의”입니다 . 전체 정의가 현재 번역 단위 (동시에 컴파일 됨)에 있어야하며 그렇지 않으면 컴파일이 실패합니다. 최신 C 컴파일러는 실제 함수 호출보다 일찍 발생하는 한 정의에서 프로토 타입을 합성합니다. 소위 “포워드 선언”은 나중에 실제 정의와 함께 임시 정의를 사용할 수 있도록하며 데이터 구조 및 라이브러리 구성에서 다양한 용도로 사용됩니다.
- 파일 서명의 첫 번째 정의는 static 또는 extern을 포함하여 전체 프로그램에 사용되는 정의입니다. 함수가 처음 정의되면 처음에 static으로 선언되면 나중에 static 키워드없이 다시 정의 되더라도 항상 static이됩니다. 처음에 extern (기본값)으로 선언 된 경우 정적으로 재정의 할 수 없습니다.
static void f(int); /* Function is always static */
...
void f(int x) { ….} /* static , not exported, no error */
void f(int); /* Function is always global */
...
static void f(int x) { ….} /*ERROR NOT STATIC */
clang: "error: static declaration of "f" follows non-static declaration"
- 블록 범위에 정의 된 함수는 정적으로 선언 할 수 없습니다. 파일 범위 정적 함수 정의 만 블록 외부에서 만들 수 있습니다. 이는 파일 범위를 전체 파일보다 작게 만들 수 없기 때문에 논리적 인 관점에서 의미가 있습니다. 따라서 파일의 아주 초기에 정적 함수 또는 최소한 프로토 타입을 정의하십시오.
- Static 반환 유형이 아닌 함수를 참조합니다 . 원하는 경우 반환 유형 뒤에 static 키워드를 배치 할 수 있지만 그렇게하면 이상하고 사람들을 혼란스럽게 할 것입니다. 반환 값은 정적이 아니며 함수는 있습니다.
- 정적 함수 정의는 동일한 파일 또는 포함 된 파일에서 그 앞에 정의 된 전역 파일. 해당 이름으로 정의 된 함수가 이미있는 경우 정적 함수 또는 동일한 이름의 함수로 재정의 할 수 없습니다.
C는 C ++처럼 내부적으로 함수와 변수의 이름을 바꾸지 않습니다 . 따라서 함수 오버로딩을 지원하지 않습니다. C ++는 클래스의 일부인지 또는 매개 변수가 무엇인지 등 여러 가지 추가 데이터 유형을 나타내는 코드화 된 이름으로 함수 이름을 “매듭”합니다. 따라서 C에서는 static 키워드가 없으면 다음 함수가 하나만있을 수 있습니다. 수반되는 파일 또는 라이브러리의 수에 관계없이 프로그램의 각 고유 이름.
이미 존재하는 이전 기능에 대한 기능을 변경하려면 어떻게해야합니까?
똑똑한 C 코더가하는 일은 그들의 기능에 대해 다른 이름을 만드는 것입니다. 그러나 전처리기로 소스 텍스트를 선제 적으로 창공하여 컴파일러를 속일수있는 방법이 있습니다.
예 : 어떤 바보가 자신의 라이브러리에 int sort( char** Array)
함수를 작성했습니다. 글로벌로 만들었고 버그가 많고 원하는대로 정확히 수행하지 않습니다. 문자 나 그 뒤에 숫자가 나오고 어떤 이유로 T 단어가 항상 첫 번째이기 때문입니다.
라이브러리를 사용하지만 함수를 수정해야합니다. 소스 코드가 아닌 헤더와 컴파일 된 라이브러리 만 있으면됩니다.
OK> “의 모든 인스턴스를 대체하는”특별한 “헤더가 만들어집니다. 헤더에서 “bad\_sort”로 정렬 한 다음 코드를 가져와 “sort”의 모든 인스턴스를 “good\_sort”로 바꿉니다. “good\_sort”는 good\_sort.h에서 완전히 정의되지만 static으로 표시되어 포함 된 파일에서만 알 수 있습니다.
/* good\_sort.h */
#ifndef \_GOOD\_SORT\_H
#define \_GOOD\_SORT\_H
static int good\_sort(char** Array)
{
... //code here
return numsorted;
}
#endif
두 번 포함되지 않도록 정의 가드 브래킷이 추가되었습니다.
/*-----------------------------------*/
/* program.c */
#include "Trumpsort.h" /* The buggy library header */
...
#ifdef sort
#undef sort /* undefine the sort function name as reserved */
#define sort bad\_sort /* replace the name */
#include "good\_sort.h" /* your fixed version */
#endif
#define sort good\_sort /* replace the name in this file */
/* rest of file */
일부 쓰레기이지만 아이디어는 함수를 호출하는 것입니다. 이름 바꾸기로 나쁜 것 대신 “good\_sort”로 지정하고 대신 호출합니다. (그러나이 파일에서만 — static ).