[c++] 구조체, 포인터 복습

struct 구조체

전역 선언

struct MyStruct{
    ...
} m1, m2;

int main(){
    ...
}

지역 선언 및 초기화

int main(){
    struct MyStruct m1;
    struct MyStruct m1 = {...};
}
  • cpp에서는 구조체 명시를 생략하고 선언 및 초기화가 가능하다.
int main(){
    MyStruct m1;
    ...
}

포인터와 변수

  • 일반적인 모든 변수는 생성시 stack 메모리에 저장된다.
  • heap 메모리에 접근하기위해 포인터 변수가 필요하다.

c언어

  • malloc을 사용해 동적 배열을 heap에 생성

c++

  • new 연산자를 사용해 heap에 배열을 생성

c언어 예제

#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
	int* p;
		
	p = (int*)malloc(3 * sizeof(int));
	p[0] = 1; p[1] = 2; p[2] = 3;

	for (int i = 0; i < 3; i++) {
		cout << p[i] << endl;
	}
    free(p); //memory deallocation
	return 0;
}

malloc(size_t)는 void*(제너릭 포인터)를 반환한다. 즉 힙 메모리의 해당 위치 주소를 똑같이 반환하는데, (int*)처럼 형변환을 통하여 해당 주소를 받은 포인터가 int 타입의 데이터를 저장하거나 읽을 수 있게 된다!

cpp 예제

#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
	int* p;
		
	p = new int[3];
	p[0] = 1; p[1] = 2; p[2] = 3;

	for (int i = 0; i < 3; i++) {
		cout << p[i] << endl;
	}

    delete [] p; //memory deallocation

	return 0;
}

memory deallocation

  • 메모리 할당 해제
  • 소규모의 프로젝트, 실습 등에서는 어차피 프로그램이 종료되니 굳이 할 필요는 없다. 프로그램이 종료되면 자동으로 힙 메모리가 해제되니깐,
  • 다만, 실시간 운영중인 서버나 대규모 프로젝트의 경우 힙메모리의 해제를 제대로 해주지 않으면, 메모리 누수가 일어날 것이다.

최신 컴파일러에서의 포인터 변수의 size

#include <iostream>
using namespace std;
struct MyStruct
{
	int a;
	int b;
};
int main() {
	int* p1;
	float* p2;
	double* p3;
	char* p4;
	MyStruct* p5;

	cout << sizeof(p1) << endl;
	cout << sizeof(p2) << endl;
	cout << sizeof(p3) << endl;
	cout << sizeof(p4) << endl;
	cout << sizeof(p5) << endl;
	
	return 0;
}
8
8
8
8
8 

전부 8bytes가 나온다. 왜그럴까.. 알아보니 64비트 시스템에서 컴파일되고 실행되기 때문이다. 64비트 환경에서는 모든 포인터가 8바이트즉 64비트로 표현되기 때문.

데이터 타입과 무관하게 포인터 변수는 힙 공간 크기에 의존하기 때문에 시스템 아키텍쳐를 따라가게 된다.

  • 그렇다면 32비트 시스템에선? 포인터 변수의 크기는 4바이트, 32비트가 될것이다!