'C++'에 해당되는 글 17건

  1. 2018.10.08 C/C++ 구조체 사용법 및 예제 1
  2. 2018.10.05 C/C++ 배열 사용법
  3. 2018.10.02 C 파일처리
  4. 2018.09.26 C++ 벡터 사용법 2
  5. 2018.09.25 C언어 포인터 8



안녕하세요 열코입니다.

이번시간에는 C/C++에서 구조체의 사용법과 간단한 예제에 대해 알아보도록 하겠습니다.


☞ 구조체란?

구조체는 C/C++에서 사용자 정의 데이터 형식입니다.

구조체는 다른 유형의 항목들을 단일 유형으로 그룹화하는데 사용합니다.

쉽게말해 int, char, double과 같은 자료형을 사용자가 임의로 만드는 것입니다.


☞ 구조체 만드는 방법?

struct 키워드를 사용하여 구조체를 작성합니다.

아래는 구조체 작성 예제입니다.


1
2
3
4
5
struct student {
    char name[20];
    char address[100];
    int age;
};
cs


☞ 구조체 변수 선언 방법?

구조체를 선언했으니 구조체 변수를 만들어야합니다.

int a; 와 같이 int 자료형의 변수를 만드는 것과 같은 이치입니다.


1. 첫번째 방법


1
2
3
4
struct Point {
    int x;
    int y;
} p1;
cs


2. 두번째 방법


1
2
3
4
5
6
7
8
struct Point {
    int x;
    int y;
};
 
int main(void) {
    struct Point p1;
}
cs


위와 같이 구조체 변수를 기본 자료형 처럼 별도로 선언할 수 있습니다.



* 두번째 방법에서 struct 키워드를 생략하고 싶을때

아래와 같이 typedef 키워드를 사용하여 구조체를 작성하면 구조체 변수 선언시 struct 키워드를 생략할 수 있습니다


1
2
3
4
5
6
7
8
typedef struct Point {
    int x;
    int y;
} Point;
 
int main(void) {
    Point p1;
}
cs

(최신 컴파일러 버전에서는 typedef를 사용하지 않아도 struct 키워드를 생략할 수 있습니다.)


☞ 구조체 멤버를 초기화 하는 방법?

구조체 멤버는 구조체 변수를 선언할 때 초기화해야 합니다.

다음과 같이 구조체를 작성할 때 초기화 하면 오류를 발생합니다.


1
2
3
4
struct Point {
    int x = 0;
    int y = 0;
};
cs


그 이유는 간단합니다.

데이터 유형이 선언될 때 변수가 메모리에 할당되지 않기 때문입니다.

변수가 생성이 되어야만 메모리에 할당됩니다.

(최신 컴파일러 버전에서는 오류를 발생하지 않습니다.)


구조체 멤버는 { } (중괄호)를 사용하여 초기화 할 수 있습니다.

아래의 예제를 확인하세요.


1
2
3
4
5
6
7
8
struct Point {
    int x;
    int y;
};
 
int main(void) {
    struct Point p1 = { 10 };
}
cs


☞ 구조체 멤버에 접근하는 방법?

구조체 멤버는 점(도트; .) 연산자를 사용하여 접근 할 수 있습니다.


1
2
3
4
5
6
7
8
9
struct Point {
    int x;
    int y;
};
 
int main(void) {
    struct Point p1 = { 10 };
    p1.x = 10;
}
cs


☞ 구조체 배열 사용법?

일반 자료형(int, char, double 등)과 같이 구조체(사용자 임의 자료형) 역시 배열을 만들 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
struct Point {
    int x;
    int y;
};
 
int main(void) {
    struct Point p[5];
    
    for (int i = 0; i < 5; i++) {
        p[i].x = i;
        p[i].y = i;
    }
}
cs



☞ 구조체 포인터란?

지난 시간에 배열과 포인터의 비교에 대해 알아보았습니다. (공부하러가기)

배열과 포인터는 닮은점이 많다고했는데요.

