무엇을 인쇄합니까? 6 6 또는 6 7? 그리고 왜?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
무엇을 인쇄합니까? 6 6 또는 6 7? 그리고 왜?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
답변:
여기에는 수명과 범위라는 두 가지 문제가 있습니다.
변수의 범위는 변수 이름을 볼 수있는 곳입니다. 여기서 x는 foo () 함수 내에서만 볼 수 있습니다.
변수의 수명은 변수가 존재하는 기간입니다. x가 static 키워드없이 정의 된 경우 수명은 foo ()의 항목에서 foo ()의 반환까지입니다. 따라서 모든 호출에서 5로 다시 초기화됩니다.
static 키워드는 변수의 수명을 프로그램의 수명으로 연장하는 역할을합니다. 예를 들어 초기화는 한 번만 발생하고 변수는 foo ()에 대한 모든 향후 호출에 대해 값을 유지합니다.
출력 : 6 7
이유 : 정적 변수는 자동 변수와 달리 한 번만 초기화되며 정적 변수의 추가 정의는 런타임 중에 무시됩니다. 수동으로 초기화하지 않으면 자동으로 0 값으로 초기화됩니다. 그래서,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
다음 프로그램이있는 것과 같습니다.
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
이 프로그램에서 static 키워드가하는 일은 컴파일러에게 (본질적으로) '이봐, 다른 사람이 액세스하지 않기를 바라는 변수가 있습니다. 다른 사람에게 그것이 존재한다고 말하지 마십시오'라고 말하는 것입니다.
메서드 내에서 static 키워드는 컴파일러에게 위와 동일하지만 '이 함수 외부에 존재한다는 사실을 아무에게도 말하지 마십시오.이 함수 내에서만 액세스 할 수 있어야합니다'라고 말합니다.
이게 도움이 되길 바란다
x
main을 사용 하여 찌르고 풀 수 있습니다 . 글로벌입니다. 원래 예제에서는 x
foo에 로컬이었고 해당 블록 내부에서만 볼 수 있었으며 일반적으로 바람직합니다. foo가 x
예측 가능하고 가시적 인 방식으로 유지하기 위해 존재한다면 다른 사람들이 찌르는 것은 일반적으로 위험합니다. 범위 내에서 유지하는 또 다른 이점으로 휴대 foo()
성도 유지합니다 foo()
.
c
컨텍스트에서 귀하의 예제는 전역 범위에서 불법입니다. (C는 전역에 대한 상수 이니셜 라이저가 필요하지만 C ++는 그렇지 않습니다.)
함수 내부의 정적 변수는 프로그램이 실행되는 한 수명이 있습니다. 함수가 호출 될 때마다 할당되고 함수가 반환 될 때 할당이 취소되는 것은 아닙니다.
의 선언 x
은 내부에 foo
있지만 x=5
초기화는 foo
!
여기서 이해해야 할 것은
static int x = 5;
다음과 같지 않다
static int x;
x = 5;
다른 답변은 여기에서 중요한 단어, 범위 및 수명을 사용했으며의 범위 x
는 함수의 선언 지점에서 함수 foo
끝까지 임을 지적했습니다 foo
. 예를 들어 선언을 함수의 끝으로 이동하여 확인한 결과 문 x
에서 선언되지 x++;
않습니다.
따라서 static int x
명령문 의 (범위) 부분은 실제로 읽은 위치, 함수 내부 어딘가에 적용되며 함수 내부의 위가 아닌 그 이후에만 적용됩니다 .
그러나 x = 5
명령문 의 (수명) 부분은 변수의 초기화이며 프로그램로드의 일부로 함수 외부 에서 발생 합니다. 변수 x
는 5
프로그램이로드 될 때의 값으로 생성 됩니다.
나는 주석 중 하나에서 이것을 읽었습니다. " 또한 이것은 정말로 혼란스러운 부분을 다루지 않습니다. 이것은 이니셜 라이저가 후속 호출에서 생략된다는 사실입니다. "모든 호출에서 생략됩니다. 변수 초기화는 적절한 기능 코드 밖에 있습니다.
5의 값은 foo 호출 여부에 관계없이 이론적으로 설정되지만 컴파일러는 아무데도 호출하지 않으면 함수를 최적화 할 수 있습니다. 5의 값은 foo가 호출되기 전에 변수에 있어야합니다.
내부 foo
에서 명령문 static int x = 5;
은 코드를 전혀 생성하지 않을 것입니다.
내 프로그램에 x
함수 foo
를 넣을 때 주소가 사용 하는 것을 발견 한 다음 프로그램을 다시 실행하면 동일한 위치가 사용될 것이라고 (올바르게) 추측했습니다. 아래의 부분 화면 캡처는에 대한 첫 번째 호출 이전에도 x
값이 있음을 보여줍니다 .5
foo
출력은 6 7
. 정적 변수 (함수 내부 여부에 관계없이)는 해당 번역 단위의 함수가 실행되기 전에 정확히 한 번 초기화됩니다. 그 후에는 수정 될 때까지 값이 유지됩니다.
바 딕크,
왜 ...? 이유는 정적 변수는 한 번만 초기화되고 프로그램 전체에서 그 값을 유지하기 때문입니다. 즉, 함수 호출 사이에 정적 변수를 사용할 수 있습니다. 또한 "함수가 호출되는 횟수"를 계산하는 데 사용할 수도 있습니다.
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
대답은 5 4 3 2 1이고 5 5 5 5 5 5 .... (무한 루프) 예상대로입니다. 다시 말하지만, 정적 변수는 한 번 초기화되고 다음에 main ()이 호출 될 때 프로그램에서 이미 초기화 되었기 때문에 5로 초기화되지 않으므로 값을 변경할 수 있지만 다시 초기화 할 수는 없습니다. 이것이 정적 변수가 작동하는 방식입니다.
또는 스토리지별로 고려할 수 있습니다. 정적 변수는 프로그램의 데이터 섹션에 저장되고 데이터 섹션에 저장된 변수는 한 번 초기화됩니다. 초기화 전에 BSS 섹션에 보관됩니다.
차례로 Auto (로컬) 변수는 Stack에 저장되고 스택의 모든 변수는 함수가 새로운 FAR (함수 활성화 레코드)로 호출 될 때 항상 다시 초기화됩니다.
이해를 돕기 위해 위의 예를 "정적"없이 수행하고 출력이 무엇인지 알려주십시오. 그러면이 둘의 차이점을 이해할 수 있습니다.
감사합니다 Javed
정적 변수에 대한 Wikipedia 기사를 읽어 보겠습니다 .
정적 지역 변수 : 함수 내에서 정적로 선언 된 변수는 자동 지역 변수와 동일한 범위를 가지면서 정적으로 할당됩니다. 따라서 함수가 한 번의 호출 중에 정적 지역 변수에 입력하는 값은 함수가 다시 호출 될 때 여전히 존재합니다.
쉽게 테스트 할 수있는 것처럼 6 7이 인쇄되고 그 이유는 다음과 같습니다. foo
처음 호출되면 정적 변수 x가 5로 초기화됩니다. 그런 다음 6으로 증가하여 인쇄됩니다.
이제에 대한 다음 호출 foo
입니다. 프로그램은 정적 변수 초기화를 건너 뛰고 대신 마지막으로 x에 할당 된 값 6을 사용합니다. 실행은 정상적으로 진행되어 7 값을 제공합니다.
6 and 7 정적 변수는 한 번만 초기화되기 때문에 5 ++는 첫 번째 호출에서 6이됩니다. 6 ++는 두 번째 호출에서 7이됩니다. 참고-두 번째 호출이 발생하면 x가 정적 변수이므로 5 대신 x 값이 6이됩니다.
적어도 C ++ 11에서 로컬 정적 변수를 초기화하는 데 사용 된 표현식이 'constexpr'이 아닌 경우 (컴파일러에서 평가할 수 없음) 함수를 처음 호출하는 동안 초기화가 발생해야합니다. 가장 간단한 예는 매개 변수를 직접 사용하여 로컬 정적 변수를 초기화하는 것입니다. 따라서 컴파일러는 호출이 첫 번째 호출인지 여부를 추측하기 위해 코드를 내 보내야하며, 이는 차례로 로컬 부울 변수가 필요합니다. 이러한 예제를 컴파일하고 어셈블리 코드를보고 이것이 사실인지 확인했습니다. 예는 다음과 같을 수 있습니다.
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
물론 expresion이 'constexpr'인 경우에는 필요하지 않으며 컴파일러가 출력 어셈블리 코드에 저장 한 값을 사용하여 프로그램로드시 변수를 초기화 할 수 있습니다.