'C로 보는 프로그래밍 입문'에 해당되는 글 14건

  1. 2009.05.02 재귀함수(Recursive) 2
  2. 2009.05.02 scope와 메모리 할당과정
  3. 2009.05.02 함수 일반론
  4. 2009.05.01 조건문
  5. 2009.05.01 다양한 반복문
  6. 2009.04.26 서식문자 2
  7. 2009.04.26 상수와 기본자료형
  8. 2009.04.26 비트단위 연산자
  9. 2009.04.26 진법의 이해
  10. 2009.04.19 변수입력과 연산
  11. 2009.04.19 변수와 연산자
  12. 2009.04.19 C의 기본단위
  13. 2009.04.19 언어와 컴파일
  14. 2009.04.19 시작하기 앞서 5


* 재귀 함수
  - 자기자신을 다시 호출하는 형태의 함수
  - 알고리즘 등에 유용하게 이용

 * 재귀 함수의 탈출 조건
  - 무한 재귀 호출을 피하기 위해서 필요
  - 자료구조와 알고리즘이 필요
  

 * 재귀 함수 디자인 사례
  - 팩토리얼(factorial) 계산을 위한 알고리즘
  예) n! = n*[(n-1)*(n-2)*(n-3)....*2*1] -> n! = n* (n-1)!
       f(n) = n이 1이상인 경우 : n*f(n-1);
       n이 0인 경우  : 1
  
  int f(int n)
  {
   if(n==0) rteturn1;
   else return n*f(n-1);
  }


예2)
 Recursive함수에 스스로 호출하는 명령문이 있으므로  loop되어 계속 출력된다.
 따라서 메모리는 가득차게되고(stack over flow) 자동으로 종료시킨다.

 //탈출의 예시
void Recursive(int n)
{
 printf("RecursiveRun! \n");
 if(n == 1) return;
 Recursive(n-1);
}

int f(int n)
{
 if(n==0) return 1;
 else return n*f(n-1);
}

int main(void)
{
 int a=3;
 int val;
 int result;

 //탈출 테스트
 Recursive(a);
 
 //팩토리얼 디자인
 printf("정수 입력 :");
 scanf("%d" , &val);
 if( val<0 )
 {
  printf("please input 0 over number. \n");
  return 1;
 }

 result =f(val); //factorial계산
 printf("%d!의 계산 결과 : %d \n", val , result );
 return 0;
}


 참고) 프로세스를 이해하기 위해서는 "컴퓨터구조"와 "운영체제"를 익혀야 한다.

Posted by 버터백통


참고) actionscript나 java등에는 함수에 직접 scope를  설정한다.
따라서 이 부분은 C의 설명이지만 scope의 개념이 중요하다.
예) private function aaa():void
{

}

* 변수의 범위(scope)
  - 지역변수(local)
    : 중괄호 내에 선언되는 변수
    : 함수가 호출될때 메모리에 선언되지만 함수가 종료되면 메모리에서 삭제 된다.
   예) int main()   
    {
     main의 함수 지역 안에 선언된 변수
     해당 함수안에서만 접근가능
     int a=10;
     return a;
     함수종료후 변수 a는 메모리에서 삭제
    }

  - 전역변수(Global)
   : 함수내에 선언되지 않는 변수
   예) int b=10;
    int main()   
    {
     변수 b는 어떤 함수에서도 접근이 가능한 전역 변수가 된다.
     int a=10;
    }

  - 정적 변수(static)
   : 함수내부,외부에 모두 선언 가능

  - 레지스터 변수(Register)
   : 선언에 제한이 많이 따름

 * 변수의 메모리 할당 과정 

  예)                                                        메모리
   int fct_one(void)                        과정1 |  undefined  |
   {                                                      |  undefined  |
    int one=10;                                       |  undefined  | 
    return 0;                                           |   val = 10  | main함수의 val이 메모리에 할당된다.
   }

   int fct_two(void)                         과정2 |  undefined  |
   {                                                      |  undefined  |
    int two=20;                                        |   one = 10  | 아직 main은 실행중이고 main에서 호출한다
    int three=30;                                      |   val = 10  | fct_one함수에 의해 변수 one이 할당된다.
    return 0;            
   }                                              과정3 |  undefined  |
                                                           |  three = 30 |
   int main(void)                                     |   two = 20  | fct_one함수는 종료되어 변수 one은 메모리에서 삭제
   {                                                      |   val = 10  | fct_two함수에 의해 two과 three가 메모리에 할당된다.
    int val=10; -> 과정 1
    fct_one();  -> 과정 2                과정4   |  undefined  |
    fct_two();  -> 과정 3                           |  undefined  |
    return 0;   -> 과정 4                            |  undefined  | fct_two가 종료되어 two과 three가 메모리에서 삭제
   }                                                       |  undefined  | main함수가 종료되어 val가 삭제


 * 다른 형태의 지역변수:for문이나while문 등에서 사용하는 변수
  - while,for,if문과 같은 문장에서 형성되는 지역 내에 선언되는 변수 : 플래시에서는 이와 상관없이 함수안에서 접근 가능


 * 지역 변수와 매개 변수
  - 매개변수도 지역 변수의 일종이다.


 * 전역변수(전체영역에서 접근가능 변수)
  - 프로그램 어디에서나 접근이 가능한 변수
  - 특정영역(함수,반복문..)에 속하지 않는다.
  - 프로그램이 종료될 때 까지 존재
  

 * 전역 변수의 또 다른 특징
  - 같은 이름의 지역변수에 의해 가려지기도 한다.


 * static 변수
  - 함수 내부 및 외부에 선언
  - 한번만 초기화 된다 : 전역 변수의 특징
   : 이후에는 값의 재설정이 언제든 가능하다. (플래시와 동일)
  - 함수 내부에서 선언될 경우 함수 내에서만 접근이 가능하다 : 지역변수 특징
  - 선언된 함수가 종료되더라도 메모리 공간에 남아있는다.
   : 재호출 시 값이 재설정 되지 않고 연산이 가능하다.(2번과 동일)
  
  * 플래시와는 다르다(scope에 따라..)
   - 플래시에서는 함수와 변수는 class 내부에서만 선언가능
   - 플래시는 언제든 값의 재설정이 가능하다.
   - 어디서든 접근이 가능하다.


 * 레지스터 변수(register 기억장치) :  처리속도가 빠르다.
  - CPU안에 들어있는 메모리(register)공간을 사용한다.
  - 극히 제한된 메모리 공간이므로 여유롭지 않다.
   : 만약 full인경우 register는 생략되어진다.
  - 컴파일러의 성능에따라 자동으로 레지스터 등록기능을 지원한다.

