• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

수업 중 궁금한점이 있습니다.

23.02.17 14:01 작성 조회수 241

1

public:
	char* m_data = nullptr; 
	int m_length = 0;
public:
	MyString(const char* source = "") 

...


};
int main()
{
	MyString hello("Hello");

	cout << (int*)hello.m_data << endl;

수업중 코드의 일부분인데 m_data라는 문자형 포인터 변수를 동적할당해서 문자열을 받는 코드입니다.

 

메인함수에서 동적할당된 m_data의 주소를 찍어보려고

교수님께서 (int*) 를 써서 주소를 정수화 했

질문:(int) 와 (int*) 의 차이점이 무엇인가요?

 

 

다른 강의시간에 비슷한 개념을 언급해주셨는데 어느 강의에서 언급하셨는지 기억이 안나네요.

 

 

답변 1

답변을 작성해보세요.

0

강민철님의 프로필

강민철

2023.02.18

제시해주신 예제에서 int를 썼을 때와 int *를 사용했을 때의 차이를 물어보시는 듯 한데,

있는 그대로 어떤 데이터 형식으로 변환되느냐에 대한 차이만 있습니다.

(int)는 특정 변수나 값을 int 타입으로 변환하고,

반면 (int*)은 특정 변수나 값을 int 포인터 타입으로 변환합니다.

제시해주신 코드에서 (int*)hello.m_data는 MyString 클래스의 m_data 멤버 변수가

문자형(char) 포인터이지만, 이를 int 포인터로 캐스팅하여 그 주소를 출력하라는 뜻입니다.

단순히 메모리 주소를 출력하기 위해 정수형 포인터로 변환해주신 것입니다.

seungmin38님의 프로필

seungmin38

질문자

2023.02.18

그렇다면 제가 이해한게 맞는지 확인 한번만 부탁드립니다.

질문은 char 포인터 변수였다면 이번엔 정수형 포인터 인데요,

int main()
{
	int fibonacci[] = { 82, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };

	int* m_data = new int[sizeof(fibonacci)/sizeof(int)];
	int x = 0;
	for (auto& i : fibonacci)
	{
		m_data[x] = fibonacci[x];
		x++;
	}

	cout <<"m_data " << m_data << endl; //m_data 000001F1EFC174E0
	cout <<"(int)m_data " <<(int)m_data << endl;//(int)m_data -272534304
	cout <<"(int*)m_data " <<(int*)m_data << endl;//(int*)m_data 000001F1EFC174E0

	delete[] m_data;

	return 0;
}


cout <<"m_data " << m_data 배열 첫번째 인덱스의 주소 출력

cout <<"(int)m_data " <<(int)m_data << endl; 주소값을 그냥 int 값으로 변환해서 표현,단 이건 주소의 개념이 아니고 주소로 나타난 값을 단지 int형태로 표현

cout <<"(int*)m_data " <<(int*)m_data << endl; 주소를 정수형 주소로 표현(그런데 원래 정수형 포인터라서 주소값이 정수형으로 표현되어 있으니 첫번째 케이스와 같은 값이 출력)

 

 

제가 이해한게 맞나요? 2번째에서 정수형 주소값을 int형태로 바꾸면 왜 -2753.... 이런 값이 나오는지는 이해가 안가네요.

요지는 포인터 변수 안에는 주소값이 들어있고 이를 정수형으로 나타내고 싶으면 (int)가 아닌주소에 해당되는거니 (int*) 이렇게 *를 붙여줘야 주소의 형태가 나온다는것이고 (int)를 하게되면 정수형 주소값을 또 정수형해서? 이상한 쓰레기값이 (왜 이렇게 되는지는 모르겠지만) 나온다는거죠?

강민철님의 프로필

강민철

2023.02.18

맞습니다.

그리고 두 번째는 int 형으로 저장하기에는 값이 너무 커져서 생기는 현상입니다.

가령 다른 컴파일러로 컴파일하면 아래와 같이 나옵니다.

error: cast from pointer to smaller type 'int' loses information
        cout <<"(int)m_data " <<(int)m_data << endl;//(int)m_data -272534304
seungmin38님의 프로필

seungmin38

질문자

2023.02.19

마지막으로 그러면 한번만 더 물어보겠습니다 ㅠ

 

        cout <<"m_data " << m_data << endl; 
	cout <<"(char)m_data " <<(char)m_data << endl;
	cout <<"(char*)m_data " <<(char*)m_data << endl;
	cout << "(char)*m_data " << (char)*m_data << endl;

m_data 0000020FC4587910

(char)m_data 

(char*)m_data R

(char)*m_data R

==================

이렇게 값이 나오는데

1.

cout <<"(char)m_data " <<(char)m_data << endl;//(char)m_data  

이 값은 실행할때마다 값이 랜덤으로 바뀌는데, 이유가 뭔가요?

2.

cout <<"(char*)m_data " <<(char*)m_data << endl;//(char*)m_data R

(char*)을 하게되면 첫번째 인덱스의 메모리 주소를 문자형으로 나타낸다는 뜻인데

어째서 출력값은 메모리 주소에 저장되어 있는 값의 아스키코드상 char값에 해당하는 82가 나온건지 궁금합니다. char* 에서 는 주소를 표현할때의 의미로 쓰이는건데 출력값을 보면 *가 de-referencing의 의미로 쓰이는것처럼 보이거든요.

오히려 세번째 (char)*m_data R의 경우는 주소값 앞에 *를 붙였기에 de-referencing 의미로 쓰였고 그래서 82를 가리키며 82를 char로 변환하였으니 R이 출력되었다는것이 논리적으로 납득이 갑니다.

 

 

추가적으로 원질문에서 코드를 변형시켜서 실행해보면

MyString hello("Hello");

	cout << hello.m_data << endl;
	cout << (int*)hello.m_data << endl;
	cout << (char)hello.m_data << endl;
        cout << (char*)hello.m_data << endl;

Hello

00000204AC98C680

€

Hello

========================

이렇게 결과값이 나오는데

3.

cout << (char)hello.m_data << endl;

이 부분의 값이 위에서와 비슷하게 랜덤하게 값이 계속 바뀝니다. 출력이 아무것도 안되거나 P가 나오거나 ' 이 나오거나 계속 바뀝니다. 1번질문은 정수형 포인터 주소값을 char로 바꿨다면 이번 케이스는 char 포인터 주소를 char로 바꾼것입니다.

 

 

강민철님의 프로필

강민철

2023.02.19

원래 메모리 주소는 실행할 때마다 값이 바뀝니다.

프로그램의 적재된 위치는 언제든 바뀔 수 있기 때문입니다.

 

seungmin38님의 프로필

seungmin38

질문자

2023.02.19

아 잠깐 망각했습니다. 랜덤하게 바뀔 수 밖에 없군요.

 

그럼

int fibonacci[] = { 82, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };

	int* m_data = new int[sizeof(fibonacci)/sizeof(int)];
	int x = 0;
	for (auto& i : fibonacci)
	{
		m_data[x] = fibonacci[x];
		x++;
	}
cout <<"(char*)m_data " <<(char*)m_data << endl;

cout << "(char)*m_data " << (char)*m_data << endl;

이 두 코드가 각각 고정적으로 R을 출력하는 이유가 뭔가요?

cout <<"(char*)m_data " <<(char*)m_data << endl;

이건 어떤 이유로 R이 나오는지 모르겠고

cout << "(char)*m_data " << (char)*m_data << endl;

이건 m_data가 배열의 첫번째 인덱스의 메모리주소를 나타내고

그 앞에 *를 붙여서 *m_data라는건 첫번째 인덱스의 메모리 주소 안의 값 즉 82를 나타내며

정수값인 82를 (char)로 변환하여 R이 나왔다 라고 이해했는데 제가 이해한게 맞나요?

강민철님의 프로필

강민철

2023.02.19

네 맞습니다

seungmin38님의 프로필

seungmin38

질문자

2023.02.19

cout <<"(char*)m_data " <<(char*)m_data << endl;

이 코드는 그럼 왜 R인가요?

주소가 예를 들어 0000018953B67900 라고 나왔는데

이걸 문자형 주소로 변환하면 단 한글자 R로 변환이 되는 과정이 궁금합니다.

seungmin38님의 프로필

seungmin38

질문자

2023.02.19

좀 당황스러운게 3번을 물어봤는데 계속 이것만 대답 안해주시고 나머지 질문만 답변해주셔서
의도치않게 계속 여쭙게 되었습니다. 제가 안찾아보고 그냥 계속 질문하는게 아닙니다..귀찮게 하려는 의도가 아니라 햇갈려서 그런겁니다.기본이라고 하셨지만 햇갈리는 순간 제겐 기본적인게 아니게 되버리는걸요..

 

 

(char*) 와 (int*)는 둘다 기존 주소를 문자형 포인터 타입 or 정수형 포인터 타입 으로 형 변환하는것

이라고 처음 답변에서 민철님께서 써주셨잖아요.

 

" 해당 주소를 문자형 포인터 타입으로 형 변환 " 이라는 문장이

"해당 주소에 들어있는 값을 문자형으로 변환" <--- 이 문장과 동일한 문장인가요?

두 문장은 뜻이 다른데 값은 같게 나오니까 같은 뜻인가 싶어서 햇갈립니다.

언급하신 강의회차에선 저 부분에 대한 언급이 없어요

 

 

강민철님의 프로필

강민철

2023.02.19

질문 개수/종류에 혼동이 있었던 것 같습니다.

혼동을 드려 죄송합니다.

(브라우저 새로고침을 하고 있지 않아 새 질문들이 추가되고 있는줄 모르고 있었네요..)

그냥 질문해주신 종류 중 나머지들에 대하여 하나씩 다 답변드리겠습니다.

3번 질문은 아래와 같았습니다.

 

cout << (char)hello.m_data << endl;

이 부분의 값이 위에서와 비슷하게 랜덤하게 값이 계속 바뀝니다.

출력이 아무것도 안되거나 P가 나오거나 ' 이 나오거나 계속 바뀝니다.

 

사실 이는 int 형을 토대로 질문해주신 것과 같은 질문입니다.

 

... 중략

(int)를 하게되면 정수형 주소값을 또 정수형해서? 이상한 쓰레기값이 (왜 이렇게 되는지는 모르겠지만) 나온다는거죠?

 

int에 비해 값이 커지면 문제가 발생할 수 있다고 말씀드렸습니다.

그런데 char는 그보다 더 크기가 작습니다.

Visual Studio에서는 해당 에러를 무시하거나 어떻게든 출력할 수는 있어도,

가령 다른 컴파일러로 작동시키면 아래와 같이 컴파일되지 않습니다.

test.cc:20:27: error: cast from pointer to smaller type 'char' loses information
cout <<"(char)m_data " <<(char)m_data << endl;
^~~~~~~~~~~~

그리고 3번 질문과 별개로 다른 질문들이 있는 것 같은데

 

cout <<"(char*)m_data " <<(char*)m_data << endl;

이 코드는 그럼 왜 R인가요?

 

이 부분은

정수값인 82를 (char)로 변환하여 R이 나왔다 라고 이해했는데 제가 이해한게 맞나요?

라는 부분에 대해 맞다고 말씀 드린 것입니다.

 

"해당 주소를 문자형 포인터 타입으로 형 변환 " 이라는 문장이

"해당 주소에 들어있는 값을 문자형으로 변환" <--- 이 문장과 동일한 문장인가요?

(char*)m_datam_data라는 포인터 변수를 char 형식의 포인터 변수로 캐스팅한 것입니다.

이는 m_data가 가리키는 메모리 주소를 char 형식의 포인터 변수로 취급하여

해당 주소를 문자열 형식으로 표시할 수 있도록 합니다.

반면에, (char)*m_datam_data가 가리키는 메모리 주소에 저장된 값을 char 형식으로 변환한 것입니다.

이는 포인터 변수가 가리키는 메모리 주소에 저장된 값을 문자 형식으로 처리하는 데 사용됩니다.

따라서 의미적으로는 이 두 개의 표현은 다른 의미를 가집니다.

(char*)m_data포인터 변수char 형식의 포인터로 캐스팅하는 것이고,

(char)*m_data포인터가 가리키는 값char 형식으로 변환하는 것입니다.

두 표현이 동일한 결과를 나타내는 상황은 그냥 특이 케이스라고 보시면 되는데,

m_data가 가리키는 메모리 주소에 저장된 값이 문자열 형식으로 해석 가능한 상황에서는 같은 결과가 나올 수는 있씁니다.

강민철님의 프로필

강민철

2023.02.19

추가질문이 있으시다면 더 댓글달아주시기 바랍니다

seungmin38님의 프로필

seungmin38

질문자

2023.02.19

아 제가 햇갈리게 말했네요 3번 질문이 3번째 항목 질문이 아니라

cout <<"(char*)m_data " <<(char*)m_data << endl;

이 코드는 그럼 왜 R인가요?

 

이 질문을 "세번 했는데 답변을 못들었다" 를 말한거였습니다.

그 위의 모든 부분은 다 이전에 답변 주실때 이해했습니다.

 

제가 궁금했던건

```

"해당 주소를 문자형 포인터 타입으로 형 변환 " 이라는 문장이

"해당 주소에 들어있는 값을 문자형으로 변환" <--- 이 문장과 동일한 문장인가요?

```

오직 이 부분이었습니다.

각설하고 다시 질문을 이어가면,

주소를 문자형 포인터 타입으로 바꾸는것과 (char*)m_data

해당주소의 value값을 문자형으로 변환하는것 (char)*m_data

이 같다면 (char*)m_data 과 (char)*m_data 도 같다고 생각해야하나요?

엄연히 뜻이 다른거 같은데 왜 같은지 모르겠는데 그냥 받아들여야 하는건가 싶네요.

자야되는데 납득이 안되니까 찝찝해서 계속 질문하게 되네요 죄송합니다..

강민철님의 프로필

강민철

2023.02.19

(char*)m_data 과 (char)*m_data 예제와

관련하여 헷갈리셨던 점을 최대한 자세하게 이전 답변에 추가로 달아드렸습니다.

seungmin38님의 프로필

seungmin38

질문자

2023.02.19

아 이해 했습니다.그런데

```

이는 m_data가 가리키는 메모리 주소를 char 형식의 포인터 변수로 취급하여

해당 주소를 문자열 형식으로 표시할 수 있도록 합니다.

```

이런 이유로 인해

0000016171867A60 이렇게 나오는 주소값을 문자열 형식으로 표시하였더니 우연하게 첫번째 인덱스안에 들어있는 값을 문자형으로 바꾼것과 일치한다는게 신기하네요.

 

대략적인건 이해했습니다.자세한 답변 감사드립니다 좋은 주말 보내세요