일반 자료형(int, char, double 등)과 같이 구조체(사용자 임의 자료형) 역시 포인터를 만들 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
struct Point {
    int x;
    int y;
};
 
int main(void) {
    struct Point p1 = { 11 };
    struct Point* p2 = &p1;
 
    p2->= 2;
    p2->= 3;
}
cs


위와 같이 * 연산자를 사용하여 포인터 변수를 선언하고, 변수의 주소값을 대입하여 정의할 수 있습니다.

구조체 포인터의 대한 접근방법은 -> 연산자를 사용하여 접근 가능합니다.


구조체는 C와 C++에서 모두 사용 가능합니다.

C++이 세상에 나오기 전 C에서의 구조체를 활용하여 C++의 클래스(class)를 만들었다고 하네요.

이 처럼 C의 구조체와 C++의 클래스는 닮은점이 많이있답니다.

다음 시간에는 C++의 클래스에 대해 한번 배워보도록 하겠습니다.



이상 'C/C++ 구조체'에 대해 알아보았습니다.

질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.



'C, C++' 카테고리의 다른 글

C/C++ 메모리 동적할당  (0) 2018.10.11
C++ friend 클래스와 함수  (1) 2018.10.10
C++ 클래스 접근제한자  (0) 2018.10.10
C++ 클래스와 객체  (0) 2018.10.09
C/C++ 배열 사용법  (0) 2018.10.05
C 파일처리  (0) 2018.10.02
C++ 벡터 사용법  (2) 2018.09.26
C언어 포인터  (8) 2018.09.25

C/C++ 배열 사용법




안녕하세요 열코입니다.


이번시간에는 C/C++에서 배열의 사용법에 대해 알아보겠습니다.

컴퓨터 공학에서 배열(array)이란 번호(index)와 그에 대응하는 데이터들로 이루어진 자료구조를 뜻합니다.

일반적으로 배열은 같은 종류(type)의 데이터들이 순차적으로 메모리에 저장됩니다.

대부분의 프로그래밍 언어에서 배열을 지원하며 이번시간에는 C와 C++의 배열 사용법에 대해 알아보도록 하겠습니다.


배열의 사용 이유?

많은 수의 데이터를 저장하기위한 변수를 선언할 때 일반 변수로 관리하기가 어렵기 때문에 하나의 변수(배열)를

선언해서 많은 데이터를 한꺼번에 순차적으로 처리 할 수 있습니다.


☞ 배열의 선언 방법?

C/C++에서 배열은 선언 당시 크기가 지정되어야 합니다.(고정된 크기의 자료구조)

일반적으로 다음과 같이 선언 할 수 있습니다.


int arr[5];


배열은 일반 변수와 같이 자료형(type)을 먼저 선언하고 배열의 이름(기본적으로 arr 또는 ary 등을 사용합니다)을

명시해준 후, 대괄호( ' [ ' , ' ] ' )를 사용해서 배열의 크기를 지정해 줍니다. 

이때 배열의 크기는 고정된 상수(양의 정수형 숫자)여야 하며 일반 변수를 지정해 줄 수 없습니다.

배열 요소의 자료형은 int(정수)형을 포함, 모든 기본 자료형(char, double 등)을 지원합니다.


또한 아래와 같이 크기를 명시 해 주지않고 배열의 요소를 모두 정의할 수 있습니다.


int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };


이 경우에는 arr 변수의 크기는 개발자가 직접 명시하지 않아도 자동으로 10으로 지정됩니다.

또한 배열의 크기를 명시적으로 지정해 주고 배열 요소를 모두 지정해 주지않으면 나머지 요소들은 모두 0으로 초기화 됩니다.

아래의 예제를 확인해보겠습니다.



int arr1[5] = { 1, 2, 3 }; // 배열의 요소들은 { 1, 2, 3, 0, 0 } 으로 초기화 됨

int arr2[5]; // 배열의 요소들은 모두 쓰레기값으로 초기화 됨

int arr3[10] = { 0 }; // 배열의 요소들은 모두 0으로 초기화 됨


