<함수 포인터란?>


함수포인터는 함수의 주소를 저장하는 포인터 변수이다.

함수의 작동 원리에 대해서 간단히 살펴보면 컴파일 하면 함수의 정의는 기계어로 변환되고, 링크를 퉁해 실행 파일의 일부분이 된다. 함수를 실행하려면 메모리 주소를 알아야 하는데 그것이 함수 이름이다. , 함수 이름은 함수의 시작주소를 의미한다. 그렇다면 함수 포인터란 무엇일까?

위에서 말했듯이 함수의 시작주소를 저장하는 변수이다.

 

<실습>


 

 

-결과-


 

 

<함수 포인터 구조>

 

int (*pointer) (int, int)

int : 자료형

(*pointer) : 함수 포인터 이름, *과 같이 묶어서 사용 (주의!)

(int, int) : 인수 자료형 목록

 


<실습>


-결과-

LIST

<포인터란?>

 

포인터는 주소를 저장하는 변수이다. 변수? 그렇다. 변수는 어떤 데이터를 저장하기 위한 사용자들이 만든 공간으로 주로 우리는 숫자, 문자등을 저장하여 사용하였다.

그 개념을 그대로 변수에 주소를 저장하는 것이다.

 

포인터 변수의 선언에 대해 알아보자.

구조) int* pointer = NULL;

int : 포인터 변수는 주소를 저장하는 변수이다. 그런데 왠 int? 이 자료형은 pointer라는 포인터 변수에 주소를 참조했을때 나타내는 값이 int형이다 라는 의미이다.

pointer : 포인터 변수 이름

NULL : NULL로 초기화 함.

해석 : pointer라는 포인터 변수에 NULL이라는 아무것도 저장하지 않겠다라는 의미이다. , 빈깡통!

 

 

<실습>

실습을 통해 포인터 변수가 어떻게 사용되는지 알아보자

 


 

-결과-



 

결과값을 보면 포인터 변수의 값이랑 변수a의 주소와 같은 값이 출력되는 것을 알 수 있다.

이렇듯이 포인터 변수는 변수들의 주소를 저장하는 변수이다!

참고로 모든 포인터 변수의 공간은 4바이트이다. 주소체계를 저장할 수 있으면 되므로 4바이트면 된다.

 

<실습>

이번 실습에서는 포인터 변수를 이용하여 값을 참조해보자!

 



-결과-

 

위 코드를 살펴보자. num1, num2, num3의 변수를 각각 생성하고, 포인터변수 p만을 통해 모든 변수에 값을 대입하고 있다. 즉 간접 접근을 통해서 각각 대상이 바뀌고 바뀌는 대상에 대해 값을 넣어주었다.

 

 

 

<포인터를 사용할 때 주의할 사항>

 

1. 포인터 변수에 주소를 저장하지 않은 경우이다.

#include <stdio.h>

int main()

{

   int* p=NULL;

   *p=100;

   return 0;

}

이렇듯 포인터 변수 p에 아무 주소도 저장하지 않은 채포인터 변수의 참조 값에 100을 저장하려고 하면 당연히 에러가 난다. 왜냐? 참조하는 주소가 없는데 뭘 참조해서 넣겠다는건지...

 

2. 포인터 변수에 임의로 주소를 저장한 경우이다.

#include <stdio.h>

int main()

{

   int* p=124532;  // 이렇듯 임의로 주소를 저장한다.

   *p=100;

   return 0;

}

포인터 변수에 저장되는 주소는 메모리 상에 존재하는 주소여야 하기 때문에 124532이런 주소는 어떤 주소인지 알 수 없기 때문에 에러가 난다.



LIST

2차원 배열의 구조부터 알아보자 

int array [4][3];

int : 자료형

array : 배열 이름

[4][3] : *열로 총 12개의 배열의 칸을 확보, , 열의 길이는 무조건 설정해주어야 한다.

 

 

<2차원 배열 선언과 초기화>

int a1[4][3] = {{1,2}, {3}, {4}, {5}};




