의 이름을 해결 :C++ 컴파일러 - 클래스 멤버 컴파일러는이 코드를보고
SomeClass foo;
int x = foo.bar;
을 무엇입니까가 바의 값을 검색에 대해 진행 과정? 나는. 그것은 클래스 정의를 나타내는 데이터 구조를 보았는가? 그렇다면이 데이터 구조는 컴파일 타임이나 런타임에 생성됩니까?
의 이름을 해결 :C++ 컴파일러 - 클래스 멤버 컴파일러는이 코드를보고
SomeClass foo;
int x = foo.bar;
을 무엇입니까가 바의 값을 검색에 대해 진행 과정? 나는. 그것은 클래스 정의를 나타내는 데이터 구조를 보았는가? 그렇다면이 데이터 구조는 컴파일 타임이나 런타임에 생성됩니까?
프로세스에 할당이 시작됩니다. 이 정의에 기초하여, SomeClass
의 필드 및 SomeClass
의 방법에 대한 코드의 위치의 종류를 포함하는 내부 구조를 구축한다. 당신이 을 쓸 때
컴파일러는 SomeClass
의 생성자에 해당하는 코드를 찾아 내고, 그 코드를 호출하는 기계 명령어를 생성합니다. 다음 줄에는 int x = foo.bar
이라고 쓰십시오. 여기서 컴파일러는 int
에 대한 스택 공간을 할당하는 컴퓨터 명령어를 작성한 다음 데이터 구조를 SomeClass
으로 봅니다. 해당 데이터 구조는 foo
개체의 시작 부분에서 바이트 단위로 오프셋을 bar
으로 알려줍니다. 그런 다음 컴파일러는 bar
에 해당하는 바이트를 x
의 메모리에 복사하는 컴퓨터 코드를 씁니다. 이 기계 코드는 모두 실행 파일에 기록됩니다. 컴파일이 완료되면
일반적으로, 데이터 SomeClass
를 나타내는 구조와 다른 정의는 버려된다. 당신이 남긴 것은 단지 일련의 기계 지침 일뿐입니다. 이 지침은 실제로 이 실행될 때을 실행하면 SomeClass
의 생성자와 foo.bar
을 x
으로 복사하는 코드가 개체 구조에 대한 명확한 지식없이 CPU에 의해 실행됩니다.
이것은 일반적인 경우입니다. 이 디버거에서 및 최적화에 대한 귀하의 코드를 실행하면에 대한 특별한 경우가 있지만, 이것은 일반적으로 발생하는입니다.
컴파일러는 foo
의 주소가 있습니다. 해당 주소에는 멤버 변수 (sizeof(SomeClass)
)를위한 충분한 공간이 있으며 여기에는 약간의 패딩이 포함됩니다.
그것은 줄은 클래스의 일부 위치 (일반적으로이 선언 된 순서, 플러스 상속과 같은 몇 가지 다른 마법)에있다 '것을 알고 있으며, 오프셋로 이동합니다. 이다
: 컴파일러가 SomeClass
에 대한 정의를 볼 때
struct SomeClass
{
short s;
float f;
int bar;
char *c;
}
// pseudo-code:
&SomeClass.bar == (&SomeClass) + sizeof(short) + sizeof(float);
, 그것은 데이터를 가져오고 x
"컴파일러에는 foo의 주소가 있습니다."- 일반적으로 foo는 자동 변수이므로 일부 스택 포인터에 비해 foo의 오프셋이 있습니다. –
아직 주소는 무엇입니까 :) – GManNickG
이것은 기술적으로 부정확합니다. 컴파일러는 (보통) foo.bar를 x에 할당하지 않습니다. 컴파일러는 foo.bar를 런타임에 x에 할당하는 기계 명령어를 생성합니다. –
당신은 컴파일시 모든 클래스 (설명을 단순화하기 위해) 구조체에 전원이 켜져 있는지 생각해야한다, 그래서 당신은
class Foo
{
int x, y, z;
char bar[10];
... etc ...
}
이있는 경우 그들은이 경우, 지정된 크기를 가지는 구조체로 전환된다 4 * 3 + 10 바이트. 그런 다음 정렬에 따라 더 편리한 방법으로 정렬합니다. 예를 들어 오프셋 4에서 속성 y를 찾을 수 있으며 주소 8에서 z를 찾을 수 있습니다.
다음은 쉽습니다. 할당에 관련된 클래스의 주소에 4를 추가하면 y 주소 등을 얻을 수 있습니다.
4 대신에 sizeof (int)를 사용하십시오. 'int'는 꼭 4 바이트는 아닙니다. – GManNickG
컴파일러는 컴파일 할 때만 이러한 클래스 메타 데이터를 저장합니다. 귀하의 첫 번째 질문, 어떻게 막대의 가치를 검색합니까, 실제로는 상당히 복잡합니다. foo 객체의 bar의 오프셋을 계산 한 다음 그 위치에서 메모리를 읽는 것으로 생각할 수 있습니다. 그러나 x가 실제로 어떻게 사용되는지에 따라 훨씬 다른 것을 할 수 있습니다. 일부 상황에서는 'x'가 컴파일 된 코드에 전혀 표시되지 않을 수도 있습니다.
컴파일러에는 컴파일러가 SomeClass의 각 멤버에 액세스하는 방법을 알려주는 데이터 구조가 있습니다. 단순한 경우에는 그냥 오프셋이 될 것이지만, 사소한 상속을받는다면 더 많은 것이있을 수 있습니다.
식을 처리하기 위해 컴파일러는이 내부 데이터를 참조하여 (결국) 적절한 컴퓨터 코드를 내 보냅니다. 런타임에이 구조체는 버려 질 것이고 나머지는 foo의 주소부터 시작하여 필요한 것을 수행하기 위해 생성 된 코드입니다. 그러나 막대에 대한 포인터를 갖는 포인터가있는 경우 bar 멤버에 액세스하는 방법에 대한 세부 정보가 포인터 값에 캡슐화됩니다 (아마도 오프셋, 어쩌면 좀 더 복잡한).
내 자신을 포함하여 아래의 모든 대답은 "일반적인 컴파일러에서 정상적으로 수행되어야합니다"라고 가정해야합니다. C++의 구현과 관련이있는 거의 모든 것과 마찬가지로, "컴파일러 작성자는 전적으로 프로그램에 대한 올바른 대답이 나오는 한 언제든지 할 수 있습니다."라고 대답했습니다. 아래에서 설명하는 것은 악의적 인 최적화를 적용하기 전에 가장 분명하고 합리적인 방법입니다. –