위 코드를 보면 알 수 있듯이, 요소들의 값을 하나라도 지정해 주면 나머지 지정 해 주지않은 요소들은 모두 0으로 초기화되며,

만약 요소의 값을 하나라도 지정 해 주지않으면 모두 쓰레기 값으로 초기화됩니다.


☞ 배열의 요소에 접근하는 방법?

배열 각각의 요소에 접근을 하기 위해서는 대괄호( ' [ ' , ' ] ' )를 사용해서 접근 할 수 있습니다.


int arr[3];

arr[0] = 5;

arr[1] = 2;

arr[2] = 0;

arr[3] = 4; // 런타임 에러!!


위와 같이 배열의 크기를 3으로 지정하면 배열의 요소(index)는 0부터 2(배열의 크기 - 1)까지 생성됩니다.

또한 배열의 요소에 접근역시 0부터 2까지 허용되며 배열의 요소 범위를 초과하면 런타임 에러가 발생하게 됩니다.

* 배열의 요소의 시작이 1이아닌 0부터 시작한다는 것을 주의합니다.


☞ 배열의 이름의 의미?

우리가 배열을 만들어 줄 때 이름을 arr 또는 ary 또는 a, b, c...등 으로 의미없이 지어주었지만

컴파일러는 배열의 이름에 남다른 의미를 부여해줍니다.

바로 배열의 이름에는 배열의 시작 주소를 담고있는데요.

이 배열의 시작 주소로 여러가지 활용이 가능합니다.


int arr[3]; 

printf("%d\n", arr); // 배열의 시작 주소를 출력 (100번지)

printf("%d\n", arr + 1); // 배열의 다음 요소의 주소를 출력 (104번지)


배열의 다음 요소의 주소가 104번지 (4차이)가 나는 이유는 배열의 자료형이 int(정수형) 4바이트(32비트 운영체제 기준)이기 때문입니다.

이를 이용해 배열의 자료형을 알 수도있으며, 배열 각각의 요소에 접근 할 수도 있고, 포인터와 활용하여 여러가지 연산이 가능해지게 됩니다.



☞ 배열과 포인터의 차이?

배열과 포인터는 엄연히 말하면 다르지만 사용 측면에서 비슷한점이 많습니다. 

먼저 포인터에 대해 이해한 다음 아래 내용을 확인하시면 좋겠습니다.

포인터에 대해 배우러 가기 < 클릭


배열과 포인터는 구조상 차이가 있지만 사용 측면에서는 큰 차이가 없으며 대부분 같은 동작을 수행합니다.

아래 코드를 확인해보시면 배열과 포인터의 비슷한 점을 확인 하실 수 있습니다.


int arr[3] = { 1, 2, 3 }; // 배열 선언

int *p = arr; // 포인터 선언(배열의 첫번째 요소의 주소값을 가리킴)

// 배열을 포인터처럼 사용

printf("%d\n", *(arr + 2)); 

// 배열의 시작 주소의 2를 더함(8바이트 이동하여 배열의 3번째 요소에 도착)

// 배열의 3번째 요소의 주소값에 *(역참조연산자)를 연산하면 그 주소값의 실제 저장된 값에 접근

// 따라서 배열의 마지막 요소인 3을 출력


// 포인터를 배열처럼 사용

printf("%d\n", p[0]);

// p는 포인터 변수이지만 배열처럼 [ ] 대괄호를 사용해 배열의 요소에 접근하는 것 처럼 활용이 가능

// 배열의 첫번째 요소인 1을 출력


// 포인터의 연산

printf("%d\n", *(p + 1));

// p는 포인터 변수이며 배열의 첫번째 요소를 가리킴

// p에 1을 더한것은 포인터의 타입인 int형을 기준으로 4바이트 더한 연산을 수행

// 따라서 p는 배열의 첫번째 요소의 주소값에서 4를 더했으므로 배열의 두번째 연산의 주소값을 가리킴

// *(역참조연산자)을 연산하면 주소값의 실제 값인 2를 출력


