3. 복합 데이터형(8) - 포인터(문자열, char 주소, new 구조체)

WanJu Kim·2022년 10월 19일
0

C++

목록 보기
14/81

포인터와 문자열

문자열을 포인터와 연관 시키면 조금 복잡해진다.

	char flower[20] = "rose";
    cout << flower << "s are red" << endl;

실행 결과.

배열 이름은 첫 번째 원소의 주소이다. 그래서 널 문자를 만날 때까지 출력이 되었다. 그럼 오른쪽에 "s are red"는 뭘까? 문자열 출력에 일관성이 있으려면 큰 따옴표로 둘러싸인 문자열도 반드시 주소여야 한다. 배열과 마찬가지로, 문자열도 문자열의 첫 번째 문자의 주소를 나타낸다. 이걸 알면 char형의 포인터도 만들 수 있다.

	const char* bird = "wren";

이렇게 하면 포인터 변수 bird에 "wren"의 주소가 저장된 것이다. '문자열 상수'이기 때문에 const를 썼다.

char*이 안되는 이유?!

위의 예시에는 const char*을 이용했는데 단순히 char*로 하면 안된다.

이는 해결 방법이 2가지가 있는데, 첫 번째는 위에서처럼 const char*를 이용하는 것이고, 두 번째 방법은 프로젝트 → 속성 → C/C++ → 언어 → 준수 모드를 '아니오'로 해주는 것이다. 구버전에는 준수 모드가 자동으로 아니오로 돼있어서 표준 문법을 조금 무시(?)할 수 있었는데 요즘 버전은 준수 모드가 자동으로 '예'로 돼있어서 엄격하다고 한다.

근데 왜 안될까? 다른 자료형들과 달리, 문자열은 한번 정해지면 bird[3] 뭐 이런 식으로 변경이 불가능하다. 그래서 문법상 const가 맞다. 난 최신 버전에 따라서 그냥 const char*를 사용할란다.

char의 주소

char는 다른 자료형과 같은 방법으로 주소를 확인할 수 없다. 다음 코드를 보자.

	char* p = new char[4];
	char c = 'a';
	char* pC = &c;
	cout << "대입 전 주소들 c : " << &c << ", p : " << p << ", pC : " << pC << endl;
	p = pC;
	cout << "대입 후 주소들 c : " << &c << ", p : " << p << ", pC : " << pC << endl;

실행 결과.

이상하게 나온다. 왤까?
찾아보니 ostream을 사용할 때 char*를 주소가 아니라 문자열로 인식해서 널문자가 나올 때까지 출력한다 어쩌구 저쩌구 해서 저렇댄다... 이럴땐 강제 형변환을 해주면 된다.

	char* p = new char[4];
	char c = 'a';
	char* pC = &c;
	cout << "대입 전 주소들 c : " << (void*)&c << ", p : " << (void*)p << ", pC : " << (void*)pC << endl;
	p = pC;
	cout << "대입 후 주소들 c : " << (void*)&c << ", p : " << (void*)p << ", pC : " << (void*)pC << endl;

실행 결과.

잘 나온다~

new를 사용한 동적 구조체의 생성

new를 사용해서 구조체도 생성할 수 있다.

	struct inflatable
	{
		char name[20];
		float volume;
		double price;
	};

	inflatable* ps = new inflatable;
	ps->price = 20.0;

	cout << "ps->volume = " << ps->volume << endl;
	cout << "(*ps).volume = " << (*ps).volume << endl;

	delete ps;

여기서 자료형은 struct이 아니라 구조체 이름을 사용한다. 동적 구조체는 포인터의 가리킨다는 의미를 받아들여 화살표 모양(->)을 쓴다. 보기 매우 불편한 구문이지만, (*ps).volume이랑 ps->volume은 같다. 가독성을 위해 나라면 후자를 사용하겠다.

new를 사용해서 동적 구조체를 배열로 만들고 싶다면, 배열처럼 [숫자]만 붙이면 된다. delete는 항상 유의하자.

inflatable* ps = new inflatable[5];
delete[] ps;
profile
Question, Think, Select

0개의 댓글