위에 선언한 2차원 배열을 구조적으로 살펴보면 이런식으로 배열이 만들어 진다.

앞에 [4]는 행을, 뒤에 [3]은 열을 말한다.

 

int  a2[4][3]={1,2,3,4,5}

 

2차원 배열의 원소를 저장하는 방법은 여러가지다.

일일이 모든 배열의 원소에 대입해줘도 돼고, 간략하게 괄호로 표현해도 된다.


<실습>

 

 

2차원 배열의 원소는 arr1[0][0]이런식으로 첫번째는 행, 두번째는 열로 표현이 된다.

 

-결과-





<2차원 배열 주소와 값의 참조>

 

2차원 배열의 주소를 참조하는 연산자는 &이다. 1차원 배열의 주소 연산자와 동일하다.

&연산자 자체가 주소를 나타낼 때 사용하는 연산자이기 때문이다.

, 이번에는 2차원 배열의 주소를 나열해보자. 좀 헷갈릴수도 있지만 자세히 이해하면 쉬울 것이다.

int arr[2][2]={1,2,3,4}; 이렇게 만들어다고 가정하자.

다음 표는 각 자리의 주소를 나타낸 것이다.

 


 

2차원 배열의 대표주소 : arr

첫 번째 행 대표주소 : arr[0] == *(arr+0)

두 번째 행 대표주소 : arr[1] == *(arr+1)

이렇게 구성된다. (실제 하드디스크에는 이렇게 2차원적으로 존재하지 않고 일렬로 존재하지만 논리적으로 설명하기 위해 이렇게 만든것이다. 앞으로도 이렇게 해석하는게 도움이 될 것이다.)

 

 

<실습>

 

-결과-


 

<*연산자>

 

*연산자는 주소안에 있는 값을 참조할 때 사용한다.

예를 들어 int arr[2][2] = {1,2,3,4}를 만들었다고 가정하자. 이때 주소를 표현할 때는 어떻게할까?

&arr[0][0]이면 첫행의 첫번째열의 주소를 출력한다. 그 주소의 값을 참조하고 싶을땐? *연산자를 사용하여 참조하면된다

*&arr[0][0] => 1출력

 

<실습>

-결과-



LIST

<&연산자>


주소 연산자인 &연산자를 사용하면 메모리 공간의 주소를 표현할 수 있다.

 

<실습>

-결과-

 

결과값에 보면 주소가 4만큼씩 떨어져서 찍혔다. 4만큼 떨어졌을까? 배열의 자료형을 보면 int형이기 때문에 4바이트씩 떨어진 것을 표현한것이다.

 

 

<배열의 이름은 시작주소>

배열 이름은 배열에 할당된 메모리 공간의 시작주소이다.


<실습>


-결과-


 

코드를 보면 arr은 배열의 시작주소이므로, 40fb00이라는 주소가 찍혔다. arr+1arr에서 +1만큼 다음 주소를 가리킨 것이다. 4바이트 건너뛴 주소를 의미한다

 

 

 

<*연산자>

*연산자는 메모리 공간에 저장된 값을 참조하는 연산자이다.

&연산자로는 주소를 알 수 있고, *연산자로는 그 주소에 들어있는 값을 알 수 있다.

 

<실습>

-결과-

 


이것을 활용하면 다음과 같은 공식?을 만들 수 있다.

*(array+i) == array[i] == *&array[i]

 

LIST

'Programming > C' 카테고리의 다른 글

C언어 - 포인터(Pointer)  (0) 2016.05.14
C언어 - 2차원 배열, 주소체계  (0) 2016.05.13
C언어 - 1차원 배열  (0) 2016.05.11
C언어 - 지역변수, 전역변수, 정적변수, 레지스터 변수  (0) 2016.05.10
C언어 - 함수란?  (0) 2016.05.09

<배열이란?>

 

같은 자료형을 가진 연속된 메모리 공간으로 이루어진 자료구조이다.

그렇다면 배열을 왜 사용할까?