☞ 배열의 크기를 동적으로 만들고 싶을 때?

배열은 정적인 크기의 자료구조입니다. 하지만 프로그래밍을 하다보면 배열의 크기를 마음대로 조절하고 싶을 때가 생깁니다.

그럴 때에는 포인터를 사용하여 동적할당을 활용하거나 C++에서는 STL의 하나인 벡터 클래스를 활용하시면 됩니다.


1. C에서 동적할당

C언어에서는 포인터 변수를 활용해 배열을 동적으로 생성하고 제거할 수 있습니다.

아래의 코드는 malloc() 함수를 사용하여 배열의 크기를 입력 받은 후 사용하고 메모리를 해제하는 예제 코드입니다.


int *p; // 포인터 변수 선언

int arr_size; // 배열의 크기를 입력 받을 변수

scanf("%d", &arr_size); // 배열의 크기를 입력 받음

p = (int *)malloc(sizeof(int) * arr_size); // 입력 받은 숫자만큼 배열을 동적 생성

free(p); // 사용이 끝난 후 메모리 해제


2. C++에서 동적할당

C++언어에서도 마찬가지로 포인터 변수를 활용해 배열을 동적으로 생성하고 제거할 수 있습니다.

C++에서는 malloc() 함수이외에 new 키워드를 지원하므로 new 키워드를 사용하여 배열을 동적으로 생성할 수 있습니다.

아래는 new 키워드를 사용하여 배열을 동적 할당하는 예제 코드입니다.


int *p; // 포인터 변수 선언

int arr_size; // 배열의 크기를 입력받을 변수

cin >> arr_size; // 배열의 크기를 입력받음

p = new int[arr_size]; // 입력받은 크기만큼 배열을 동적 생성

delete[] p; // 사용이 끝난 후 메모리 해제


3. C++ STL 벡터클래스 활용

C++은 STL이라는 표준 라이브러리를 지원하며 이 중 벡터(Vector) 클래스를 활용하여 크기가 가변하는 배열을 사용할 수 있습니다.

벡터 클래스의 사용방법은 여기를 참고하세요.



이상 'C/C++ 배열 사용법'에 대해 알아보았습니다.

질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.



'C, C++' 카테고리의 다른 글

C++ friend 클래스와 함수  (1) 2018.10.10
C++ 클래스 접근제한자  (0) 2018.10.10
C++ 클래스와 객체  (0) 2018.10.09
C/C++ 구조체 사용법 및 예제  (1) 2018.10.08
C 파일처리  (0) 2018.10.02
C++ 벡터 사용법  (2) 2018.09.26
C언어 포인터  (8) 2018.09.25
C++ 자바 상속 비교  (0) 2018.09.08

C 파일처리



안녕하세요 열코입니다.


이번 시간에는 C언어에서 파일처리에 대해 알아보겠습니다.

지금까지 했던 작업은 어디에도 저장 되어있지 않고 오로지 명령 프롬프트(터미널)에서만 수행됐지만,

실제 소프트웨어 프로그래밍을 할 때에는 대부분 정보를 저장하기 위해 파일 처리는 필수적으로 

구현 해야합니다.

C언어에서 파일처리는 파일 열기, 읽기, 쓰기, 닫기 등을 지원합니다.

먼저 파일 열기에 대해 알아보겠습니다.


1. 파일 열기(파일 만들기)

먼저 파일을 열거나 만들기 위해서는 FILE 구조체의 포인터 변수를 만들어 주어야 합니다.

다음과 같이 포인터 변수를 만들고 fopen() 함수를 이용하여 파일을 열거나 만들어줍니다.


int main() {

FILE *f = fopen("test.txt", "w");

return 0;

}


위 코드와 같이 작성하고 프로그램을 실행하면 해당 프로젝트 안에 test.txt라는 파일이 하나 생성됩니다.

만약 test.txt라는 파일이 존재한다면 파일을 열게 된 것입니다.


