2011년5월9일...함수포인터, 배열, ATmega128 타이머/카운터 응용실습
★부드러우면서도 강하게... ★기억력 나쁘면 이해를 잘 하면되… ★프로그래머는 논리지능이 높을 수록 유리하다. 인간의 지능은 개인의 노력에 의해 발달할 수 있으니 잘하는 것에 빗대어 다른 지능을 발달시키면 된다. 예를 들어, 음악을 좋아하면 음악프로그램을 짜면 보다 빨리 논리지능을 높일 수 있다. 로봇을 좋아하면 임베디드(?) ★자신의 가치를 높여라~ ★노트필기 = 급여 (I like money!) ★비판을 위한 비판은 끌어내리기 위한 목적으로 하니 나쁘다. 질문을 위한 질문은 하지 말 것. (뜨끔) |
함수포인터 |
void test1( )
{
printf(“test1\n”);
}
void test2( )
{
printf(“test2\n”);
}
type |
상기 test1()과 test2()의 type은 모두,
void (*) ( )
이다.
전에 man 3 printf명령으로 보았던 printf()의 type은,
int printf(const char *, …); 으로 type은,
int (*) (const char *,…)
이다.
선언 |
<symbol table>
type | name |
void (*) ( ) | name |
void (*) ( ) | test1 |
void (*) ( ) | test2 |
int (*) (const char *,…) | printf |
표준라이브러리 함수 printf()를 제외한 사용자정의 함수 name, test1, test2가 모두 같은 type인 것을 알 수 있다.
호출 |
○함수포인터의 사용예
int (*handle) (const char *,…);
위와 같이 handle명의 함수포인터를 선언하고,
handle = printf; → handle은 화면에 문자를 출력할 수 있고,
handle = scanf; → handle은 키보드로 부터 문자를 입력 받을 수 있다.
이렇게 함수포인터로 printf()와 scanf() 이 두 함수를 자유롭게 호출할 수 있는 이유는 아래와 같이...
두 함수의 type이 같기 때문이다.
<symbol table>
type | name |
int (*) (const char *,...) | printf |
int (*) (const char *,...) | scanf |
배열 (Array) |
○같은 type의 변수가 여러 개 다다닥 붙어 있는 것을 배열이라 한다.
배열A는 변수a와 다르게 주소를 출력할 때 ‘&’(엠퍼센트)를 붙이지 않아도 된다.
배열A에서 A라는 이름자체가 시작주소이다.
<symbol table>
type | name | address |
int | a | 0xBFFFF848 |
int * | A[ ] | 0xBFFFF840 |
상기의 심볼테이블을 보면 배열A는 int형 포인터 type이고 주소를 보면 840으로 a의 주소 848과 8Bytes차이가 나므로..
A[2]의 크기는 8Bytes라는 것을 쉽게 알 수 있다. (stack구조라 처음 선언된 변수가 맨 아래에 놓인다.)
변수에 대입하는 것과 관련하여, a = 10은 가능하나 A = 10은 에러다. (상기의 에러메세지 참조)
A는 주소상수라 대입이 불가능하다.
10개의 원소를 가지는 A배열을 선언하여 시작주소와 배열전체주소, 각 자리별 주소를 알아보면,
<symbol table>
type | name | address | 비고 |
int | a | 0xBFFFF848 | &a = 주소 |
int * | A | 0xBFFFF820 | 주소 |
int * | &A | 0xBFFFF820 | 배열전체 |
int * | A + 1 | 0xBFFFF824 | 두 번째 원소주소 |
int * | &A + 1 | 0xBFFFF828 | 배열전체를 뜻함. |
int * | &A + 1 (@A[10]) | 0xBFFFF848 | 上同 |
int * | A[0] | 0xBFFFF820 | 값 |
int * | A[1] | 0xBFFFF824 | 값 |
배열의 값대입 |
int A[2] = {1, 2}; → A[0]에는 1이 들어가, A[1]에는 2가 들어간다.
*와 &은 전기의 (+)와 (-)극처럼 서로 상쇄된다. 따라서 다음과 같이 바꾸어 보면,
A[0] → *&A[0] → *(&A[0]) → *(A + 0)
배열에 값을 대입할 때 A[0] 또는 *(A + 0) 적어도 된다.
○ int A[2] = {1, 2}; 의 경우 A[2] ~ A[9]까지 모두 0으로 초기화된다.
○ int A[10] = { }; 의 경우 A[0] ~ A[9]까지 모두 0으로 초기화된다.
20110509_array/test.c |
차원 (Dimension) |
int array[10]; ← 1차원
int array[10][10]; ← 2차원
20110509/test_dim2.c |
임베디드C p.217 주소표기법 |
줄이동 | 칸이동 | 줄이동 |
array + 0 +1 array + 1 | array[0] +1 array[1] | &array[0] +1 &array[1] |
1줄의 주소 | 1개의 주소 | 1줄의 주소 |
포인터식 배열식
*(array + 0) + 1 → array[0] + 1
○ [ ] (대괄호) 한 개가 * 한 개
○ &array + 1 400Bytes이동 (배열전체)
DK-128..ATmega128 타이머/카운터0 |
○0.5초 지연
sleep(1000); → sleep(500);
○prescaler를 64에서 128로 바꾸라.
타이머/카운터 응용실습문제 |
1. 1초씩 FND숫자가 증가되도록 하시오.
5월6일 소스코드 참조…
2. 1초마다 FND값을 증가시키다가 60초가 되는 순간 LED를 하나씩 ON 하시오.
FND는 0으로 초기화된 후 다시 증가합니다.
참조 (Reference) |