검색결과 리스트
전체 글에 해당되는 글 199건
- 2014.04.02 20140402 (main 인자전달, stream)
- 2014.04.01 20140401 (함수 포인터, void 포인터)
- 2014.03.31 20140331 (2차원 배열, 이중포인터, 배열포인터)
글
20140402 (main 인자전달, stream)
32일차
---------------------------
main 함 수 로 인 자 전 달
---------------------------
- int main( int iNum, char * Cmd[] )
main함수 인자에 위의 인자 처럼 넣어주면
iNum에는 받은 명령어 갯수,
Cmd에는 그 명령어들이 각각 저장되어 있다.
ex) gcc -o main main.c
iNum 에는 4,
Cmd[0] : gcc
Cmd[1] : -o
Cmd[2] : main
Cmd[3] : main.c
이렇게 저장됨.
인자의 이름은 프로그래머 재량이지만 보통
int main(int argc, char * argv[])
로 많이 쓴다. argc ( ARGument Count ) argv ( ARGument Vector )
-------------------------
이중 포인터와 2차원 배열
-------------------------
- 이전에 한 번 했었는데 헷갈려서 다시 한 번 언급한다.
void test ( int ** ptr )
{ A }
int main()
{
int arr[5][3];
test( arr );
....
위의 소스처럼 썼었는데 warning!
이유는
char ** 와 char [][] 참조수준이 다름.
서로 데이터 타입이 달라서 그랬다.
2차배열은 이중포인터와 같은 것인지 착각했었다.
그래서 고치면
void test( int (* ptr)[3] ) { A } or void test( int ptr[][3] ) { A }
둘 다 동일한 선언이고 '배열 포인터'이다.
- int * whoA [4] // 포인터 배열
- int (* whoA)[4] // 배열을 가리키는 포인터
------------------
Stream 흐름
------------------
- ' >' Redirection. 출력 방향을 바꾼다.
- 표준입력 (키보드) : stdin, 0
- 표준출력 (모니터) : stdout, 1
- 표준에러 (모니터) : stderr, 2
ms-dos, linux에서는 0, 1, 2로 스트림으로 쓴다.
ex)
dir > a.txt dir 내용을 a.txt에 넣음
dir 1> a.txt dir 내용을 a.txt에 넣음
dir 2> a.txt dir 에러 내용을 a.txt에 넣음
- ' >> ' 이것도 redirection인데 ' > ' 와 다른 점은
> : 새로 쓰기
>> : 추가로 쓰기
- fprintf( Stream, format, ...);
printf 함수와 다르게 stream을 정해서 출력할 수 있다.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140404 (Adder, NOT, NAND, puts, fputs, gets, fgets, fflush) (0) | 2014.04.04 |
---|---|
20140403 (TTL, AND gate, putchar, fputc, getchar, fgetc) (0) | 2014.04.03 |
20140401 (함수 포인터, void 포인터) (0) | 2014.04.01 |
20140331 (2차원 배열, 이중포인터, 배열포인터) (0) | 2014.03.31 |
20140328 (const, 2차원배열) (0) | 2014.03.28 |
글
20140401 (함수 포인터, void 포인터)
32일차
------------------------
함 수 포 인 터
------------------------
- 함수의 주소값을 저장하는 포인터.
먼저 이 포인터를 선언하기 위해서는 Data Type을 알아야한다.
Data Type은 Prototype(함수원형)에서 이름 부분만 (*)로 바꾸면 된다.
ex)
int main() main함수의 Data Type은
{ 명령어들 } int (*)() 이다
void test() test함수의 Data Type은
{ 명령어들 } void (*)() 이다
int printf(const char *, ... ) printf함수의 Data Type은
int (*)(const char *, ...) 이다
- 함수 포인터 선언 및 사용
#include <stdio.h>
void test()
{
int (*fp)(const char *, ...) = printf;
(*fp)("hello \n"); // C++에서는 괄호를 넣지않으면 오류라고 한다.
fp("hello \n"); // C에서는 위와 밑에 둘 다 가능.
return ;
}
int main()
{
void (*fp)();
fp = test;
fp();
return 0;
}
위와 같은 방법으로 사용한다.
-------------------------
void 형 포 인 터
-------------------------
- Data Type이 void * 형이다.
타입을 안가리고 그 주소값을 warning 없이 다 받을 수 있다.
그러나 값을 가리키는 *를 붙이면 자료형이 얼만큼 인지 모르니
사용할 수 없다.
캐스팅을 하면 사용가능.
ex)
#include <stdio.h>
int main()
{
void * vp;
int iNum = 500;
char cNum = 100;
vp = &cNum;
*((char *)vp) = 99;
vp = &iNum;
*((int *)vp) = 400;
printf("%d \n", cNum);
printf("%d \n", *((int *)vp) );
printf("%d \n", iNum);
return 0;
}
위에 *((char *)vp) 식으로 char * 형이라고 캐스팅을 해서 사용.
아래 소스는 HexaView 코드인데
void * 가 사용되는 예를 보자.
#include <stdio.h>
void HexaView(void * vpData);
int main()
{
int iNum = 0x12345678;
HexaView(&iNum);
return 0;
}
void HexaView(void * vpData)
{
int iCnt;
int iCnt2;
printf("===============================================================================\n");
printf("= ADDRESS HEXA ASCII =\n");
printf("=-----------------------------------------------------------------------------=\n");
for(iCnt2=0; 20>iCnt2; ++iCnt2)
{
//----------------------------//
//--- Address Part Start ---//
printf("= %08X ", vpData);
//--- Address Part End ---//
//----------------------------//
//--- Hexa View Part Start ---//
for(iCnt=0; 16>iCnt; ++iCnt)
{
if(7 == iCnt)
{
printf("%02X ", (*((unsigned char *)vpData)) );
}
else
{
printf("%02X ", (*((unsigned char *)vpData)) );
}
vpData = ((unsigned char *)vpData) + 1;
}
//--- Hexa View Part End ----//
//----------------------------//
//----------------------------//
//--- ASCII Part Start ---//
vpData = ((unsigned char *)vpData) - iCnt;
for(iCnt=0; 16>iCnt; ++iCnt)
{
if(0x20 <= (*((unsigned char *)vpData)) && 0x80 > (*((unsigned char *)vpData)))
{
printf("%c", (*((unsigned char *)vpData)));
}
else
{
printf(".");
}
vpData = ((unsigned char *)vpData) + 1;
}
//--- ASCII Part End ---//
//----------------------------//
printf(" =\n");
}
printf("===============================================================================\n");
return ;
}
위에 연한 빨강색 바탕으로 강조된 곳들이
void *를 사용한 곳들이다.
main 함수에서 HexaView 함수를 호출 할 때에
void *를 사용하지 않았다면
HexaView( (unsigned char *)&iNum );
이런식으로 함수를 호출할 때마다 캐스팅을 해줘야 하기때문에
편의성의 위해서 작성할 때 좀 더 코드를 길게 적어주면 좋다.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140403 (TTL, AND gate, putchar, fputc, getchar, fgetc) (0) | 2014.04.03 |
---|---|
20140402 (main 인자전달, stream) (0) | 2014.04.02 |
20140331 (2차원 배열, 이중포인터, 배열포인터) (0) | 2014.03.31 |
20140328 (const, 2차원배열) (0) | 2014.03.28 |
20140327 (포인터, 배열, call by address, call by value) (0) | 2014.03.27 |
글
20140331 (2차원 배열, 이중포인터, 배열포인터)
31일차
-------------------------
2차원 배열 메모리 구조
-------------------------
-
char Arr[3][3];
int * ip = &Arr[0][0];
2차원 배열이 실제 메모리에서는
이런 식으로 저장되어 있다.
그래서 아래와 같이 모두 같은 값을 가리킨다.
ip[3] == Arr[0][3] == Arr[1][0]
- 줄 이동 (주소값)
Arr + 0 = &Arr[0] + 0 = &Arr[0]
Arr + 1 = &Arr[0] + 1 = &Arr[1]
Arr + 2 = &Arr[0] + 2 = &Arr[2]
- 칸 이동 (주소값)
&Arr[0][0] = Arr[0] + 0 = *(Arr + 0) + 0 = *( &Arr[0] + 0 ) + 0
&Arr[0][1] = Arr[0] + 1 = *(Arr + 0) + 1 = *( &Arr[0] + 0 ) + 1
&Arr[0][2] = Arr[0] + 2 = *(Arr + 0) + 2 = *( &Arr[0] + 0 ) + 2
- 칸 이동 (값)
Arr[0][0] = *(Arr[0] + 0) = *( *(Arr + 0) + 0 ) = *( *( &Arr[0] + 0 ) + 0 )
Arr[0][1] = *(Arr[0] + 1) = *( *(Arr + 0) + 1 ) = *( *( &Arr[0] + 0 ) + 1 )
Arr[0][2] = *(Arr[0] + 2) = *( *(Arr + 0) + 2 ) = *( *( &Arr[0] + 0 ) + 2 )
-----------------------
---배열에서 []숫자 생략
배열에서 []안에 숫자 생략이 가능한데 맨 왼쪽에 있는 숫자 하나만 가능하다.
다만 초기화시에만 가능.
int iaArr[ ] = {1, 2, 4, 5};
int iaArr[ ][2] = { {1, 2}, {3, 4} };
int iaArr[ ][2][2] = { { {1, 2}, {3, 4} }, { {1, 2}, {3, 4} } };
------------------
---포인터의 포인터
int iNum = 3; iNum -> 3
&iNum -> iNum주소
int * ip = &iNum; ip -> iNum주소
&ip -> ip주소
*ip -> 3
int ** ipp = &ip; ipp -> ip주소
&ipp -> ipp주소
*ipp -> iNum주소
**ipp -> 3
--------------------------
---배열 포인터, 포인터 배열
int arr[3][4]; // 배열
int * ptr2[4]; // 포인터 배열 , 이 변수 크기 16byte
int (*ptr)[4]; // 배열 포인터 (16byte씩 건너뛰는 포인터) , 이 변수 크기 4byte
int (* ptr)[4]; // 포인터방식 선언
int ptr[][4]; // 배열방식 선언
둘 다 4byte 크기의 포인터로 연산시 16byte씩 이동하는 같은 뜻이다.
ex) 예제 소스
#include <stdio.h>
void ShowArr2DStyle(int (*arr)[4], int column)
{
int i;
int j;
for(i = 0; column > i; ++i)
{
for(j = 0; 4 > j; ++j)
{
printf("%d ", arr[i][j] );
}
printf("\n");
}
printf("\n");
printf("arr : %d \n", sizeof(arr) );
}
int Sum2DArr(int arr[][4], int column)
{
int i;
int j;
int sum = 0;
for(i = 0; column > i; ++i)
{
for(j = 0; 4 > j; ++j)
{
sum = sum + arr[i][j];
}
}
printf("arr : %d \n", sizeof(arr) );
return sum;
}
int main()
{
int arr1[2][4] = {1,2,3,4,5,6,7,8};
int arr2[3][4] = {1,1,1,1,3,3,3,3,5,5,5,5};
ShowArr2DStyle(arr1, sizeof(arr1)/sizeof(arr1[0]) );
ShowArr2DStyle(arr2, sizeof(arr2)/sizeof(arr2[0]) );
printf("arr1의 합 : %d \n", Sum2DArr(arr1, sizeof(arr1)/sizeof(arr1[0]) ) );
printf("arr2의 합 : %d \n", Sum2DArr(arr2, sizeof(arr2)/sizeof(arr2[0]) ) );
return 0;
}
위의 예제처럼 이 차원 배열로도 사용할 수 있다.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140402 (main 인자전달, stream) (0) | 2014.04.02 |
---|---|
20140401 (함수 포인터, void 포인터) (0) | 2014.04.01 |
20140328 (const, 2차원배열) (0) | 2014.03.28 |
20140327 (포인터, 배열, call by address, call by value) (0) | 2014.03.27 |
20140326 (배열) (0) | 2014.03.26 |