문제

C, C ++ 및 Java의 정확한 정적 변수가 기본적으로 0으로 초기화되는 이유를 알고 싶습니다. 그리고 왜 이것이 로컬 변수에 사실이 아닌가?

도움이 되었습니까?

해결책

정적 변수가 결정적으로 초기화되고 로컬 변수가 그렇지 않은 이유는 무엇입니까?

정적 변수가 어떻게 구현되는지 확인하십시오. 그들에 대한 메모리는 링크 시간에 할당되며, 초기 값은 링크 시간에도 제공됩니다. 런타임 오버 헤드가 없습니다.

반면, 로컬 변수에 대한 메모리는 런타임에 할당됩니다. 스택은 성장해야합니다. 당신은 전에 무엇이 있었는지 모릅니다. 원한다면 해당 메모리 (0)를 지울 수 있지만 런타임 오버 헤드가 발생합니다. C ++ 철학은 "당신이 사용하지 않는 것에 대해 지불하지 않는다"는 것이므로 기본적으로 그 메모리를 제로하지 않습니다.

자,하지만 왜 정적 변수가 다른 값이 아닌 0으로 초기화됩니까?

글쎄, 당신은 일반적으로 그 변수로 무언가를하고 싶어합니다. 그러나 그것이 초기화되었는지 어떻게 알 수 있습니까? 정적 부울 변수를 만들 수 있습니다. 그러나 그것은 또한 무언가 (바람직하게는 거짓)로 안정적으로 초기화되어야합니다. 포인터는 어떻습니까? 당신은 차라리 임의의 쓰레기보다 null로 초기화하기를 원합니다. 구조물/레코드는 어떻습니까? 내부에는 다른 데이터 구성원이 있습니다. 모든 것을 기본값으로 초기화하는 것이 합리적입니다. 그러나 단순화를 위해 "0으로 초기화"전략을 사용하는 경우 개별 회원을 검사하고 유형을 확인할 필요가 없습니다. 전체 메모리 영역을 0으로 초기화 할 수 있습니다.

이것은 실제로 기술적 인 요구 사항이 아닙니다. 기본값이 0이 아닌 다른 경우 초기화의 의미는 여전히 제정신으로 간주 될 수 있지만 여전히 결정적입니다. 그러나 그 가치는 무엇이어야합니까? 0이 사용되는 이유를 쉽게 설명 할 수 있지만 (실제로는 약간 임의적으로 들리지만) -1 또는 1024를 설명하는 것은 훨씬 더 어려워 보입니다 (특히 변수가 해당 값을 유지하기에 충분히 크지 않을 수 있음).

그리고 항상 변수를 명시 적으로 초기화 할 수 있습니다.

그리고 당신은 항상 C ++ 표준의 8.5.6 단락을 가지고 있으며, 이는 "정적 저장 시간의 모든 객체는 프로그램 스타트 업에서 제로 시작해야한다"고 말합니다.

자세한 내용은 다른 질문을 참조하십시오.

다른 팁

C ++ 표준의 8.5.6 단락은 다음과 같은 상태를 나타냅니다.

"정적 저장 시간의 모든 객체는 프로그램 스타트 업에서 제로 시작해야합니다."

(표준은 또한 로컬 변수의 초기화가 정의되지 않았다고 말합니다)

왜 표준이 말하지 않는지;) 한 가지 추측은 추가 다운 사이드 없이는 합리적으로 구현하기 쉽다는 것입니다.

Java를 위해 말하기 :

안전 게인이기 때문에 로컬 변수는 액세스하기 전에 초기화되어야합니다. 변수가 명확하게 설정된 경우 컴파일러가 귀하를 확인합니다.

정적 또는 클래스 변수 (객체 유형의)가 초기화됩니다. null, 컴파일러는 컴파일 시간에 초기화되는지 확인할 수 없기 때문에. 비 에니티얼 변수에 액세스하면 프로그램에 실패하는 대신 null.

기본 유형의 변수는 a를 얻을 수 없습니다 null 값, 비 국소 변수는 초기화됩니다 0 또는 false, 폴백으로. 그것은 최상의 솔루션은 아니지만 더 나은 솔루션을 모릅니다. ;-)

