[C Programming] 포인터 & 구조체

Kioreo·2023년 4월 8일
0

Layer7

목록 보기
2/5

포인터란?

포인터(Pointer)는 C언어의 꽃이라고 불리는 가장 악명 높은 자료형 중 하나입니다.
프로그래밍 언어에서 변수 또는 함수의 메모리 공간의 주소 값을 저장하는 변수를 말합니다.
이름만 다를 뿐 포인터는 int, char같이 다를 바 없는 변수입니다.
변수면 어떤 값을 저장하는데 포인터는 주소 값을 저장합니다.
이를 통해 다른 변수 또는 함수를 가리킬 수 있으며 포인터를 통해 변수에 접근하여 읽고 쓰거나 함수를 실행할 수 있습니다.

포인터 관련 연산자

주소 연산자(&)

주소 연산자는 변수의 이름 앞에 사용하며, 해당 변수의 주소를 반환합니다.

참조 연산자(*)

참조 연산자는 포인터의 이름이나 주소 앞에 사용하여, 포인터가 가리키는 주소에 저장된 값을 반환합니다.

포인터 선언

C언어에서 포인터는 다음과 같은 문법으로 선언합니다.

기본 문법
타입* 포인터명;

// example
int *p;
int* p;
int * p;

위와 같이 *의 위치는 상관없으므로, 마음에 드는 형태로 사용하시면 됩니다.

선언과 동시 초기화 하는 문법
타입* 포인터명 = &변수명;

// example
int a = 1;
int *p = &a;

a변수를 1로 초기화해주었고 포인터 p에는 주소 값이 저장되어야 하므로 주소 연산자를 사용하여 a의 주소로 *p를 선언해준다.

Call by Value & Call by Reference

c언어는 함수에서 인자를 전달하는 방식에는 크게 두 가지가 있습니다.

Call by Value
기본적으로 C언어에서 지원하는 방식으로 함수에서 값을 복사해서 전달하는 방식으로, 인자로 전달되는 변수를 함수의 매개변수에 복사합니다. 복사를 하게 되면 인자와 전달한 변수와는 별개의 변수가 됩니다.

Call by Reference
call by value와 다르게 함수에서 값을 전달하는 대신 주소 값을 전달하는 방식입니다.
엄밀히 따졌을 때 C언어에서는 주소 값 자체를 복사해서 넘겨주는 것으로 call by value입니다.
또, 이렇게 주소 값을 복사해서 넘겨주는 방식을 call by address라고 합니다.
C언어에서는 call by reference는 공식적으로 지원하지는 않으나 call by address를 call by reference 형식으로 사용할 수 있어 주소 값을 넘겨주는 방식으로 call by reference라고 설명하는 곳도 많습니다.


구조체란?

구조체(structure type)란 사용자가 C언어의 기본 타입을 가지고 새롭게 정의할 수 있는 사용자 정의 타입입니다. 구조체는 기본 타입만으로는 나타낼 수 없는 복잡한 데이터를 표현할 수 있습니다. 배열이 같은 타입의 변수 집합이라고 한다면, 구조체는 다양한 타입의 변수 집합을 하나의 타입으로 나타낸 것입니다.
이때 구조체를 구성하는 변수를 구조체의 멤버(member) 또는 멤버 변수(member variable)라고 합니다.

구조체 정의와 선언

C언어에서 구조체는 struct 키워드를 사용하여 다음과 같이 정의합니다.

구조체 정의
struct 구조체 이름 { 멤버변수 ... };

// example
struct book{
    char title[30];
    char author[30];
    int price;
};

구조체 선언
struct 구조체이름 구조체변수이름;

//example
struct book my_book;

typedef를 이용한 구조체 선언

typedef 키워드는 C언어에서 자료형을 새롭게 이름을 붙일 때 쓰는 키워드입니다.
typedef 키워드를 사용하여 구조체의 새로운 이름을 선언하는 방법은 다음과 같습니다.

기본 문법
typedef struct 구조체이름 { 맴버변수 ... } 새로운이름;

// example
typedef struct BOOK{
    char title[30];
    char author[30];
    int price;
} book;

구조체 멤버 접근

배열에서는 인덱스를 이용하여 배열 요소에 접근할 수 있습니다.
하지만 구조체에서 구조체 멤버로 접근하려고 할 때는 멤버 연산자(.)를 사용해야 합니다.

구조체에서 구조체 멤버로의 접근 방법은 다음과 같습니다.

문법
구조체변수이름.멤버변수이름

// example
my_book.author

구조체 포인터

포인터가 어떤 변수의 주소를 담아 가리키는 변수이기 때문에 구조체 포인터도 마찬가지로 구조체의 주소를 가리키는 포인터를 구조체 포인터라고 합니다.

구조체 포인터 문법
struct 구조체이름* 구조체포인터이름;

// example
struct book my_book;
struct book* p_my_book;
p_my_book = &my_book;

배열의 경우와는 달리 구조체의 이름은 구조체를 가리키는 주소가 아닙니다.
따라서 포인터에 할당할 때는 반드시 주소 연산자(&)를 사용해야 합니다.

구조체 포인터를 이용하여 구조체 멤버에 접근하는 방법은 두 가지가 있습니다.

  1. 참조 연산자(*)를 이용하는 방법

  2. 화살표 연산자(->)를 이용하는 방법

구조체 포인터 맴버 접근
1. (*구조체포인터).멤버변수이름
2. 구조체포인터 -> 멤버변수이름

// example
(*ptr_my_book).author
ptr_my_book -> author  

(1)번과 같이 허용할 때 주의해야 할 점은 *ptr_my_book.author이 아니라 (*ptr_my_book).author와 같이 괄호를 이용한다는 것입니다. 이 *도 참조 연산자이기 때문에 *ptr_my_book.author같이 이용하면 구조체가 아닌 포인터 변수를 구조체처럼 참조하려고 하기 때문에 오류가 발생합니다.


참조

TCPschool : http://www.tcpschool.com/
구름 / 한 눈에 끝내는 C언어 기초

profile
KITRI BoB 12th, Layer7 23rd

0개의 댓글