Posted by 버터백통

* 함수를 정의하는 이유
  - 모듈화(기능별 분리)에 의한 프로그램의 질 향상 가능
  - 유지보수 및 확장의 용이성
  - 문제 해결의 용이성("Divide and conquer!")

 * 4가지 형태의 함수
  1 전달인자(O) 반환값(O)

   int Add( int i, int j )
   {
    int result = i+j;
    return result;
   }


  2 전달인자(O) 반환값(X)
   void Result_Print(int val)
   { 
    printf("*** 반환값이 없고 매개변수 있는 함수 *** \n"); 
    printf("덧셈결과 : %d \n" , val);
    printf("end \n");
   }


  3 전달인자(X) 반환값(O)
   int Input_Scan(void)
   {
    printf("*** 반환값이 있으나 매개변수가 없는 함수 *** \n"); 
    int num=0;
    scanf("%d", &num);
    return num;
   }

  4 전달인자(X) 반환값(X)
   void Intro(void)
   {
    printf("*** 반환값과 매개변수가 없는 함수 *** \n"); 
   }

  int:반환형 main:함수이름(전달인자(매개변수) 입력형태)
  {
   함수몸체
   return 반환값:반환값이 있는 함수형태에 한함
  }

 * 함수의 원형
  문서 초반에 이후에 정의될 함수에 대한 정보를 제공
 C는 절차지향이므로 컴파일러 특성상 main에서 실행할 함수는 미리 설정되어있어야 한다.
 만약 main함수가 먼저 실행한다면 빌더다운 발생한다. 
 
 int Add( int i, int j )
 {
  int result = i+j;
  return result;
 }


 int main(void)
 {
  
  int d;
 d = Add(3,4); 
  printf("%d \n" , d);
  return 0;
 }
----------------------------------------------------------------------------------------------
일반적으로 main을 제일 위에 설정한다 이를 위해서는 아래의 본 코딩처럼 "함수의 원형" 선언을 해야 한다.

int Add( int i, int j );  //함수의 원형

int main(void)
{
 
 int a, b, result;
 a = 3;
 b = 4;

 result = Add(a , b);
 Result_Print(result);

 return 0;
}

int Add( int i, int j )
{
 int result = i+j;
 return result;
}



현재 함수의 원형인 경우 C에서만 필요한 형태이고 우리는 interface나 그냥 scope에 의해 설정과 접근이 용이하다. 따라서 actionscript에서는 원형이 필요없다.

Posted by 버터백통


 * if문
  - 조건에 만족되는 경우에 한해서 실행
  - 한 줄 명령문인 경우 중괄호 생략가능(actionscript도 동일)

  if(조건식){
   명령문
    }

  
  참고) else를 사용하여 if연산을 줄여준다.

 * if ~ else , else
  - 불필요한 연산을 줄여준다.
  - if else if...등 분기가 많으면 switch로 구현하는 것이 가독성이 좋다.

예) 계산기
int opt;
float val1,val2,result;

 printf("덧셈 1, 뺄셈 2, 곱셈3, 나눗셈4 \n");
 printf("선택하세요 \n");
 scanf( "%d" , &opt );

 printf("두개의 실수 입력 \n");
 scanf( "%f %f" , &val1 , &val2 );

 if( opt == 1 )
  result = val1 + val2;
 else if( opt == 2 )
  result = val1 - val2;
 else if( opt == 3 )
  result = val1 * val2;
 else
  result = val1 / val2;

 printf(" 결과 : %f \n" , result );



 * 조건연산자(삼항연산자)

  - if ~ else문을 간결하게 표현
  - 조건 ? A : B (조건을 만족하면 A 문장을 실행 및 반환 false이면 B를 실행 및 반환)

  X = (y<0)? 10 : 20;
  X = (y>0)? a*b : a/b;

  
  예) int i=5;
   X = ( i < 10 ) 10 : 20;
   i는 10보다 작은 5이므로 조건식을 만족하여 X의 값은 10을 반환 받게 된다.

예) 부호표시
 int x;
 char ch;

printf("정수 입력 : ");
 scanf("%d" , &x);

 ch = (x<0) ? '-' : '+';
 ( ch == '+' ) ? printf("양수 \n") : printf("음수 \n"); 
 printf("절대값 : %d \n" , (x<0) ? -1*x : x);


 