* 첫번째 파라미터(파일 경로)에 대해 : 기본적으로 fopen() 함수의 경로는 상대경로입니다.

경로를 아무것도 적지않고 오로지 파일명만 적는다면, 경로는 프로젝트 폴더내로 지정됩니다.

절대경로로 지정하고 싶다면 "C:\\test.txt" 또는 "D:\\test\\test.txt" 등 처럼 절대 경로로 설정하세요.


* 두번째 파라미터(접근 방식)에 대해 : fopen() 함수는 두개의 파라미터를 받는 함수로 첫번째는 경로, 두번째는 접근 방식입니다.

fopen() 함수의 접근 방식은 다음과 같습니다.


r

읽기 전용(파일이 존재해야 합니다.)

w

쓰기 전용(파일이 존재하면 내용이 삭제되며, 

파일이 존재하지 않으면 새 파일이 생성됩니다.)

a

쓰기 전용(파일이 존재하면 내용 끝에서 부터 쓰기 시작합니다. 

파일이 존재하지 않으면 새 파일이 생성됩니다.)

r+

읽기 및 쓰기 전용(파일이 존재해야 합니다.)

w+

읽기 및 쓰기 전용(파일이 존재하면 내용이 삭제되며, 

파일이 존재하지 않으면 새 파일이 생성됩니다.)

a+

읽기 및 쓰기 전용(파일이 존재하면 내용 끝에서 부터 쓰기 시작합니다. 

파일이 존재하지 않으면 새 파일이 생성됩니다.)


또한 r, w, a 뒤에 b를 붙여 2진 파일을 열고 쓸 수 있습니다.


* fopen() 함수를 사용할 때 다음과 같은 오류가 발생하면,

C4996 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

#define _CRT_SECURE_NO_WARNINGS 또는 #pragma warning(disable:4996)를 추가하여 해결할 수 있습니다.



2. 파일 읽기

파일을 열었으니 이제 읽어야겠죠? 파일을 읽기위해 열 때에는 위의 fopen() 함수의 접근 방식을 

r 또는 r, w, a에 +를 붙여 파일을 열어야 합니다.

다음과 같은 텍스트 파일이 있다고 가정합니다.


[test.txt]

1 2 3

가 나 다

A B C


위 텍스트 파일을 열어서 읽어보도록 합시다.


int main()

{

FILE *f = fopen("test.txt", "r"); // test.txt 파일을 읽기 전용으로 열기


while (!feof(f)) { // '파일의 끝' 까지 반복

char buffer[255]; // 문자열을 담을 버퍼

char *string = fgets(buffer, sizeof(buffer), f); // 버퍼의 크기만큼 한 줄 씩 읽기

printf("%s", string); // 출력

}


    return 0;

}


간단한 설명은 주석으로 처리했습니다.

아래는 실행화면입니다.



여기까지 텍스트파일을 열어서 읽는 것 까지 했습니다. (잘 따라오셨나요? ㅎㅎ)

이제 파일을 열고 읽기 까지 했으니 써봐야겠죠! 파일 쓰기로 넘어갑니다.



3. 파일 쓰기

자 이제 파일을 써보겠습니다. 어떤 문자를 쓸까 고민을 하다가...

구구단을 힘들게 만들고 명령 프롬프트 창에 출력하고... 끝내면 아쉽잖아요?

자신이 힘들게 만든 구구단을 파일로 저장하면 멋질것 같네요!!

파일 쓰기 시작합니다.


int main()

{

FILE *f = fopen("test.txt", "w"); // test.txt 파일을 쓰기 전용으로 열기


for (int i = 2; i <= 9; i++) {

for (int j = 1; j <= 9; j++) {

fprintf(f, "%d X %d = %d\n", i, j, i*j); // 파일 쓰기

}

fprintf(f, "\n");

}


    return 0;

}


구구단을 콘솔 창에 출력하는 것이 아닌 fprintf를 사용하여 파일에 출력했습니다.

사용법은 printf와 같으며 맨 앞에 파일 포인터 변수를 추가하면 됩니다. (참 쉽죠?)

