콘텐츠로 건너뛰기
Home » 포인터

포인터

Raw 포인터 사용에 대해

https://developer.apple.com/documentation/swift/unsaferawpointer

UnsafeRawPointer 타입은 자동 메모리 관리, 타입 안정성 및 메모리 정렬 보장이 되지 않는 원시 포인터 액세스를 제공합니다. 이 타입을 사용하려면 누수를 피하고, 할당된 메모리의 라이프 사이클을 직접 관리해야 하며, 그 외의 정의되지 않는 동작들을 회피해야 합니다. 수동으로 직접 관리하는 메모리 영역은 특정한 타입에 바운드되거나, 타입이 지정되지 않을 수도 있습니다. 메모리 영역에서 해당 영역이 특정 타입에 묶여있는지 여부와 무관하게 순수 바이트를 액세스하려할 때 UnsafeRawPointer 타입을 사용할 수 있습니다.

막 할당된 Raw 메모리는 타입화되지도 초기화되지도 않은 상태입니다. 이 메모리는 타입화된 연산을 사용하기 전에 반드시 초기화되어야 합니다. (초기화되려면 초기값을 가져야하고, 이는 타입화를 수반해야한다는 의미가 됩니다.) 초기화되지 않은 상태에서 특정 타입에 바인등하려면 bindMemory(to: count:)를 사용합니다. 이 메소드는 타입화된 포인터를 반환하며, 이후에는 해당 포인터를 사용해야 합니다.

더 보기 »Raw 포인터 사용에 대해

버퍼 포인터 이해하기

C에서 특정한 T타입의 배열은 메모리 상에서 연속적인 공간입니다. 이 때문에 정적 배열이든 동적 배열이든 배열을 액세스하는 것은 필연적으로 포인터와 관련됩니다. 반면 Swift의 배열에서 원소들은 반드시 이런 식으로 배치되지는 않습니다. C의 배열이 단지 원소값이 나란히 배치된 메모리 영역임에 비해 Swift의 배열은 struct로 구성되는 보다 복잡한 내부 구조를 가지고 있습니다.

이 때 T 타입이 차지하는 바이트 수가 고정되어 있으므로 배열의 시작번지와 인덱스 값을 알고 있다면 해당 인덱스에 위치한 값을 액세스할 수 있습니다. C에서 배열 이름은 암묵적으로 배열의 시작번지를 의미하므로, arr[i]로 표현되는 i 번째 원소의 값은 실제 컴파일러는 *(arr + i) 로 변환하여 접근합니다.

Swift에서도 UnsafePointer를 사용하여 포인터를 다룰 수 있는데, 이 때 범위(capacity, Pointee 타입의 메모리 사이즈 x 원소의 개수)내에는 동일타입을 구성하는 값들이 연속하여 배치되어 있습니다. 따라서 (ptr + i).pointee 와 같은 식으로 i 번째 원소에 대해 액세스가 가능합니다. 이것은 C의 접근방법과 매우 유사합니다. 하지만 이것은 단순한 메모리 연속체에서 특정 지점을 액세스하는 법일 뿐, Swift의 배열을 다루는 것과는 차이가 있습니다. Swift의 배열은 원소가 연속해있으면서 Sequence, Collection 프로토콜에 의한 여러가지 연산을 지원받습니다.

더 보기 »버퍼 포인터 이해하기

포인터 관련 메모

타입화된 포인터

Swift는 C API와의 상호작용 혹은 고성능 자료구조의 구현등을 위해 포인터를 통한 메모리 액세스를 제한적으로 지원하고 있습니다. 기본적으로 Swift 타입 혹은 Swift 에서 인식할 수 있는 C 타입에 대한 포인터는 ‘타입화된(typed)’ 포인터라고 하며, UnsafePointer를 사용합니다. UnsafePointer는 제네릭 struct 타입으로 특정 Swift 타입에 대한 포인터로 기능합니다. UnsafePointer는 메모리 주소를 통한 액세스를 허용해주기는 하지만 값의 불변성을 보장하기 때문에 해당 포인터가 가리키는 값(pointee)를 변경하는 것을 허용하지 않습니다. 변수에 대한 포인터는 UnsafeMutablePointer를 별도로 사용합니다.

더 보기 »포인터 관련 메모

Swift에서 포인터를 함수에 전달하는 법

