본문 바로가기

Programming/C++ 2

[C++ 실습] 4장-08. 포인터, 배열, 포인터 연산

반응형
#include <iostream>
using namespace std;
int main()
{
	double wages[3] = { 10000.0, 20000.0, 30000.0 };
	short stacks[3] = { 3,2,1 };

	//배열의 주소를 알아내는 두 가지 방법
	double* pw = wages; //배열 이름 = 첫번째 원소의 주소
	short* ps = &stacks[0]; //배열 원소에 주소 연산자 사용

	cout << "pw = " << pw << ", pw= " << *pw << endl;
	pw = pw + 1;
	cout << "pw 포인터에 1을 더함: " << endl;
	cout << "pw= " << pw << ", *pw = " << *pw << endl << endl;

	cout << "ps= " << ps << ", *ps= " << *ps << "\n";
	ps = ps + 1;
	cout << "ps 포인터에 1을 더함 : " << endl;
	cout << "ps= " << ps << ", *ps= " << *ps << "\n\n";

	cout << "배열 표기로 두 원소에 접근 \n";
	cout << "stacks[0] = " << stacks[0] << ", stacks[1]= " << stacks[1] << endl;

	cout << "포인터 표기로 두 원소에 접근 \n";
	cout << "*stacks= " << *stacks << ", *(stacks+1)= " << *(stacks + 1) << endl << endl;

	cout << sizeof(wages) << " = wages 배열의 크기 \n";
	cout << sizeof(pw) << " = pw 포인터의 크기\n";

	return 0;
}

-> double* pw = wages;  : wages=&wages[0]; 배열의 이름은 배열의 첫번째 원소의 주소를 의미

 

cout << "pw = " << pw << ", pw= " << *pw << endl;
pw = pw + 1;
cout << "pw 포인터에 1을 더함: " << endl;
cout << "pw= " << pw << ", *pw = " << *pw << endl << endl;

 

: pw: 8바이트 증가 / *pw : 다음 원소

 

cout << "ps= " << ps << ", *ps= " << *ps << "\n";
ps = ps + 1;
cout << "ps 포인터에 1을 더함 : " << endl;
cout << "ps= " << ps << ", *ps= " << *ps << "\n\n";

 

: ps: 2바이트 증가 / *ps : 다음 원소

 

cout << "배열 표기로 두 원소에 접근 \n";
cout << "stacks[0] = " << stacks[0] << ", stacks[1]= " << stacks[1] << endl;

cout << "포인터 표기로 두 원소에 접근 \n";
cout << "*stacks= " << *stacks << ", *(stacks+1)= " << *(stacks + 1) << endl << endl;

 

: 배열[0] = * pointer_name / 배열[1] = *(pointer_name +1)

 

cout << sizeof(wages) << " = wages 배열의 크기 \n";
cout << sizeof(pw) << " = pw 포인터의 크기\n";

 

: 24= 배열의 크기 / 4=포인터의 크기[배열의 지시하더라도 항상 같은 크기이다]

 

  • arrayname[i] = *(arrayname +i)
  • pointername[i] = *(pointername +i)

 

  • 배열의 주소
    • 배열의 이름 vs 배열의 주소
      • 배열의 이름 : 배열의 첫 번째 원소의 주소
      • 배열의 주소 : 전체 배열의 주소
    • short tell[10]; : 20바이트 배열
    • &tell : 전체 배열의 주소
    • short(*)20 : short형 20바이트 배열
    • short(*pas)[20] = &tell : pas는 20바이트 배열을 가리킨다.
    • short *pas[20] : pas는 short를 가리키는 20개의 포인터 배열

포인터와 문자열

// ptrstr.cpp -- 문자열을 지시하는 포인터의 사용
#define _CRT_SECURE_NO_WARNINGS 

#include <iostream>
#include <cstring>				// strlen(), strcpy()를 선언