따라서 어느 정도까지는 언어 디자이너의 일부에 대한 디자인 결정입니다. 그러나 Java에서 이러한 결정에 대한 가능한 이유는 다음과 같습니다.

  • 정적/멤버 변수의 경우, 당신이 그것들을 무언가로 초기화하려고한다면, Zero는 편리한 값입니다. 어쨌든 카운터와 같은 경우에는 선택했습니다. (b) 내부적으로, 객체 참조의 경우 널을 나타내는 "특수"값에 0이 사용될 수 있습니다.
  • 로컬 변수의 경우, 기본값을 제공하지 않으면 변수를 읽기 전에 프로그래머가 일부 값을 설정하도록하는 규칙이 허용되므로 컴파일러가 특정 오류를 발견 할 수 있습니다.

로컬 변수의 경우, 로컬 변수가 선언 될 수 있다고 생각할 수 있습니다 (바이트 코드/머신 코드 레벨에서는 본질적으로 스택 공간을 할당/스택 포인터 이동을 의미합니다). 그런 다음 특정 코드 경로에서는 실제로 쓰여진/읽지 않습니다. 따라서 기본값이 없으면 해당 경우 기본값을 설정하는 불필요한 작업을 수행하지 않습니다.

그러나 나는 이것들이 어느 정도 설계 결정입니다. 그들은 본질적으로 JVM 구현에 편리 할 가능성이 높고 프로그래머에게 편리한 것 사이의 상충 관계입니다.

C/C ++의 NB, "정적"변수는 Java의 정적 변수와는 다른 것을 의미합니다!

나는 Java에 대해 전혀 모른다. 그리고 나는 그것이 Java의 정적/현지인들과 다르다고 의심한다.

C 및 C ++의 경우, 코드 효과를 돌보고 사랑하는 사람이 통제하는 프로그램에 관한 것입니다. 로컬 변수 초기화 프로그램이 스코프를 입력 할 때마다 추가 코드 실행을 의미합니다. 재앙 일 수있는 자주 호출되는 기능.

이것은 C/C ++에서 "사용하는 것에 대해서만 지불"이라는 개념과 관련이 있습니다.

정적 변수의 경우 코드를 생성하지 않고 초기화를 수행 할 수 있습니다. 객체 파일에는 데이터 세그먼트의 변수의 초기 값이 포함되어 있으며 OS가 실행 가능로로드하면 프로그램이 실행되기 전에이 데이터 세그먼트를로드하고 맵핑합니다.

로컬 변수의 경우 한 번 초기화되지 않기 때문에 코드없이 초기화 할 수있는 방법이 없습니다. 범위를 입력 할 때마다 초기화해야합니다. 또한 그들은 스택에 할당되며, 할당이 발생하면 일반적인 경우 스택의 초기 값은 단순히 이전에 있었던 것입니다 (드문 순간을 제외하고는 스택을 이전보다 더 많이 키 웁니다).

따라서 로컬 변수를 암시 적으로 초기화하려면 컴파일러가 프로그래머가 명시 적으로 명령하지 않고도 코드를 생성해야합니다. 이는 "철학"에 위배됩니다.

내가 아는 한, Java 정보는 프로그램이 정적인지 아닌지에 관계없이 프로그램이 범위에 들어갈 때 항상 초기화됩니다. 그들 사이의 유일한 중요한 차이점은 정적 변수의 범위가 전체 프로그램이라는 것입니다. 그 점을 감안할 때, 행동은 그들 모두에서 일관성이 있습니다.

이것은 단지 추측 일 뿐이지 만 구현하기 쉽고 유용하기 때문에 정적 인 방식 일 수 있습니다.

컴파일러는 모든 변수를 하나의 연속 메모리 영역으로 공동 할 수있는 다음 코드를 방출 할 수 있습니다 (단일 memset() 전화) 전에 지우려면 main() 호출됩니다. 대부분의 경우 해당 형식이 지원되는 경우 운영 체제의 실행 파일 형식의 기능에 의존 할 수도 있습니다. "BSS 섹션 ", 대신 로더에 의해 지워집니다. 이것은 실행 파일의 공간을 절약 할 수 있습니다.

static unsigned char megabyte[1 << 20];

그리고 실행 파일은 메가 바이트로 자라지 않을 것입니다.

로컬 변수의 경우, 이들 중 어느 것도 적용되지 않습니다. 그것들은 "비행 중"(일반적으로 스택에) 할당되며 일반적으로 어쨌든 곧 할당 될 것이기 때문에이를 제거하는 자원 낭비가 될 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top