출력 결과를 확인 해 볼까요?



구구단이 아주 잘~ 나왔네요. ㅎㅎㅎ

fprintf() 함수 외에도 fputc(), fputs() 등 함수를 사용할 수 있습니다. 개인적으로는 printf() 함수와 사용법도 비슷한

fprintf() 함수가 가장 사용하기 편리하더군요.

자 거의 다왔습니다! 대망의 마지막 파일 닫기입니다.



4. 파일 닫기

파일닫기는 객체의 메모리 해제 처럼 C++/ Java 등의 객체지향 프로그래밍에서도 누누이 언급했던 중요한 부분입니다.

파일을 열고 난 후 다 썼으면? 닫아야겠죠!

파일 열기보다 훨씬 간단합니다. fclose() 함수 한줄이면 되요.

int main()

{

FILE *f = fopen("test.txt", "w"); // 파일을 열고


// 내맘대로 막 쓴 다음


fclose(f); // 파일을 닫아줍니다.


    return 0;

}


정말 간단하죠? ㅎㅎ 객체의 할당 및 해제 처럼 파일 닫기도 아주 중요한 작업입니다.

두개이상의 파일을 동시에 열어 사용할 때는 충돌이 일어나기도 하죠...

아무튼 C 파일처리에 대한 글을 여기까지 입니다!



이상 'C 파일처리'에 대해 알아보았습니다.

질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.



'C, C++' 카테고리의 다른 글

C++ 클래스 접근제한자  (0) 2018.10.10
C++ 클래스와 객체  (0) 2018.10.09
C/C++ 구조체 사용법 및 예제  (1) 2018.10.08
C/C++ 배열 사용법  (0) 2018.10.05
C++ 벡터 사용법  (2) 2018.09.26
C언어 포인터  (8) 2018.09.25
C++ 자바 상속 비교  (0) 2018.09.08
C 랜덤 - 난수 생성하기  (7) 2018.09.06

C++ 벡터 사용법



안녕하세요 열코입니다.


C++에서 벡터는 표준 템플릿 라이브러리(STL)에서 제공하는 동적 배열구조 클래스입니다.


C의 배열처럼 빠른 랜덤 접근이 가능하며 자동으로 배열의 크기 조절과 추가 삭제가 가능합니다.


모든 자료형에 대해 배열처럼 저장할 수 있지만 한번에 한 타입만 저장이 가능합니다.


자바의 벡터와 마찬가지로 배열 크기를 추가할때 기존 배열 크기의 100%가 늘어납니다.(2배)



먼저 벡터를 선언하는 방법에 대해 알아보겠습니다.



vector<int> integer_vector;

vector<double> double_vector;

vector<char> char_vector;


벡터 클래스는 C++ 모든 자료형의 저장을 지원하며 위 코드와 같이 만들수 있습니다.


벡터에서의 데이터 추가 및 삭제는 배열의 끝에서 O(1), 배열의 중간 O(n)만큼의 시간복잡도가 소요됩니다.



벡터에 데이터 추가하기



for (int i = 0; i < 5; i++) {

integer_vector.push_back(i);

double_vector.push_back((double)i);

char_vector.push_back('a' + i);

}


벡터 클래스에서 push_back() 함수를 이용하여 요소의 끝에 데이터를 추가할 수 있습니다.


지정된 위치에 요소를 추가하려면 insert() 함수를 사용하세요.



벡터의 데이터 삭제하기



integer_vector.pop_back(); // 요소 끝의 데이터 삭제

double_vector.erase(double_vector.begin()); // 지정된 위치의 데이터 삭제

char_vector.clear(); // 모든 데이터 삭제



벡터는 다음과 같은 내부 함수가 존재합니다.



begin() - 벡터의 첫번째 요소를 가리킵니다.


end() - 벡터의 마지막 요소를 가리킵니다.


size() - 벡터의 요소 수(크기)를 반환합니다.


resize() - 벡터의 크기를 재조정합니다.