* switch문 : 명령문 선택 실행
  - if문보다 간결하다.
  - 비교연상이 올 수 없다. switch문의 한계
  예)
 switch( 인자 : int 또는 char ){
   case 1:
    인자가 1인 경우 실행
    break;
   case 2:
    인자가 2인 경우 실행
    break;
   default :
    해당되는 case가 없을시 실행
    }

예) 입력된 문자로 단어출력
int n;
char sel;

printf("오전(M), 오후(A), 저녁(E) \n");
printf("확인(q to quit) : ");
scanf("%c",&sel);

 switch(sel)
{
 case 'M':
 case 'm':
  printf("Morning. \n");
  break;
 case 'A':
 case 'a':
  printf("Afternoon. \n");
  break;
 case 'E':
 case 'e':
  printf("Evening. \n");
  break;
 }
 


 참고)
break문
  
- 반복문에서 빠져 나올때 사용
   : 호출되면 반복문에서 탈출

continue문
  - 다음 반복문으로 넘어 갈때 사용
   : 반복문안에서 조건을 만족하면 아래에 있는 루프문을 실행하지 않고 반복문 처음으로 돌아가 실행 

참고) 함수에서 탈출하기 위해서는 return을 사용

Posted by 버터백통

 * 반복문의 기능
  - 특정 영역을 특정조건이 만족하는 동안 반복 실행

 * 3가지 형태 반복문 : 중괄호는 반복의 범위를 결정 1개의 라인은 중괄호 생략가능
  - while
  - do ~ while
  - for

 * while :
  while(반복 조건검사)
  {
   반복 내용 
   조건변수 연산 : 설정하지 않으면 loop에 빠짐
  }

  예) while( i<10 )
   {
    i++;
   }

 
 * do ~ while : 경우에 따라 한번 먼저 실행하는 것이 유용한 경우가 있지만
                         대부분 while과 do while은 별차이가 없다.

  - do ~ while문은 일단 한번 실행하고 조건검사를 실행
  - while문과의 차이점은 조건검사를 실행하는 시점에 차이가 있다. 

  do
  {
   반복 내용
  }whle
( 반복 조건검사 );

예)
 i=1;
 printf( "출력하고자 하는 구구단, 몇 단?" );
 scanf("%d" , &val);
 do
 {
  printf("%d * %d = %d \n" , val , i , val*i);
  i++;
 }while(i<10);
 
 printf("*** escape while *** \n"); 
 printf("%d * %d = %d \n" , val , i , val*i);


 * for문
  - 초기문,조건문,증감문 모두를 기본적으로 설정
  - 가장 많이 사용되는 반복문
  for( 초기문; 조건문; 증감문 )
  {
   반복 내용
  }


 * 반복문의 중첩

  - 반복 구조 내에서 또하나의 반복 구조를 형성
예)
i=0;
j=0;
 for(i=0; i<3; i++)
 { 
  printf("\n\n현재 i는 %d입니다. \n" , i);
  for(j=0; j<2; j++)
  {
   printf("현재 j는 %d입니다. \n" , j);
  }
 }


Posted by 버터백통


 * 쌍따옴표는 문자열의 시작과 끝을 알린다.
 printf( "그녀는 "하하" 하고 웃었다." );
 위의 "하하"는 정체불명이다. 따라서 "그녀는 '하하' 하고 웃었다."로 교정해야 한다.
 만약 쌍따옴표를 사용하기 위해서는 아래의 특수문자(\")를 이용한다.

 * printf는 특수문자 출력이 가능하다. 
  특수문자      의미
   \a             경고음 발생
   \b             백스페이스
   \f              폼피드
   \n             줄바꿈
   \r              캐리지 리턴
   \t              수평 탭
   \v             수직 탭
   \\            백슬래시(\)
   \'              작은 따옴표
   \"             큰 따옴표

 

 * 서식문자 : 출력의 형태를 지정하는 의미
  - %c(단일문자), %d(정수), %f(실수:주로 float에 사용), %s(문자열) : 가장많이 사용되는 서식 문자.
    - %o(8진수정수) , %u(10진수정수) , %x(16진수정수) , %X(16진수정수) : 부호없는 정수형 출력(unsigned)
  - %e, %E(주로 double에 사용) : 부동소수점 표현방식(실수)에 의한 출력
   예) 3.1245e+2 -> 3.1245*10^+2
    2.4e-4  -> 2.4e*10^-4

  - %g,%G : 소수점이하 6자리의 여부를 체크하여 %f,%F(6자리미만)나 %e,%E(6자리이상)로 출력
   예) "%g" , 0.00123  -> 0.00123  : %f로 출력
    "%G" , 0.000123  -> 0.000123  : %F로 출력
    "%g" , 0.0000123 -> 1.23e-005 : %e로 출력
    "%G" , 0.00000123 -> 1.23E-006 : %E로 출력


  참고) %x와 %X는 0x이후의 값 중 알파벳이 대문자인 경우 0x8A는 %X이며 0x8a인 경우 a는 %x이다.

 * 필드폭 지정
  - 서식을 이용하여 폭 지정 가능

  서식문자      출력 형태
  %8d              필드폭 8칸을 확보하고 오른쪽 정렬
  %-8d             필드폭 8칸을 확보하고 왼쪽 정렬
  %+8d             필드폭 8칸을 확보하고 오른쪽 정렬하고 양수는 +, 음수는 -를 붙여서 출력
  결과는 숫자만큼 칸을 띠운 다음 정렬에 의해 띠워진 칸안에서 왼쪽 또는 우측 정렬


 * scanf함수의 입력 %d,%o,%x 형태 정의
  - 데이터를 입력받는 형태를 설정한 서식(%d,%o,%x...)에 의해 저장
  - 실수입력에 주의사항
   : 정밀도
   : 소수 6자리 이하의 실수 입력 시 %f사용
   : 소수 6자리 이상의 실수 입력 시 %e사용
   : 단 double형 변수를 사용하는 경우에는 서식문자 %le를 사용
    