기본적으로 Swift는 C(그리고 Objective-C)와 호환이 가능하다. 이를 위해 C의 각 데이터 타입에 대응할 수 있는 Swift 타입들을 정의해 두고 있다. 따라서 C로 작성된 라이브러리를 사용할 수 있고, 이 때 해당 라이브러리의 함수들은 적절하게 Swift 버전에 맞는 시그니처로 변환된다. 예를 들어 문자열의 길이를 구하는 C함수인 strlen 함수를 Swift에서 호출하고 싶은 상황을 가정해보자. strlen 함수의 원형과 반입된 버전의 함수는 각각 아래와 같은 형태로 만들어질 것이다. 자 그러면 Swift 문자열의 길이를 저 함수를 사용해서 구하고 싶은 상황이라고 하자. 문자열을 어떻게 UnsafePointer<UInt> 로 변환할… 더 보기 »Swift에서 포인터를 함수에 전달하는 법

한 편으로 이해해보는 포인터(C)

C를 공부하는 많은 사람들이 입버릇처럼 ‘포인터는 어렵다’고 말한다. 기술적으로 포인터는 사실 단순히 메모리상의 주소를 가리키는 정수값일 뿐이다. 그런데 왜 이것이 어려울까? 사실 포인터 자체는 단순하지만, 포인터를 이해하기 까지에는 제법 많은 배경지식이 추가로 필요하기 때문일 것이다. 오늘 이 글에서는 각잡고 포인터를 이해하는데 필요한 내용들을 정리하여 전달하고자 한다.

더 보기 »한 편으로 이해해보는 포인터(C)

[C] 함수로 전달된 포인터

포인터를 함수의 인자로 받는 경우, 함수내에서 원본을 변경하는가. 내용이 너무 두서 없어서 포스트 전체를 수정합니다. 처음 의문이 든 부분은, 문자열을 가리키는 포인터를 함수로 넘겨주고 문자열을 변형하면 포인터의 값이 변하는가?라는것이었는데. 이는 사실 그리 어려운 문제가 아니다. 포인터는 메모리의 주소를 가리키는 타입의 변수이고 이는 사실 unsigned int 나 unsinged int64 등의 정수형과 비슷하게 숫자를(메모리 번지도 결국 숫자값이므로) 담는 변수이다. 그리고 함수에 선언된 인자는 함수 내부에서만 사용하는 지역변수이고, 표준 타입의 변수를 함수에 전달하면 그 값이 인자로 선언한 변수에 들어가는데, 이건 그냥 변수의 값이… 더 보기 »[C] 함수로 전달된 포인터

C에서의 문자열 배열과 문자열 배열을 동적으로 할당하기

문자열의 배열을 2차원배열을 쓸 때의 문제점

C언어는 문자열을 다루는 자료형이 없다. 대신에  C에서 문자열은 널 문자로 끝나는 문자(char) 타입의 배열을 사용하여 저장한다.  만약 일련의 문자열 집합을 다루려면 문자열의 배열을 써야 할테다.  여러 개의 문자열을 배열에 담고 싶다면 이차원 배열을 쓰는 방법을 생각할 수 있는데,  이 경우 크기가 일정하게 고정된 영역을 여러 개 생성해야 하고, 만약 각 문자열의 길이가 제각각 다르다면 불필요하게 낭비되는 메모리가 제법 될 수 있다.

2차원 배열의 문자열 배열
2차원 배열을 사용하여 구성한 문자열 배열

메모리를 비롯하여, 부족한 하드웨어 자원을 알뜰 살뜰 아껴서 최대의 성능을 내기 위해 개발된 초기 C언어 관점에서 이러한 2차원 배열의 사용은 그리 추천하지 않는다.더 보기 »C에서의 문자열 배열과 문자열 배열을 동적으로 할당하기

[C/C++] 가변인수를 받는 함수

C함수의 가변인수 C함수도 가변인수를 사용할 수 있다. 대표적인 예가 printf이다. printf에는 서식 문자열을 비롯하여 서식에 채워질 값들을 컴마로 연결하여 나열할 수 있다. 이러한 가변인수는 어떻게 만들어서 사용할 수 있는지 살펴보자. 가변인수 함수의 선언 가변 인수 함수는 가변적으로 받을 인수 대신 …을 사용하는 것으로 가변 인수 함수임을 컴파일러에게 알릴 수 있다. 인수에 …이 들어있는 경우 컴파일러는 인수의 개수나 타입에 대해서는 전혀 신경을 쓰지 않게 된다. (결국 이는 함수 구현 시 프로그래머가 일일이 체크해야 하는 부분이다.) 이 때 중요한 것은 고정적으로 사용하는 인수는… 더 보기 »[C/C++] 가변인수를 받는 함수