C++프로그래밍/C 와 C++ 기초실습

배열과 포인터 (문자열)

season97 2024. 9. 18. 13:44

※ C / C++을 이미 알고 있으나 개인적인 공부를 위해 포스팅 하는 글이므로

C++에 대한 구체적인 정보를 담고 있지 않습니다.

 


▶ 배열

int a=10;  //바구니
int b = a;

ㆍ 여태 사용하던 변수들의 [이름]은 바구니의 이름이였다.

 

ㆍ 하지만 배열은 [이름]이 좀 다르게 동작한다.

struct StatInfo
{
	int hp = 0xAAAAAAAA;
	int attack = 0xBBBBBBBB;
	int defence = 0xDDDDDDDD;
};

int main()
{
	//배열의 크기는 상수여야 한다. VC컴파일러 기준
	const int monsterCnt = 10;
	StatInfo monsters[monsterCnt];

	StatInfo Players[10];
//	players = monsters; 이건 안됨. 

	auto WhoAmI = monsters; //이건돼서 확인을 해보면 StatInfo*로 작동하고있다.
}

 

ㆍ players = monsters... 이건 오류가 발생한다.

 

ㆍ 배열의 이름은 곧 배열의 시작 주소이다, 정확히는 시작 위치를 기리키는 TYPE* 포인터

	StatInfo* monster_0 = monsters;
	monster_0->hp = 100;
	monster_0->attack = 10;
	monster_0->defence = 1;

ㆍ monster_0에 monsters의 첫번째 주소를 할당해줬다.

 

ㆍ 다음 주소에 접근하려면 포인터 연산을 기억해보자!

	StatInfo* monster_1 = monsters + 1;
	monster_1->hp = 200;
	monster_1->attack = 20;
	monster_1->defence = 2;

ㆍ 포인터 연산은 정말+1을 하라는게 아니라 다음 주소를 가리키라는 말이였다

 

ㆍ 포인터와 참조는 자유자재로 변환이 가능하다 했으니 참조로도 해보자!

	StatInfo& monster_2 = *(monsters + 2);
	monster_2.hp = 300;
	monster_2.attack = 30;
	monster_2.defence = 3;

ㆍ 잘 된다.

 

ㆍ 주의할건 아래 코드는 완전히 다른 의미 이므로 조심하자

	StatInfo temp = *(monsters + 2);
	temp.hp = 300;
	temp.attack = 30;
	temp.defence = 3;

ㆍ 해당 코드는 3번째 주소의 내용물이 바뀌는게 아니라 그냥 temp만 변화한다. 여태까지 공부한걸 이해했다면 쉽게 이해가 된다. (실제 주소 접근이 아니란 소리)

//배열 초기화 문법 몇가지
int numbers[5] = {}; //빈거로 만들면 기본값인 0으로 댐
//어셈블리까보면 걍 하나하나 접근해서 0으로하고있음, 성능은같다

int numbers1[10] = { 1,2,3,4,5 }; //안한건 0으로초기화

int numbers2[] = { 1,2,3,4,5,6,7,8,9,0,11 }; // 데이터 개수 만큼의 크기에 해당하는 배열로 만들어준다

 

▶ 포인터와 배열은 다른거다. 차이점 (문자열)

const char* test1 = "Hello World";
char test2[] = "Hello World";

ㆍ 두 코드를 어셈블리로 확인해보자. 차이점이 보인다

 

1) const char* test1 = "Hello World";

ㆍ mov로 test라는 바구니에 Hello World를 옮겨주는 작업을 하고있고 유추해 보건데 offset string은 이제 첫번째 주소 뒤에 1바이트 자료형인 char를 하나씩 자리에 맞게 넣어준다는 소리같다.

 

ㆍ .read only data에 Hello World를 박아줬다는 뜻

 

2) char test2[] = "Hello World";

ㆍ 좀 더 복잡한 무언가가 일어나고있다, 주소가 4바이트씩 끊어서 복사되고있다.

 

ㆍ [H] [e] [l] [l] / [o] [] [w] [o] / [r] [l] [d] [\0] /


ㆍ 얘는 별도의 바구니가 만들어 진 것이 아니다!!


ㆍ 포인터는 [주소를 담는 바구니]


ㆍ 배열은 [닭장] 즉, 그 자체로 같은 데이터 끼리 붙어있는 '바구니 모음'


ㆍ 다만 [배열이름] 은 '바구니 모음' 의 [시작 주소] 

 

ㆍ 즉 배열과 배열이름은 다른걸 말한다. 배열 = 배열그자체(전체) 배열이름 = 배열의 시작주소

 

※ 쉽게말해

1) 포인터는 크기가 늘어나도 계속 4or8 크기 고정 (시작주소) (연산을 통해 다음 주소 접근)
2) 배열은 실질적인 크기가 늘어나면 크기도 늘어난다 (배열의 본체 자체는 어마어마하게 클 수도 있는 배열 그 전체를 의미한다)

char test2[] = "Hello World";
char test3[1];
test2 = test3 
//해당 코드는 오류

ㆍ 배열이름은 바구니가 아니라 배열의 첫번째주소이다. 따라서 오류

 

★ 배열을 함수 인자로 넘겨준다면?

void Test(char a[])
{
	a[0] = 'x';
}

int main()
{
	char test2[] = "Hello World";
    Test(test2); // 배열의 시작 주소만 넘긴다
	cout << test2 << endl;
}

ㆍ xello World로 바뀐다.

ㆍ그 이유는 컴파일러가 자동으로 char* 형으로 바꿔주기 때문이다.