Posted by 버터백통

 * 기본자료형과 표현범위 (ANSI:표준) : int,long은 시스템에 따라 크기가 다를 수 있음
  - 메모리 공간을 적절히 사용하기 위해 다양한 자료형을 제공한다.
  - 작은 메모리 공간에 큰데이터를 저장할 경우 손실발생
    (1byte에 100만을 대입..100을 대입하려면 4byte이상 되어야 한다.)


  자료형(정수형)          할당 메모리 크기           표현 데이터 범위
  char                                      1byte                         -128 ~ 127 (2^8 : 256가지)
  short                                     2byte                         -32768 ~ 32767 ( 2^16 )
  int (과거 2byte였음)                 4byte                         -2147483648 ~ 2147483647 ( 2^32 )
  long(4byte~이상)                    4byte                         -2147483648 ~ 2147483647 (4byte인 경우)

  
  자료형(실수형)          할당 메모리 크기           표현 데이터 범위
  float                                      4byte                          3.4 * 10^-37 ~ 3.4 * 10^38
  double                                  8byte                          1.7 * 10^-307 ~ 1.7 * 10^308
  long double                           8byte이상                    시스템에 따라 차이가 많이 나타남

 * sizeof() 연산자 
  - 피연산자의 메모리 크기를 반환
  - 피연산자로 자료형의 이름이 올 경우 괄호를 반드시 사용
  - 그 이외의 경우 괄호의 사용은 선택적

 * 자료형 선택의 기준
  - 정수형 데이터의 경우
   : 컴퓨터는 내부적으로 int의 연산을 가장 빠르게 처리
   : 범위가 int형 변수를 넘어가는 경우 long으로 선언

  - 실수형 데이터의 경우
   : 선택의 지표는 정밀도
   : 최근은 일반적으로 double을 사용(값의 크기가 크므로 보다 정확함)
   
     자료형                                    정밀도
     float(4b)                                     소수점 이하 6자리
     double(8b)                                 소수점 이하 15자리(AVM1에서 사용되는 소수점 수식 데이터형)
     long double                                double의 정밀도와 같거나 크다.

  - unsigned가 붙어서 달라지는 표현 범위
   : MSB까지도 데이터의 크기를 표현
   : 양의 정수로 인식
   : 실수형 자료형에는 붙일 수 없다

  자료형(정수형)            할당 메모리 크기              표현 데이터 범위
  char                                      1byte                               -128 ~ 127
  unsigned char                        1byte                               0 ~ ( 127 + 128 )
  short                                     2byte                               -32768 ~ 32767
  unsigned short                       2byte                               0 ~ ( 32767 + 32768 )
  int                                         4byte                               -2147483648 ~ 2147483647
  unsigned int                           4byte                               0 ~ ( 2147483647 + 2147483648 )
  long                                      4byte                               -2147483648 ~ 2147483647
  unsigned long                        4byte                                0 ~ ( 2147483647 + 2147483648 )
  
 * 문자표현을 위한 ASCII코드 등장 :