empty() - 벡터가 비어있는지 여부(true or false)를 반환합니다.


at() (또는 [ ]) - 벡터의 인덱스에 접근할 수 있습니다.


front() - 벡터의 첫번째 요소를 반환합니다.


back() - 벡터의 마지막 요소를 반환합니다.


data() - 포인터가 접근할 수 있도록 벡터의 주소값을 반환합니다( int *p = vector1.data() )



더 상세한 내용을 확인하고 싶다면 여기를 방문하세요.






이상 'C++ 벡터'에 대해 알아보았습니다.


질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!


공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.


'C, C++' 카테고리의 다른 글

C++ 클래스와 객체  (0) 2018.10.09
C/C++ 구조체 사용법 및 예제  (1) 2018.10.08
C/C++ 배열 사용법  (0) 2018.10.05
C 파일처리  (0) 2018.10.02
C언어 포인터  (8) 2018.09.25
C++ 자바 상속 비교  (0) 2018.09.08
C 랜덤 - 난수 생성하기  (7) 2018.09.06
C++ String 문자열 사용법 정리  (0) 2018.08.20

C언어 포인터



안녕하세요 열코입니다.


이번시간에는 C언어 포인터에 대해 알아보겠습니다.


포인터(Pointer)란 프로그래밍 언어에서 변수의 메모리 주소를 가리키는 변수를 말합니다.


포인터는 Low Level 언어(C/C++/어셈블리...등)에서 많이 사용됩니다.



이번 포스트는 다음과 같이 진행됩니다.


1. 포인터 사용법


2. 포인터 활용


3. 포인터와 배열의 차이점



준비되셨으면 그럼 시작하겠습니다!!


먼저 포인터에 대한 사용법에 대해 알아보겠습니다.



1. 포인터 사용법


포인터를 사용하려면 먼저 두가지 연산자에 대한 이해가 필요합니다.


& 연산자와 * 연산자입니다.


scanf에 대해 공부하셨다면 &연산자에 대해 보신적이 있을텐데요.


& 연산자에 대해 조금 설명하자면 변수의 주소에 액세스 하기위한 단항 연산자입니다.


(참고 영어로는 ampersand라고 합니다.)


그래서 scanf는 표준 입력함수로 콘솔에서 입력을 변수에 메모리에 접근하여 저장하기 위해 


& 연산자를 사용하는 것입니다.


아래 예제는 & 연산자를 이용하여 변수의 주소를 출력하는 코드입니다.


#include <stdio.h> // 표준 입출력 라이브러리


int main(void) {

int num = 10; // 정수형 변수 선언

printf("%p", &num); // num의 주소값 출력

}


위 코드는 num이라는 이름을 가진 정수형(Integer) 변수를 선언하고 그 값으로 10이라는 


정수(10진수)를 정의했습니다.


그리고 이 num이라는 변수는 메모리 어딘가(스택영역)에 할당됩니다.


(참고 : 메모리공간은 크게 데이터, 스택, 힙 공간으로 분류됩니다.


여기서 num 변수는 main() 함수의 지역변수이기 때문에 지역변수의 저장 공간인 스택영역에 저장되게 됩니다.)


표준 출력함수인 printf() 함수를 통해 num 변수의 주소값을 출력해보겠습니다.



첫번째 매개변수로 %p를 주었습니다. 왜 %d가 아닌 %p일까요?


%d 는 decimal의 줄임말로 변수를 10진수로 표현하기 위한 포맷(format)입니다.


%p 는 주소값을 표현하기 위한 포맷이라고 생각하시면 되겠습니다.


두번째 매개변수로는 num앞에 &연산자를 추가했습니다. 이는 num변수안에 저장된 값 10이 아닌


num변수가 저장된 메모리 주소에 접근하기 위해 연산자 &를 사용한 것입니다.



우리가 사용하는 컴퓨터의 메모리는 RAM인거 다 아시죠?


RAM은 Random Access Memory의 줄임말로 접근이 임의인 메모리입니다.