어떤 학교의 학생들의 성적을 처리하기위해 변수를 많이 만들어야 한다. 50명이면... 변수를 50개 만들어야 한다.

 

#include <stdio.h>

int main()

{

   int stu1, stu2, stu3, ... ,stu50;

   ...

   return 0;

}

이런식으로 학생수만큼 변수를 만들어야 한다.

이런 변수를 배열로 만들면 아주 간단하게 정리할 수 있다.

 

#include <stdio.h>

int main()

{

   int stu[50];

   ...

   return 0;

}

이렇게 변수를 배열로 선언하면 stu[0], stu[1], ... ,stu[49] 이런식으로 사용할 수 있다. (배열은 0부터 원소가 시작하기 때문에 49에서 끝남)

 

 

구조)

int array [10]

int : 자료형

array : 배열이름

[10] : 배열 길이

 

 


<배열 선언시 주의사항>

 

1. 배열 원소는 0부터 시작한다.

int a[2];   // 배열길이는 2

a[0]=1;

a[1]=2;

a[2]=3;   // 에러.

 

2. 배열 초기화로 중괄호 할 때, 배열의 선언과 초기화가 개별적으로 이루어지면 안된다.

int a[3] = {10, 20, 30};

int a1[2];

a1={10,20,30}   // 에러개별적으로 초기화가 이루어지면 에러남.

 

3. 배열길이를 변수로 설정하면 안된다. 반드시 상수로 설정하자!

#define MAX 5

int main()

{

   int a=3;

   const int SIZE=10;

   int a1[MAX];   // 정상

   int a2[SIZE];   // 정상

   int a3[a];   // 에러. 배열 길이를 변수로 설정했기 때문!

}

 

<실습>



-결과-

 


<실습>

for문과 배열을 같이 사용하여 프로그래밍 해보자.

for문을 사용하여 배열의 합을 계산하는 프로그래밍을 만들어보자.


 


-결과-

LIST

<지역변수란?>

main()함수, 조건문, 반복문의 괄호, 함수의 매개 변수로 사용되는 변수이다.

<실습>




여기에서 main()함수의 지역변수 afunc함수의 지역변수 a는 완전히 다른 변수이다. 왜냐? 생성된 곳이 하나는 main()함수이고 하나는 func()함수이기 때문이다.

이 구문의 문법을 차례대로 해석해보자.

1. main()함수의 변수 a생성 후, 그 안에 10을 저장

2. func함수의 변수 a생성 후 5대입, b생성 후 10대입.

3. func함수의 return문을 만났을때 함수가 종료되면서 변수 ab의 메모리 공간이 소멸됨

4. 마지막으로 main()함수의 return 0;을 만났을때 main()함수의 변수 a값이 소멸된다.

 

-결과-

 

 

 

 

 

<전역변수란?>

 

전역변수는 지역변수와 다르게 중괄호 외부에 선언되는 변수이다. 어느 지역에서도 사용이 제한되지 않는 즉, 프로그램 어디에서든 접근이 가능한 변수이다.

초깃값을 지정하지 않아도 자동으로 값을 0으로 가지며, 초기화 할 때 반드시 상수로 초기화 해야한다.

<실습>


-결과-


 

 

 

 

<정적변수란?>

 

함수의 내부, 조건문, 반복문 등과 같이 중괄호가 있는 지역에서 전역 변수의 기능을 갖고 싶을 때 사용한다. 정적 변수는 전역 변수처럼 프로그램이 종료되지 않는 한 메모리가 소멸되지 않고, 초깃값을 지정하지 않아도 자동으로 0을 갖는다.

구문)

static int num;    // static을 사용해 정적변수를 만든다.


<실습>


 


abc()함수내에서 static을 사용하여 정적변수를 만들었다.

정적변수a는 마치 함수내에서 전역변수처럼 행동하는데 반해, b는 함수가 다시 호출될때 계속 초기화된다. 바로 이것이 정적변수a와 지역변수b의 차이다.

 

-결과-

 


 