컴퓨터는 2진수만 처리 가능하므로 문자와 2진수사이에 mapping을 처리한다.

  예) A:65 , B:66 (A 65 부터 Z까지 1씩 증가, 소문자는 a:97부터 1씩 증가)
  - 미국 표준 협회 ANSI에 의해 정의
  - 컴퓨터를 통해서 문자를 표현하기 위한 표준
  - 문자와 숫자의 연결 관계를 정의

 * ASCII코드의 범위
  - 0이상 127이하
  - char형으로 처리하는 것이 합리적 :  정수는 int가 합리적 이유는 연산을 위함, char는 연산을 하지
    않으므로 1byte로 처리

 * 문자의 표현

  - 따옴표( '' )를 이용, C에서는 쌍따옴표("")를 사용하지 않는다.
  예) char ch1 = 'a' -> 내부적으로 65의 값을 갖는 2진수로 저장된다.
 
 * 리터럴(Literal) 상수
  - 이름을 지니지 않는 상수
  예) int a = 30(상수) + 40(상수) => a에는 우항의 두 값을 메모리에 등록되어 CPU가 연산한 후 70이 대입
  참고) 30과 40이라는 값은 이름이 없으므로 재사용 할 수 없다.
    
  - 상수도 메모리 공간에 저장되기 위해서 자료형이 결정된다.
  예) char c='A'  : 문자상수
   int i=5   : 정수상수
   double d=3.15 : 실수상수
  참고) 좌항과 우항의 사용메모리는 서로 다르며 별도로 데이터 타입이 결정된다.
  증명) float f = 1.7 * 10^308 // 실제 메모리에 등록된 우항(double)의 크기가 좌항에서 선언한 float보다 크므로 값은 잘려서 들어가게 된다.
   
 * 심볼릭 상수
  - 이름이 있는 상수
  - const를 이용하여 상수화
  - 매크로를 이용한 상수화
  예1) const int MAX = 300;
         const double PI=3.1415;
  참고) 상수는 변수와 구분하기 위하여 대문자로 표기하는 것이 관례
 
  예2) const int MAX //상수선언(가비지 값으로 채워짐)
    MAX = 300;    //상수에 값 대입 불가.

 
 * 자료형 변환의 형태
  - 자동형 변환(묵시적 형 변환) : 자동적으로 발생하는 형태의 변환
  - 강제형 변환(명시적 형 변환) : 개발자가 명시적으로 형 변환을 요청
  
 * 자동형 변환이 발생하는 상황1
  - 대입연산 시
  예) 1.3 + 1 => 연산불가..따라서 자동으로 자료형으로 변환 후 연산가능
   int n = 5.25 //소수부의 손실( 5 ) - warning발생
   double d  = 3 //값의 표현범위( 3 -> 3.0.. )가 넒으므로 이상없음
   char c = 129 //상위비트 손실( -127 ) : 4byte에서 1byte에 저장하므로 앞의 3byte는 손실 - warning발생


 * 자동형 변환이 발생하는 상황2
  - 정수의 자동 승격에 의해(int현 연산이 빠른 이유) : 정수형 연사 자체를 int로 단일화 시켰기 때문이다.
  예) char c1 = 10, c2 = 20;
   char c3 = c1+c2 //c1과 c2는 int로 형변환 연산한 30을 다시 char로 변환하여 c3에 대입
  
 * 자동형 변환이 발생하는 상황3
  - 산술연산 과정에 의해여
  예) 5.5(double) + 7(int)    : int를 double로 변환(데이터의 손실을 자동으로 최소화 시킨다.)
   3.14f(float) + 5.25(double)   : float를 double로 변환(데이터의 손실을 자동으로 최소화 시킨다.)

  참고) [정수] char(1) -> int(4) -> long(4) -> [실수]  float(4) -> double(8) -> long double(8이상)
     순으로 변환하는 것이 손실을 최소화 시킨다.(바이트의 크기가 큰쪽으로 변환이 일어난다)

 * 강제형 변환
  - 프로그래머의 요청에 의해 변환
  예) float f = (float)3.14  : f의 값은 3.14
   double e1 = 3 + 3.14  : e1의 값은 6.14
   double e2 = 3 + (int)3.14 : e2의 값은 6

참고) 아스키 코드표


Posted by 버터백통

* 비트단위 연산
  - &연산자 : 비트단위 AND
   0 & 0 : return 0
   0 & 1 : return 0
   1 & 0 : return 0
   1 & 1 : return 1

  ex)
   int a = 15  // 00000000  00000000  00000000  00001111
   int b = 20  // 00000000  00000000  00000000  00010100
   int c = a & b
   출력 결과 c = 4로 표현

           00000000  00000000  00000000  00001111
    AND 00000000  00000000  00000000  00010100
  ----------------------------------------------
           00000000  00000000  00000000  00000100 : 4


  - |연산자(OR) : 둘중에 하나라도 1(true)인경우에 반환
   0 | 0 : return 0
   0 | 1 : return 1
   1 | 0 : return 1
   1 | 1 : return 1

  ex) 
     int a = 15  // 00000000  00000000  00000000  00001111
     int b = 20  // 00000000  00000000  00000000  00010100
   int c = a | b
   출력 결과 c = 31로 표현

         00000000  00000000  00000000  00001111
    OR 00000000  00000000  00000000  00010100
  ----------------------------------------------
         00000000  00000000  00000000  00011111 : 31

 

  - ^연산자(XOR):두개가 서로 다른 경우에만 반환
   0 ^ 0 : return 0
   0 ^ 1 : return 1
   1 ^ 0 : return 1
   1 ^ 1 : return 0

  ex) 
     int a = 15  // 00000000  00000000  00000000  00001111
     int b = 20  // 00000000  00000000  00000000  00010100
   int c = a ^ b
   출력 결과 c = 27로 표현

         00000000  00000000  00000000  00001111
    OR 00000000  00000000  00000000  00010100
  ----------------------------------------------
         00000000  00000000  00000000  00011011 : 27


  
   
  - ~연산자(NOT): 값을 반대로 바꾸어 준다
   ~0 : return 1
   ~1 : return 0
   

  ex) 
     int a = 15  // 00000000  00000000  00000000  00001111
     int b = ~a  
   출력 결과 b = 27로 표현

         00000000  00000000  00000000  00001111
    -> 11111111  11111111  11111111  11110000 : (1의 보수, 부호비트도 반전)
   ->  10000000  00000000  00000000  00001111 : (1을 더함)
   ->  10000000  00000000  00000000  00010000 : (값은 -16 )

 


  - <<연산자: 왼쪽 shift연산
   a << b : a의 비트들을 b칸씩 왼쪽으로 이동한 값을 반환
   8 << 2 : 8의 비트들을 왼쪽으로 2칸씩 이동한 값을 반환
   

  ex)
     int a = 15  // 00000000  00000000  00000000  00001111
     int b = a<<2 //a의 비트들을 왼쪽으로 2칸씩 이동
   출력 결과 b = 60로 표현

        00000000  00000000  00000000  00001111
    -> 00000000  00000000  00000000  00111100 : ( 결과 : 60 )  

 

  - >>연산자: 오른쪽 shift연산
   a >> b : a의 비트들을 b칸씩 오른쪽으로 이동한 값을 반환
   8 >> 2 : 8의 비트들을 오른쪽으로 2칸씩 이동한 값을 반환
   

  ex) 
     int a = -10  // 11111111  11111111  11111111  11110110
     int b = a>>2 //a의 비트들을 오른쪽으로 2칸씩 이동
   출력 결과 b = 60로 표현

        11111111  11111111  11111111  11110110
    -> 0011111111  11111111  11111111  111101 : (0으로 채우는 시스템)
    -> 1111111111  11111111  11111111  111101 : (1로채우는 시스템)
  =====================================================
  참고) shift연산자는 시스템(처리방식)에 따라 결과 값이 달라진다