int main()
{
	using namespace std;
	char animal[20] = "bear";		// animal에 bear가 들어 있다
	const char* bird = "wren";		// bird에 문자열의 주소가 들어 있다
	char* ps;				// 초기화되지 않았다

	cout << animal << " and ";		// bear를 출력한다
	cout << bird << "\n";			// wren을 출력한다
	// cout << ps << "\n";          	// 쓰레기 출력하거나 먹통이 될 수도 있다

	cout << "동물의 종류를 입력하십시오: ";
	cin >> animal;				// 입력이 20문자 이내여야 한다
	// cin >> ps; 절대로 해서는 안 될 엄청난 실수이다
	// ps가 대입된 공간을 지시하고 있지 않다

	ps = animal;				// ps를 문자열을 지시하도록 설정한다
	cout << ps << "s!\n";			// 맞다, animal을 사용하는 것과 동등
	cout << "strcpy() 사용 전:\n";
	cout << (int*)animal << ": " << animal << endl;
	cout << (int*)ps << ": " << ps << endl;

	ps = new char[strlen(animal) + 1];	// 새 메모리를 할당한다
	strcpy(ps, animal);			// 새 메모리에 문자열을 복사한다
	cout << "strcpy() 사용 후:\n";
	cout << (int*)animal << ": " << animal << endl;
	cout << (int*)ps << ": " << ps << endl;
	delete[] ps;
	return 0;
}

-> strcpy 함수는 2017부터 unsafe 함수로 사용불가

-> strcpy_s 함수는 ( A, 버퍼의 크기, B)꼴로 버퍼의 크기를 정해줘야 한다.

-> strcpy 함수를 사용하려면 #define _CRT_SECURE_NO_WARNINGS을 해줘야 한다.

 

  • C스타일 문자열과 cstring 라이브러리 사용
    • 문자열을 배열에 저장하는 함수
      • strcpy()
      • strncpy()
        • 세 번째 매개변수에 복사할 최대 문자수 지정
        • 마지막 문자열엔 \0을 추가해야한다.
    • 연산자는 배열을 초기화 할때만 사용한다.
  • C++의 string형을 사용하는 게 바람직하다.

#include <iostream>
using namespace std;

struct inflatable //구조체 템플릿
{
	char name[20];
	float volume;
	double price;
};


int main()
{
	inflatable* ps = new inflatable; //구조체를 위한 메모리 대입
	cout << "모형풍선의 이름을 입력하십시오 : ";
	cin.get(ps->name, 20); //멤버에 접근하는 제2 방법; 간접 멤버 접근연산자 사용
	cout << "부피를 세제곱 피트 단위로 입력하십시오.: ";
	cin >> (*ps).volume; //멤버에 접근하는 제1 방법 : 멤버 접근 연산자 사용
	cout << "가격을 달러 단위로 입력하십시오: $";
	cin >> ps->price;

	cout << "이름: " << (*ps).name << endl; //제 1 방법
	cout << "부피: " << ps->volume << " cubic feet\n"; //제2 방법
	cout << "가격: $" << ps->price << endl; //제2 방법

	delete ps; //구조체가 사용한 메모리 해제


	return 0;
}

-> 구조체 생성 -> 구조체 멤버에 접근 (접근방법 2가지 -> 구조체변수.멤버변수 / 구조체포인터->멤버변수)

 

구조체와 포인터

struct things
{
	int good;
    int bad;
 };
 things grubnose={3, 453};
 things* pt=&grubnose;

 

 


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;

char* getname(void); //함수원형
int main()
{
	char* name; //포인터를 만들지만 메모리는 대입하지 않는다.

	name = getname(); //문자열의 주소를 name에 대입한다
	cout << (int*)name << ": " << name << "\n";
	delete[] name; //메모리 해제

	name = getname(); //해제한 메모리 사용
	cout << (int*)name << ": " << name << "\n";
	delete[] name; //메모리 다시 해제

	
	return 0; 
	
	
}

char* getname() //새 문자열을 가리키는 포인터 리턴하는 함수
{
	char temp[80]; //임시 배열
	cout << "이름을 입력하십시오: ";
	cin >> temp;
	char* pn = new char[strlen(temp) + 1]; //널 문자 포함해 +1 크기
	strcpy(pn, temp); //문자열을 더 작은 공간을 복사한다.

	return pn; //함수가 종료될 때 임시 배열인 temp은 소멸
}

  • 대입하는 방법에 따른 메모리 분류
    • 자동공간
      • 호출 -> 종료
      • 스택에 저장
      • LIFO
    • 정적공간
      • 실행되는 동안 지속
      • 외부에서 변수 선언
      • static 변수 선언
    • 동적공간
      • 분리된 메모리
      • 힙에 저장
      • delete 안하면 메모리 누수

 

반응형