따라서 num 변수의 주소값은 출력할 때마다 매번 다른 값을 출력하게됩니다.(직접해보세요)



이제 포인터를 사용하기 위해 * 연산자에 대해 알아보겠습니다.


앞서 배운 & 연산자를 일반적으로 참조 연산자라고 부르며, * 연산자를 역참조 연산자라고 부릅니다.


포인터를 사용하기 위해서는 변수와 자료형 사이에 * 연산자를 추가하면 됩니다.


아래 예제 코드를 참고하세요.


#include <stdio.h> // 표준 입출력 라이브러리


int main(void) {

int num = 10; // 정수형 변수 선언

int *p; // 정수형 포인터 선언

p = &num; // 포인터가 num 변수의 주소값을 가리킴


printf("%d\n", p); // 포인터가 가리키는 변수의 주소 출력

printf("%d\n", *p); // 포인터가 가리키는 변수의 값 출력

printf("%d\n", &p); // 포인터 변수의 주소 출력

}


자 *도 많고 &도 많고 참 헷갈린다 그쵸?


먼저 글로 최대한 간단히 설명하고 그림으로 설명드리겠습니다.


첫번째 줄 부터 설명하겠습니다.




① num이라는 정수형 변수를 선언했습니다. 이로써 스택영역에 num 변수의 메모리가 할당됩니다.


② p라는 정수형 포인터를 선언했습니다. 이로써 힙영역에 p 변수의 메모리가 할당됩니다.


(num이라는 정수형 변수를 가리키기 위한 포인터로써 정수형 포인터를 선언합니다. 


또한 포인터는 힙 영역에 할당 됩니다.)


③ p라는 정수형 포인터에 num 변수의 주소값을 대입했습니다.


(포인터의 주소값을 대입하는 표현을 편의상 가리킨다라고 표현합니다.)



여러분들의 이해를 돕기위해 그림을 직접 그려서 대령했습니다.(짝짝)


메모리는 데이터, 힙, 스택영역이 있다고 위에 설명했죠?


따라서 지역변수인 num은 스택영역할당되고, 포인터 변수인 p는 힙 영역에 할당되었습니다.


그리고 num의 주소값을 p에게 대입(p가 num을 가리킴)을 화살표로 표현했습니다.



여기서 출력값에 대해 알아보면


printf("%d\n", p); // 포인터가 가리키는 변수의 주소 출력


printf("%d\n", *p); // 포인터가 가리키는 변수의 값 출력


printf("%d\n", &p); // 포인터 변수의 주소 출력


은 각각 어떤 값을 출력할까요?


맞추시는 분께는 열코 블로그 3개월 구독권을 드립니다! (필요없음)




자 하나씩 살펴보도록 합시다.


첫번째 p의 출력값은 p가 가리키는 변수의 주소 출력, 따라서 num의 주소값이 0(임의의 주소값)이 출력되겠죠?


두번째 *p의 출력값은 p가 가리키는 변수의 값 출력, 따라서 num의 값 10이 출력됩니다.


세번째 &p의 출력값은 p의 주소값, 따라서 100이 출력됩니다.


위 과정에 대한 이해가 안되시는분은 댓글로 질문남겨주시면 더욱! 더욱! 상세히 설명드리겠습니다.



2. 포인터의 활용은 다음 포스팅에서 소개하겠습니다. ^0^




이상 'C언어 포인터'에 대해 알아보았습니다.

질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.



'C, C++' 카테고리의 다른 글

C/C++ 구조체 사용법 및 예제  (1) 2018.10.08
C/C++ 배열 사용법  (0) 2018.10.05
C 파일처리  (0) 2018.10.02
C++ 벡터 사용법  (2) 2018.09.26
C++ 자바 상속 비교  (0) 2018.09.08
C 랜덤 - 난수 생성하기  (7) 2018.09.06
C++ String 문자열 사용법 정리  (0) 2018.08.20
[C++] C# 연동하기 / C# dll 파일 만들기  (1) 2018.08.18

to Top