Posted by 버터백통


* 진법의 이해
  - n진수의 표현방식 : n개의 문자를 이용해서 데이터를 표현
    | 0 1 | 2 3 4 5 6 7 8 9 | a b c d e f |
    |2진수|                   |                 |
    |         10진수          |                 |
    |                16진수                      |

 * 2진수와 10진수
  - 10진수 : 0~9를 이용한 데이터표현
  - 2진수 : 0,1을 이용한 데이터 표현
  - 컴퓨터는 내부적으로 모든 데이터를 2진수로 처리
  - 숫자나 문자형은 같은 데이터의 2진수값을 갖지만 Int와 String에 의해 캐릭터셋을 사용
    |...  0     /1바이트   0     0    0   0   0  0  0  0  |
      256      /            128   64  32  16  8  4  2  1   ->값의 표현(2의 배수로 증가)
    위에서 보듯이 1바이트는 128개의 값을 표현

   예) 00000000 : 0
    00001001 : 8 + 1 = 9
    10010010 : 128 + 16 + 2 = 146
    11111111 : 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255
    따라서 표현의 범위는 00000000 ~ 11111111으로 0부터 255인 256개를 표현
 
 * 16진수와 10진수
  - 0~9 , a , b , c , d , e , f를 이용한 데이터의 표현
  예) e   : 14
   f   : 15
   10  : 16
   11  : 17
   12  : 18
   13  : 19
   64  : 100
   f(15)이후의 값은 10진수의 10부터 증가처럼 10에서 1씩 값이 증가한다.

 * 비트와 바이트
  비트는 1자리수로 2진수 0, 1을 담는 표현의 최소단위
  바이트는 8비트를 1바이트로 설정
  바이트는 0~255의 256개의 값을 표현

 * 프로그램상에서 8진수와 16진수 표현
  - 8진수는 0으로 시작
  - 16진수는 0x로 시작
  예) a = 10 : 10진수의 10
   b = 0xa : 16진수의 10
   c = 012 : 8진수의 10

 * 정수의 표현방식
  - MSB(most significant bit:가장 중요한 비트) : 가장 왼쪽비트로서 부호를 표현(0은 양수 1은 음수)
  - MSB를 제외한 나머지 비트 : 데이터의 크기를 표현
       |   0   |    0  0  0  0  1  0  1   |
      msb(양수)  data 크기(5) : 00000101 : 5
  
    음수는 양수에 1의 보수를 취하고 1을 더한다.
       | 1 | 1 1 1 1 0 1 0 | -> 5의 1의 보수
       | 1 | 1 1 1 1 0 1 1 | -> 보수에 1을 더함
     msb(음수)  data 크기(5) : 11111011 : -5

  예) 00110011 : 51
   11110000  -> 1의 보수 : 00001111 -> 00010000 : 최초 msb는 1이므로 -(16)
   1의 보수에 1을 더한다.
      00001111
    + 11111111
    -----------
      00010000  1+1은 10, 1이 올라가서 1+1+1이므로 0, 해당 자리에서 1이 또 올라감

 * 실수의 표현 방식
  - 오차가 존재하는 단점이 있지만 데이터의 크기면에서는 효율적이다.(모든 컴퓨터)
    
           [ msb(1.m)*2^(e-127) ]
    | 1 | 0 0 0 0 0 0 1 | 0  0 0 0 0 1 0 1 |
         |       m         |         e            |

   위의 경우 식은 -(1.1)*2^(5-127) -> -(1.1)*2^(122) = -5.84860318145363e+36

Posted by 버터백통


 앞서 살펴본 printf는 데이터를 화면에 출력하는 함수이며 scanf()함수는 키보드로 부터 얻은 값을 제공한다.
 scanf("%d" , &val) : scanf(키보드로 부터 10진수 정수로 입력받음 , 변수val에 저장)
 scanf를 호출하면 키보드 입력 시 까지 대기(커서가 scanf호출부분에서 대기하고 있다)


# include <stdio.h>

int main(void)
{
 int result;
 int val1 , val2;

 printf("첫 번째 숫자 : ");
 //&에 의해 val1의 주소값으로 반환
 scanf("%d",&val1);

 printf("두 번째 숫자 : ");
 scanf("%d",&val2);

 result = val1 + val2;
 printf( "%d + %d = %d \n" , val1 , val2 , result );

 //한번에 두개씩 값을 입력
 printf("숫자 둘을 입력하세요 : ");
 //두개 이상을 입력하더라도 엔터,탭,스페이스 등 공백에 의해 데이터들이 구분이 된다
 scanf("%d %d", &val1 , &val2);
 result = val1 + val2;
 printf( "%d + %d = %d \n" , val1 , val2 , result );

 return 0;
}