정적변수에서 참고해야할 사항이 있는데, 정적변수는 괄호안에서만 전역변수처럼 사용하는 것이다. 괄호를 벗어나면 에러가 난다. 예를들어보자!

 

<실습>



-결과-

에러가 난다. 에러 메시지를 보면 다음과 같다. 


 

선언되지 않는 식별자는 변수의 선언이 되지 않아서이다. , 정적변수라는 것이 행동은 마치 전역변수처럼 한다고 하지만 그 범위는 괄호 안에서만이다! 꼭 잊어버리지 않도록~!

 

 

 

<레지스터 변수>

레지스터변수는 CPU내부의 임시 기억 장소 레지스터에 변수를 할당하여 값을 저장하는 변수이다. CPU내부에 저장하기 때문에 속도가 훨씬 빠르다.

그렇다면 지역변수와 레지스터 변수의 차이점은 무엇일까?

지역변수는 CPU외부에 있는 RAM에 변수를 할당하고 더 많은 CPU클럭을 사용하기 때문에 입출력 속도가 느리다.

레지스터 변수는 CPU내부의 임시 기억 장소인 레지스터에 변수를 할당하기 때문에 속도가 빠르다.

구문)

register int num;     // register를 사용하여 레지스터 변수를 선언하여 사용한다

LIST

'Programming > C' 카테고리의 다른 글

C언어 - 배열의 주소와 값의 참조, &연산자, *연산자  (1) 2016.05.12
C언어 - 1차원 배열  (0) 2016.05.11
C언어 - 함수란?  (0) 2016.05.09
C언어 - switch~case문, break문  (0) 2016.02.06
C언어 – do~while문  (0) 2016.02.05

<함수란?>

 

특정 작업을 수행하는 코드의 집합이라고 정의할 수 있다. 이런 함수를 사용하는 이유는 대단위의 프로그램은 수정과 유지보수가 어렵기 때문에 기능별로 세분화하는 것이 필요하다.

함수? ... 우리가 함수를 사용했던 적이 있었나있었다. 어디에? 바로 int main()함수이다.

 

함수의 구조)

int main(void)

int : 함수의 결과값에 대해 출력 형태를 나타내는 자료형이다.

main : 함수 이름이다.

(void) : 함수가 입력받을 형태이다.

 

, 그렇다면 우리가 직접 한 번 함수를 만들어보자.

빼기함수를 만들어 두 인자를 입력해서 두 인자를 빼는 함수를 만들어보자!

int minus(int x, int y)

{   // 함수의 시작

   int result;

   result = x - y;

   return result;   // 함수의 결과값으로 result값을 반환한다.

}   // 함수의 끝

이것을 해석하자면 minus함수를 사용할때 minus(2,1) 이렇게 사용했다고 가정하자.

2int x에 있는 x 저장되고, 1int yy에 저장된다. x=2, y=1이 된 것이다.

int result라는 변수안에 x-y를 수행한 후, result에 저장한다.

함수의 결과값으로 result를 반환하면 바로 1이라는 값이 반환된다.

 

<실습>



 

-결과-

 

함수에는 4가지의 형태가 있다.

1. 11형태

int sum(int x, int y)

{

   int result=0;

   result=x+y;

   return result;

}

main()함수 내에서 입력을 주어 대입할 수 있는 x, y값을 준다. 출력 형태까지 있어서 함수 내에서 return 문을 사용하여 결과값을 반환한다.

 

 

 

2. 10형태

int input(void)

{

   int num=0;

   scanf("%d", &num);

   return num;

}

main()함수 내에서 따로 입력받는 값이 없고, 10형태의 함수 내에서 입력 값을 정의해준다. 출력형태가 있기 때문에 return문을 사용하여 결과값을 반환한다.

 

 

 

3. 01형태

void print(int x)

{

    int a=x;

    printf("%d", %a);

 }

출력 형태가 없기 때문에 출력 자체의 값을 01형태 함수 안에서 만들어버린다. 입력형태가 있기 때문에 main()함수에서 입력값을 넘어준다.

 

 

 

