레이블이 C인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C인 게시물을 표시합니다. 모든 게시물 표시

2016년 12월 9일 금요일

void** (double void pointer) 고찰

많은 API 에서 void ** 가 쓰인다.
이 void **를 한번 분석해보자

1. 다차원 포인터

int * * pI

int * * pI 포인터 변수이다
int * * pI int* 의 주소를 담는 (int**) 형의 타입이다.

2. void 포인터
보이드 포인터 타입은 모든 포인터를 대입할수 있다.
(malloc 는 void*를 리턴한다.)
단 역참조와 정수와의 주소 offset 연산이 불가능하며 같은 void 포인터 타입과 비교연산(==)가 가능하다

void * vP;
int * nP;
....
*nP <--- O 가능 int포인터로써 역참조가 가능하다.
*vP <--- X 불가능 대체 무슨타입으로 역참조를 해야한단 말인가? 컴파일러는 판단할수 없다.


*nP 는 직접적으로int의 정수에 접근이 가능하지만
위의 두 포인터 변수의 차이는 void는 형을 알수없음으로 역참조를 할수 없는데 있다.

3.void **
앞에 두 개념을 숙지하고 아래의 개념을 다시 한번 생각해보았다.
왜 void**를 쓰는가?

char* 자체를 void*로 바꿔서 생각해 보자.
void** 는 void* 의 포인터 이므로 유연하게 모든 포인터를 void*로 받을수 있다.

const char* funcMsg = "hello World";
void func(void **something)
{
    *something= (void *)funcMsg;
}
char * msg;
func((void**)&msg);
printf(msg);

2014년 12월 18일 목요일

포인터

포인터는 변수의 타입이며 무엇이든 그 컴퓨터의 주소를 담을수 있다.

포인터 형을 일반 지역변수에서 선언하던, 전역에서 선언하던 함수의 인자에서 선언하던 해당 컴퓨터/컴파일러의 주소범위 내의 사이즈 타입의 변수에 그 포인터 원형의 주소가 담기게 된다.

애초에 int a char b 처럼 변수의 이름은 컴파일시 심볼테이블에 의해 실 주소로 치환이 된다.
이것을 이해하면 포인터의 주소개념을 더 명확히 할수 있다.

거기서 오프셋 연산이나 역참조를 통한 직접접근이 가능하게 되는것이다. 포인터가 담기게되는 스택형 변수와 힙 포인터를 착각하게 되는것을 주의하자.

char * pc  -> char 타입이 담겨있는 주소. 즉 pc의 실제 메모리 주소를 가르킨다.

char ** ppc -> char * 타입이 담겨있는 주소. 역시 ppc 주소를 가르키며 그 안에는 당연히 char* 타입의 데이터가 담겨있어야 한다.



2014년 12월 9일 화요일

C 에서의 extern

사용되고 있는 변수가 다른 파일에서 정의(기억장소가 할당되도록 함) 되었다면
그 외부변수를 사용하기 위해 extern 으로 '선언' 하고 사용하여야 한다
보통 한 파일에서  아래와 같은 방식으로 사용한다

file1.c
int gInt = 1; //정의와 선언

file1.h
extern int gInt;

file2.c
#include "file1.h"
gInt = 2;
단 배열의 extern 은 그 크기를 명사하여야 하나
extern 에서는 생략이 가능하다
즉 아래의 표현은 동일하다

extern int array[10];
extern int array[]; 

2014년 12월 7일 일요일

C# 에서 (C,C++ dll) 로드시 hresult 0x8007007e Exception from HRESULT: 0x8007000B

개발한 PC에있는 dll이 실행하는 PC에 없는 경우이다..
http://www.dependencywalker.com/  를 통해 내가 만든 dll 의존성 검사를 한후
존재하지 않는 dll을 추가시켜주면 된다.

그러나 의존하는 dll이 많은 경우?
해당 DLL 컴파일시 옵션을 아래와 같이 수정해도 된다

 /MT switch instead of /MD—(it's found in the UI under "Configuration Properties" -> "C/C++" -> "Code Generation" -> "Runtime Library").

설정 -> c/++ 코드 생성 -> 런타임 라이브러리에서 /md로 되어있는것을 /mt로 변경한다

2014년 8월 25일 월요일

리턴값과 포인터

리턴값의 포인터를 처리할때. 주소가 리턴되지 범위 내의 스택변수가 생성되지 않음에 주의!

int* rtnp()
{
   int* n = new int();
return n;
}

//호출부
int a;
rtnp()=&a; //에러.. 이유는 포인터 변수의 값인 주소가 리턴되는 것이지 포인터 변수가 생성되는 것이 아니기 때문이다.
*rtnp()= a; //같이 주소를 역참조해서 사용해야 한다.