Posted by 버터백통


어떠한 값을 활용하기 위해서는 연산결과를 저장할 필요가 있다. 이때 활용하는 개념이 변수이다. 어떠한 값을 담는 그릇이자 그를 참조할 수 있는 경로가 되는 것이다. 변수나 값들은 메모리에 등록되고 연산은 cpu와 메모리사이에서 정의된 데이터를 cpu에서 연산한다.

int a = 3+4;
위와 같은 경우 좌측부터 3을 메모리에 등록한다. 이후 4를 메모리에 등록한다. cpu는 메모리에서 3과 4를 가져다가 +을 한다. 이를 활용하기 위해서는 변수(a)에 값을 저장한다. 나중에 상수부분에서 다루겠지만 3과 4는 상수에 해당한다.

 *변수 : 데이터를 저장 할 수 있는 메모리 공간에 붙여진 이름
  - 정수형 : char , int , long
  - 실수형 : float , double

* 연산
 = : 대입
 + : 덧셈
 - : 뺄셈
 * : 곱셈
 / : 나누기
 % : 나머지

코딩시 주의할 점)
실행문에서는 반드시 아래처럼 선언부와  실행부가 나뉘어져서 코딩되어야 한다.
만약 중간에 실행부나 대입부분이 있으면 컴파일 에러를 발생한다.

ex)
int val;
val = 3+4; 또는 printf("val = %d \n" , val); 등과 같은 명령문
int a, b;
int c=30, d=40; 와 같은 선언부
>> 에러 발생...


따라서 함수 초반에 모든 선언부를 마치고 실행부를 넣으며 값을 재설정하고자 할때는 a=100등과 같이 대입식을 사용하면 된다.
ex)
//선언부
int val;
int a, b;
int c=30, d=40;
//실행부
val = 3+4;
a = 10;
b = 10;

위처럼 선언부와 실행부를 분리하면 컴파일에러가 생기지 않는다. 이러한 것을 보면 액션스크립트는 정말 잘 만든언어인 것 같다.

변수선언시 같은 데이터 타입이면 컴머연산자를 사용하여 여러개가 동시에 선언 가능하다.
예)
int a, b; //쓰레기값으로 초기화;
int c=30, d=40; //선언과 동시에 초기화
int result1, result2, result3;

* 논리 연산자(&& , || , !)
- &&는 좌우 양족 항이 모두 true를 만족해야 한다.
- ||는 좌우 한쪽항만 true를 만족하면 된다.
- !는 true를 fasle로 false를 true로 변환한다.
( !(10 ) ) : !는 true<->false 변환이므로 10은 0이 아닌 true이며 true를 !에 의해 false로 변환
플래시에서도 같은 결과 출력
var a:int = 10
var res:Boolean = a
trace(res) -> true

var a:int = 10
var res:Boolean = (!a)
trace(res) -> false

* 비교 연산자(<,>,==,!=,>=,<= 등)
0을 제외하고 모든 값을 true로 인식 -3 = true, 10=true그러나 일반적으로 0은 false 1은 true로 사용한다.
(flash도 같은 방식이다.)

* 컴머연산자
,를 사용하여 연산 : 여러 연산을 구분하여 실행하도록 함
  - 둘 이상의 변수 동시 선언 시
  - 줄 이상의 문장을 한줄에 선언 시
  - 함수의 매개변수 전달 시

* 연산자의 결합성 : 우선 순위가 같은 것이 둘이상 등장하면 왼쪽에서 오른쪽으로 실행
  +,- 보다는 *,/를 먼저 실행
  3+4*5/2-10인 경우 4*5 -> 20/2 -> 3+10 -> 13-10 = 3;
  괄호()를 사용하여 코드의 가독성으로 높이고 결합성을 결정한다.

Posted by 버터백통


C의 기본단위는 함수이다.(함수  :어떠한 기능이 있고 입/출력이 존재)

* 함수의 형태
int<출력형태> main<함수이름>( void )<입력의 형태>
{<함수몸체시작>

 <함수몸체 : 기능(명령문)>
 printf("Hello, World! \n");
 printf("Hi, Gary \n");
 return 0;
}<함수몸체종료>

예) 아래는 화면에  Hello, World! 줄바꿈하고  Hi, Gary 를 출력하는 예제이다.
void main( void )
{
  printf("Hello, World! \n");
  printf("Hi, Gary \n");  
}

* 세미콜론
  ; 는 명령문의 실행완료 지점, 명령문의 끝을 마무리

 

* 서식문자
 %d 는 출력 대상의 출력 형태를 지정하기 위한 문자

[ C FULL CODE ]
//표준 라이브러리 등록
#include<stdio.h>

//c에서는 모든 프로젝트에 main을 선언하고 컴퓨터에서는 main을 먼저 호출하도록 정의되어있다
int main( void )
{
//printf()라는 함수 호출 : 표준 라이브러리에서 제공하는 함수
//printf는 화면에 내용을 출력하는 함수

printf( "Hello, World! \n" );  
printf( "하이~ 버터백통 \n" );

 //서식문자를 이용해 여러 인자를 넣을 수 있다.
printf( "%d \n" , 1234 ); //%d는 "1234"라는 "10진수 정수형태"로 표현   
printf( "%d %d %d \n" , 10 , 20 ); //3번째 %d는 가비지 값을 표현..따라서 정확한 값을 지정해야 한다
printf( "%d %d %d \n" , 10 , 20 , 100 ); //3번째 %d까지 정상적으로 표현
printf( "%d %s \n" , 10 , "원" ); //2종류의 형태로 표현 "10진수 정수형태"와 "문자열"로 표현
 
printf("****************************\n");
printf("my age : %d \n" , 20);
printf("%d is my point \n", 100);
//printf("Good\nmoning\neverybody\n");
//위와 동일코드
printf("Good\n");
printf("moning\n");
printf("everybody\n")

//함수종료, 값을 반환
 return 0;      
}