4. 00형태

void output(void)

{

   printf("hello");

}

입력형태와 출력형태 모두 없어서 둘 다 main함수에서 값을 주지 않고 00형태에 함수 자체가 그 값을 나타낸다.

 

 

<실습>

함수의 4가지 형태에 대한 실습을 해보자!



-결과-

LIST

<switch~case>

 

<실습>

switch~case문을 통해 if~else if문으로 실습 했던 점수를 입력받아 성적(A~C)를 부여하는 프로그램을 짜보자.

 



 

if~elseif문에서는 범위 지정이 가능하였기 때문에 100~90점까지는 A, 89~80점까지는 B, 이런식으로 범위 지정이 가능하였다. switch~case문같은 경우는 범위 지정이 안되기 때문에 위의 프로그램을 해석해보면... switch(score) 있는score의 값이 90, 80, 70 이런식으로 딱딱 맞지 않는 경우에는 default값으로 받아 공부하세요!가 출력된다.

 

-결과-



 


이런식으로 80점을 입력했는데 B C모두 출력되었다... 어떻게 된 일일까! case 80이 맞다면 case80에 맞는 값만 출력되는 것이 아니고 그 밑에있는 case들까지 모두 수행된다.

만약에 90점을 입력했다면?? A B C입니다이렇게 모두 출력될 것이다.

이런 경우를 피하기 위해 break라는 구문을 사용해야한다.

 

 

<실습>

break문은 case문이 적합할 경우 수행하다가... break문을 만났을때 괄호를 빠져나온다, switch~case문을 빠져나간다.



 

 

-결과-



LIST

'Programming > C' 카테고리의 다른 글

C언어 - 지역변수, 전역변수, 정적변수, 레지스터 변수  (0) 2016.05.10
C언어 - 함수란?  (0) 2016.05.09
C언어 – do~while문  (0) 2016.02.05
C언어 - if문, if~else문, if~else if문  (0) 2016.02.05
C언어 – for문  (0) 2016.02.04

<do~while>

do~while문은 while문과 거의 흡사하지만 처음 한번 수행한다는 차이점이 있다

반복할 내용을 무조건 한 번 수행한 후조건식에 의해 그 다음 반복할 내용이 수행되는지 마는지 결정된다.

구문)

do

{

   반복할 내용

} while(조건식);

해석 : 처음 "반복할 내용"  한 번 수행한다그 후조건식에 의해 그 뒤로 계속 수행할 것인지 결정한다.

 

<실습>

 

-결과-




LIST

'Programming > C' 카테고리의 다른 글

C언어 - 함수란?  (0) 2016.05.09
C언어 - switch~case문, break문  (0) 2016.02.06
C언어 - if문, if~else문, if~else if문  (0) 2016.02.05
C언어 – for문  (0) 2016.02.04
C언어 – while문  (0) 2016.02.04

<if>

 

구문

if(조선식)

   내용;

해석 : 조건식이 참이면 내용을 수행해라.


<실습>



 

-결과-



 

<if~else>

구문)

if(조건식)

{

   조건식이 참 일때 수행할 내용

}

else

{

   그 밖의 내용을 수행할 내용(조건식이 참이 아닐경우 이 부분을 수행)

}

 

<실습>



-결과-



 

 

<if~else if>

 

구문)

if(조건문)

{

   조건문이 참일 때 수행할 내용

}

else if(조건문)

{

   if문의 조건문이 거짓이면서 else if문의 조건문이 참일경우 수행할 내용

}

else if(조건문)

{

   상동

}

...

else

{

   저 위의 조건문들이 모두 거짓일 경우 수행할 내용

}

 

 

<실습>




-결과-

LIST

'Programming > C' 카테고리의 다른 글

C언어 - switch~case문, break문  (0) 2016.02.06
C언어 – do~while문  (0) 2016.02.05
C언어 – for문  (0) 2016.02.04
C언어 – while문  (0) 2016.02.04
C언어 - 자료형 변환  (1) 2016.02.03

+ Recent posts