[따배씨++]Chapter6-1. 배열, 포인터, 참조

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모님의 홍정모의 따라하며 배우는 C++ 강의를 듣고 정리한 내용입니다.
공부하는 식빵맘 님의 블로그를 참고했습니다.


🚆 Array

Array 선언

int arr1[5] = {}; // OK

const int a = 5;
int arr2[a] = {}; // OK

int b = 5;
int arr3[b] = {}; // error

int num = 0;
cin >> num;
int arr4[num] = {}; // error



const int num_students = 20;
int students_scores[num_students] = {0, 1};

cout << *students_scores << endl;	// 0
cout << students_scores << endl;	// &students_scores[0]
cout << &students_scores << endl;	// &students_scores[0]
cout << &students_scores[0] << endl;	// &students_scores[0]
cout << &students_scores[1] << endl;	// &students_scores[0] + 4 bytes
  • size는 컴파일 타임에 결정 → 정적 배열(static array)
  • array의 이름은 “포인터” 역할 (첫 번째 원소의 주소)


Enum과 함께 쓰기

enum StudentName
{
	JackJack, // 0
	DASH, // 1
	VIOLET, // 2
	NUM_STUDENTS, // 3
};

int main()
{
	int my_array[NUM_STUDENTS];

	my_array[JackJack] = 1;
	my_array[DASH] = 100;

	return 0;
}


함수 파라미터로 넘어갈 때는 포인터

void doSomething(int students_scores[20])
{
    cout << sizeof(students_scores) << endl; // 4
}
  • 파라미터로 넘어갈 때는 그냥 포인터로 넘어감 (주소만 복사해서)
  • sizeof() 찍어보면 주소 크기 4 찍힘 (포인터의 크기)
  • size 사라짐!
  • 배열로 표기하는 이유는 배열임을 강조하기 위해


정적 다차원 배열

const int num_rows = 3;
const int num_columns = 5;

int array[num_rows][num_columns] = { 0 }; // OK

int array[num_rows][num_columns] = // OK
{
    {1, 2, 3, 4, 5},     
    {6, 7, 8, 9, 10},     
    {11, 12, 13, 14, 15}
};

int array[num_rows][num_columns] = // OK
{
    {1, 2, },               	// 1 2 0 0 0
    {6, 7, 8, 9, 10},
    {11, 12, 13, 14, 15}
};

int array[][num_columns] =  // OK
{
    {1, 2, },			//   1 2 0 0 0
    {6, },			//  6 0 0 0 0
    {11, 12, 13, 14, 15}
}; 

int array[][]; // error
int array[][2]; // error
  • 주소 찍어보면 row 넘어가도 쭉 이어짐
    • 내부적으로는 연속적인 1차원 배열인 형태


🚆 포인터

메모리 주소를 담는 변수

  • & : address-of operator → 쟤 저기 살아요
  • * : de-reference operatpr → 주소에 직접 접근해서 확인
int x = 5;
int* ptr = &x;
*ptr = 7;

cout << x << endl; // 7


double d = 3.0;
double* ptr_d = &d;

cout << ( sizeof(ptr) == sizeof(ptr_d) )<< endl; // true

double* ptr_dd = &123.0 // error : &R-value 불가능 (reference는 가능!)


Null Pointer

#include <cstddef> // std::nullptr_t 

int* ptr = nullptr;

if (ptr != nullptr) {}; 


nullptr_t nptr; // null pointer만 받을 수 있음
  • nullptr 이용하면 포인터 관리하기 좋음
  • nullptr_t 는 null 포인터만 받을 수 있는 변수


포인터와 정적 배열

int array[5] = { 0,1,2,3,4, };
int* ptr = array;

*ptr[1] = 100;
cout << array[1] << endl;  // 100

cout << sizeof(array) << endl;	// 20
cout << sizeof(ptr) << endl;	// 4
  • array의 이름은 “포인터” 역할 (첫 번째 원소의 주소)
  • ptr을 통해 배열의 원소 값 변경 가능
  • array이름과 포인터의 차이점은 sizeof
  • Q. 배열이 아닌 포인터 ptr[1] → 쓰레기 값(컴파일은 됨)


포인터 연산

int array[] = { 9, 7, 5, 3, 1 };
int* ptr = array;

cout << uintptr_t(ptr) << endl; 
cout << uintptr_t(ptr + 1) << endl; // uintptr_t(ptr) + 4
cout << uintptr_t(ptr + 2) << endl; // uintptr_t(ptr) + 8
  • uintptr_t : 포인터 주소 정수로 깔끔하게 표기
  • pointer + 1 → pointer + sizeof(data_type)
  • array[i] = *(ptr + i)


🚆 C언어 스타일의 문자열 기호적 상수

char 포인터는 컴파일러가 특별 대우!

문자열 포인터

char* ptr = "Jack Jack"; // Error
const char* name = "Jack Jack"; // OK

const char* name1 = "Jack Jack";
const char* name2 = "Jack Jack";

cout << (uintptr_t)name1 << endl;
cout << (uintptr_t)name2 << endl; // name1과 주소 같음
  • “Jack Jack” 은 R-value라 포인터에 담을 수 없음
  • const pointer로는 선언 가능 (문자열만 가능)
  • 내용 같으면 같은 주소에 담김 (컴파일러가 해줌)


문자열 cout

int int_arr[5] = { 1,2,3,4,5 };
char char_arr[] = "Hello World!";
const char* name = "Jack Jack";

cout << int_arr << endl;	// 0000004B8156FB28
cout << char_arr << endl;	// Hello World
cout << name << endl;		// Jack Jack
  • 문자열 포인터의 경우 주소가 아닌 \0 나올 때 까지 내용 출력 (특별 대우)


char c = 'Q';
cout << &c << endl;   // Q儆儆儆儆儆儆儆儆儆儆儆儆儆儆儆儆儆?릖¼
  • \0 나올 때 까지 내용 출력하니 이상한 값 나옴


print('a'); // char 혹은 int
print("a"); // 문자열. const char * 혹은 string 혹은 cahr [] 배열
  • ' ' → 문자
  • " " → 문자열



맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기