C에는 여러가지 서식문자가 있다 이들은 나중에 printf와 scanf 함수에서 다루어 본다. 우선 이번은 C를 코딩해서 빌드해보는 것까지가 중요하다.
Posted by 버터백통

컴퓨터가 이해할 수 있는 언어는 2진수 뿐이다. 1940년대에는 2진수로 개발을 하였다고 한다...
그러나 언어가 발달하면서 점차 사람이 이해하기 쉬운 언어가 등장하게 되었고 사람이 이해하기 쉬울 수록 High Level언어이고 포트란 코볼등이 이에 해당한다. 중간에 Middle Level언어가 있다 그것이 바로 C이다. 그 아래로는 Low Level언어가 있으며 이에는 어셈블러가있고 Low level일 수록 컴퓨터가 이해하기 쉬운 언어이다.

이처럼 다양한 형태의 언어가 있는데 이들 모두 컴퓨터가 이해 할 수 있는 기게어로 제작되어야 한다. 따라서 인간중심의 프로그래밍 언어는 컴파일러라는 것을 가지고있다. 이를 통해 컴퓨터가 이해하기 쉬운 기계어로 변환을 하게 되며 컴파일된 언어는 결국 모두 한가지 기계어로 통일된다는 것이다. 이는 아주 중요한 사실이다. 가령 액션스크립트에서 어떠한 변수에 A이라고 저장한다면 이는 아스키코드로 65라고 저장된다. 또한 자바나 C등 기타언어에서 똑같이 변수를 선언하고 A를 저장한다면 역시 같은 65를 저장하게 되고 이를 기계어로 컴퓨터에서는 해석된다. 따라서 같은 메모리를 사용하는 환경에서는 저장된 메모리 주소를 알게되면 서로 다른 언어간에 같은 값을 주고 받는 통신이 가능하게 되는 것이다.

컴파일러의 역할을 수많은 언어들에 맞게 제작되어 있고 다양하지만 결국 한 개의 언어로 통일화 시켜 컴퓨터가 이해 할 수 있도록 기계어로 번역하는 것이다.
Posted by 버터백통

이제 C에대해서 포스팅을 하려고 합니다..액션스크립트 레시피에서 쌩뚱맞게 C냐구요?
물론 저도 C에 대한 욕심은 없습니다. 꼭 배우고자 한다면 MFC정도일까요?
간단히 swf를 감싸고 인스톨 할 수 있는 정도만 욕심내고 있습니다...그러나 최근 모바일쪽 작업을 하다가 보니 C를 접할 기회가 조금 있었습니다...학교 수업중에 C와 C++을 다루고 있었는데...아주 조금 알고 있는 개념만으로 호스트개발자와 같이 설계를 하고 통신을 다루며 잘못된 부분을 짚어가며 어떠한 문제를 해결한 일이있었는데,
스스로 너무 놀랐고 대단했습니다.. 

아..언어가 다 비슷하구나...란 생각을 하고 엄청 어렵게만 느껴지던 C에 대해 호기심과 도전해볼만한 자신감이
붙었습니다..물론 C로 뭘 만들생각은 없구요...그렇게 시작해 조금씩 공부를 하다보니 그동안 구멍이 뚫렸던 부분들...그냥 그렇구나 이해하고 사용했던 것들이나 개념들에 많은 도움이 되고 있습니다. 전에도 표현했지만 손상된머리결에 엘라스틴한 기분~ㅎㅎ 과 같다고 할까요?

해서 액션스크립트를 개발하고 변수의 활용이나 메모리 활용등 유익한 부분들이 있을 것 같아서 부족하나마 공부하는 내용을 공유하고자 합니다..어디서 부터 손대고 어디까지 해야할지 몰라서 일단 폴더는 많이 잡아두긴했지만 우리에게 필요한 내용까지만 포스팅할 생각입니다.

테스트하기 위한 빌더는 저는 microsoft visual C++을 사용합니다. 그외에 다른 빌더도 있으므로 좋으신거 구하여 사용하시면 됩니다. microsoft visual C++인 경우에는 프로젝트를 만들때 WIN32 Console Application으로 만드시고 나머지 옵션은 넘어가심 됩니다. 소스파일을 만드실때는 확장자를 그냥 *.c라고 하면 그냥 C파일이 됩니다.

C파일을 만들고 기본 라이브러리를 불러와야 하는데 #include하시면 되고 대상 헤더파일은 <stdio.h>입니다.
(C계열에서 헤더파일(확장자 *.h)이라는 곳에 광역 변수나 함수등을 담거나 interface등을 선언하여 참조하는 곳)

역시 책을쓰는 것이 아니므로 간단히 에제와 개념을 요약하는 방향으로 포스팅을 진행할 예정입니다..물론 저도 아직 자세히 모르구요~ ^^
Posted by 버터백통