'프로그래밍/Language'에 해당되는 글 28건

  1. 2016.02.23 포인터에 대하여
  2. 2016.02.23 C언어 연산자에 대하여 - 비트연산
  3. 2016.02.23 C언어 연산자에 대하여
  4. 2016.02.22 상수란 무엇인가?
  5. 2016.02.22 변수란 무엇인가?
  6. 2016.02.22 #Pragma의 사용법
  7. 2016.02.22 전처리기에 대하여
  8. 2016.02.22 C언어를 배워야 하는 이유
2016. 2. 23. 08:41


포인터 *


포인터란 어떠한 값을 저장하는게 아닌 어떠한 값의 주소(Address)를 저장하는 것 입니다


어떠한 값의 주소는 컴퓨터 메모리의 주소를 의미합니다.

1
2
3
4
5
6
7
8
#include<stdio.h>
 
void main()
{
    int num = 0;
    int *pnum = &num;
    //pnum은 num의 주소값을 가지고 있다.
}
cs


포인터 변수를 선언하기 위해서는 변수이름 앞에 *을 붙여서 선언하면 그 변수는 포인터 변수가 됩니다.


대체로 포인터인걸 알리기위해 변수병 앞에 소문자로 p를 붙이기도 합니다. 하지만 이건 코드 스타일이니.. 각자 알아서..


아직 이해가 잘 안되실텐데, 포인터 변수를 이용하여, 주소값과 포인터의 관계를 나타낸 예제입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
 
int main(void)
{
    int *pnum;         // 포인터 변수 선언
    int num = 10;     // 일반변수 선언 & 초기화
    pnum = &num;     // num의 주소값을 pnum에 저장
 
    printf("num의 값: %d\n", num);
    printf("num변수의 주소:%p\n", &num);
    printf("pnum변수의 값 :%p\n", pnum);
    printf("pnum이 가리키는 값: %d\n"*pnum);
 
/*
결과값
num의 값: 10
num변수의 주소:001919fC
pnum변수의 값 :001919fC
pnum이 가리키는 값: 10
*/
}

cs


밑에 주석처리한 결과값을 보면 pnum은 num의 주소값을 가리킨다는것을 알수있습니다.

즉 pnum이 가진 주소값의 위치로 찾아가면 num의 값을 얻을수있다는 것입니다.

주소값의 위치를 찾기위해선, 포인터 선언때 사용했던 * 연산자를 변수 명 앞에 적어주면 됩니다.


그럼 여기서 num의 값이 변화한다면 어떻게 될까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<stdio.h>
 
int main(void)
{
    int *pnum;         // 포인터 변수 선언
    int num = 10;     // 일반변수 선언 & 초기화
    pnum = &num;     // num의 주소값을 pnum에 저장
 
    printf("num의 값: %d\n", num);
    printf("num변수의 주소:%p\n", &num);
    printf("pnum변수의 값 :%p\n", pnum);
    printf("pnum이 가리키는 값: %d\n"*pnum);
    printf("num값 증가 +10 \n");
    num+=10;
    printf("pnum이 가리키는 값: %d\n"*pnum);
 
/*
결과값
num의 값: 10
num변수의 주소:001919fC
pnum변수의 값 :001919fC
pnum이 가리키는 값: 10
num값 증가 +10
pnum이 가리키는 값: 20
*/
}

cs


주석 처리된 출력값을 보면 마지막에 num의 값이 증가했는데 pnum이 가리키는 값 또한 증가한걸 볼수있습니다.

당연하겠죠?

이해가 안된다면, pnum이 가지고있는 값은 주소값이며, *pnum으로 가리키는 주소로 갔더니 값이 있어서 그걸 출력한것뿐입니다.


집주소를 알고있지만, 같은 주소에 다른사람이 살고있는것과 같겠죠?




◎ 포인터의 초기화


포인터의 초기값은 무엇으로 해야할까요? 

1
2
3
4
5
6
7
#include<stdio.h>
 
int main(void)
{
    int *pnum;         // 포인터 변수 선언
    *pnum = 100;
}

cs

위와 같이 코딩해 실행한다면 어떻게 될까요?

물론 컴파일러의 도움을 받아서 컴파일을 해주지 않겠지만, 이론대로라면 초기화 되지않은 포인터 변수는 쓰레기값.. 어딘지 모르는 주소값을 가지고있어서, 컴퓨터가 사용하는 어느 일정 부분의 메모리를 갑자기 100으로 덮어씌울수도있고, 그에따라 치명적인 오류를 뱉어 낼수도있습니다.


따라서 포인터 변수의 초기화는 NULL 또는 0 으로 하면 됩니다.

1
2
3
4
5
6
7
#include<stdio.h>
 
int main(void)
{
    int *pnum01 = null;         // 포인터 변수 선언
    int *pnum02 = 0;         // 포인터 변수 선언
}
cs

NULL은 아스키 코드값으로 0을 나타내며, 포인터 변수에 들어간 0은 0번째 주소를 가리키는게 아닌, "아무것도 없다." 라는 뜻을 지니게 됩니다.






Posted by 시리시안
2016. 2. 23. 07:58

저번 포스트에 앞내용을 그대로 가져오겠습니다.


C언어 연산자. 

C연어 연산자는 C언어의 아주 기초적인 내용입니다.

아주 기초적이기 때문에 소홀히 하기 쉬운 부분이기도 합니다.

C언어에서 연산자가 상당히 많은 중요한 역할을 하고 있다 할 수 있지만, 주목받지 못하는 이유는 이해 하기가 너무 쉽고, 소프트웨어 관련 프로그램에서는 문법보다 많은 비중을 차지하지 못하기 때문입니다.

그럼에도 연산자를 알아야 하는 이유는, 당연히 C언어 코딩 과정이 게임을 만드든, 뭘 만드든 연산자와 함수를 통해서 이루어지기 때문이죠.

특히, 비트연산자는 하드웨어와 관련된 신호를 처리할 때 도움이 되는 개념으로 꼭 알아야 합니다.

 

 

※ 연산자 종류


분류 

연산자 

 대입 연산자 

 

 산술 연산자 

 +, -, *, /, %

 복합 대입 연산자

 +=, -=, *=, /=, %=

 증감 연산자 

  ++, --

 관계 연산자 

  >, <, ==, !=, >=, <=

 논리 연산자 

  &&, ||, !

 조건 연산자

  ? :

 비트 논리 연산자 

  &, |, ^, ~

 비트 이동 연산자 

 >>, <<


대입 연산자 부터 조건 연산자 까지는 이전 포스팅에서 작성 되었습니다.


http://silisian.tistory.com/35


◎ 비트 논리 연산자


비트 논리 연산자는 총 &, |, ^, ~ 4개를 가지고있습니다.


비트 논리 연산자 

구분 

& 

 비트 곱 (AND)

 비트 합 (OR)

^ 

 베타적 비트 합 (XOR)

 비트 부정 (NOT)


◎ 비트 곱은 비트 라는 것을 제외하고 생각하면 곱셈연산과 같습니다. 단, 비트별로 곱합니다.

◎ 비트 합은 비트 라는 것을 제외하고 생각하면 덧셈연산과 같습니다. 단, 비트별로 덧셈하며 결과값은 참/거짓(1/0)으로만 표현합니다.

◎ 베타적 비트 합은 비트별로 연산하며 같으면 거짓을 다르면 참을 반환합니다. 비트별 != 연산이라 생각하면 간단합니다.

◎ 비트 부정은 Not연산이며, 비트 보수 연산자라고 불리기도 합니다. 자기자신의 비트별 !연산이라 생각하면 간단합니다.


◎ 비트 곱 (AND)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<stdio.h>
 
void main()
{
 
    /*
    비트 곱은 비트별로 연산 한다느넛만 빼면 논리 곱과 똑같습니다.
    A(1100) 과 B(1010)을 비트 곱 한다 하면
    차례대로 
    1&1 = 1            (1*1 = 1)
    1&0 = 0            (1*0 = 0)
    0&1 = 0            (0*1 = 0)
    0&0 = 0            (0*0 = 0)
    이 나오게 됩니다. 오른쪽 처럼 생각하면 간단하죠?
    */    
 
    //예제 소스
    
    char Data = 0x86;         //16진수인 0x86은 2진법으로 표현하면 1000 0110 입니다.
    char BitMask = 0xf2;    //16진수인 0xf2는 2진법으로 표현하면 1111 0010 입니다.
    char Result = Data & Bitmask;    //이 2개의 수를 비트곱 연산을 하게되면, 값은 1000 0010이 나오게됩니다.
    // 즉 0x82가 나오게 됩니다.
 
    /*
    연산
    1 & 1 = 1
    0 & 1 = 0
    0 & 1 = 0
    0 & 1 = 0
    0 & 0 = 0
    1 & 0 = 0
    1 & 1 = 1
    0 & 0 = 0
    */
}
cs



◎ 비트 합 (OR)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<stdio.h>
 
void main()
{
 
    /*
    비트 합은 비트별로 연산 한다는것만 빼면 논리 합과 똑같습니다.
    A(1100) 과 B(1010)을 비트 합 한다 하면
    차례대로 
    1|1 = 1            (1||1 = 1)
    1|0 = 1            (1||0 = 1)
    0|1 = 1            (0||1 = 1)
    0|0 = 0            (0||0 = 0)
    둘중 하나라고 비트값이 1 이면 1을 반환합니다.
    논리연산자중 ||을 생각해서 둘중 하나라고 참이면 참을 반환한다. 라고 생각하면 간단합니다.
    */    
 
    //예제 소스
    
    char Data = 0x86;         //16진수인 0x86은 2진법으로 표현하면 1000 0110 입니다.
    char BitMask = 0xf2;    //16진수인 0xf2는 2진법으로 표현하면 1111 0010 입니다.
    char Result = Data | Bitmask;    //이 2개의 수를 비트곱 연산을 하게되면, 값은 1111 0110이 나오게됩니다.
    // 즉 0xf6가 나오게 됩니다.
 
    /*
    연산
    1 | 1 = 1
    0 | 1 = 1
    0 | 1 = 1
    0 | 1 = 1
    0 | 0 = 0
    1 | 0 = 1
    1 | 1 = 1
    0 | 0 = 0
    */
}
cs


◎ 베타적 비트 합 (XOR)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<stdio.h>
 
void main()
{
 
    /*
    베타적 비트 합은 비트별로 연산 한다는것만 빼면 논리연산자중 != 과 똑같습니다.
    A(1100) 과 B(1010)을 베타적 비트 합 한다 하면
    차례대로 
    1^1 = 1            (1!=1 = 0)
    1^0 = 1            (1!=0 = 1)
    0^1 = 1            (0!=1 = 1)
    0^0 = 0            (0!=0 = 0)
    두개의 값이 서로 다르다면 1 같으면 0을 반환합니다.
    논리연산자중 !=을 생각해서 둘이 다르다면 참을 반환 한다고 생각하면 간단합니다.
    */    
 
    //예제 소스
    
    char Data = 0x86;         //16진수인 0x86은 2진법으로 표현하면 1000 0110 입니다.
    char BitMask = 0xf2;    //16진수인 0xf2는 2진법으로 표현하면 1111 0010 입니다.
    char Result = Data ^ Bitmask;    //이 2개의 수를 비트곱 연산을 하게되면, 값은 0111 0100이 나오게됩니다.
    // 즉 0x74가 나오게 됩니다.
 
    /*
    연산
    1 ^ 1 = 0
    0 ^ 1 = 1
    0 ^ 1 = 1
    0 ^ 1 = 1
    0 ^ 0 = 0
    1 ^ 0 = 1
    1 ^ 1 = 0
    0 ^ 0 = 0
    */
 
    //여기서 특이한점은, 베타적 비트합을 2번 연산 하게되면 원래 값으로 돌아가게 됩니다.
 
    Result = Result ^ Bitmask;    // (0111 0100) ^ (1111 0010) = 1000 0110
 
    //이처럼 XOR 즉 베타적 비트 합은 암호화의 자주 사용 됩니다.
}
cs

◎ 비트 부정 (NOT)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<stdio.h>
 
void main()
{
 
    /*
    비트 부정은 자기자신의 비트별로 연산 한다는것만 빼면 논리연산자중 ! 과 똑같습니다.
    논리연산자중 앞에 !을 붙이면 참과 거짓이 바뀌듯 비트값앞에 !을 붙이게되면 비트의 0과 1이 바뀌게 됩니다.
    따라서 A(1100)를 ~A 한다 하면
    차례대로 
    ~1 = 0            
    ~1 = 0            
    ~0 = 1            
    ~0 = 1            
    1은 0으로 0은 1로 연산하게 됩니다.
    */    
 
    //예제 소스
    
    char Data = 0x86;         //16진수인 0x86은 2진법으로 표현하면 1000 0110 입니다.
    char Result = ~Data;    //Data를 부정(~) 하게되면 0111 1001이 됩니다.
    // 즉 0x79가 나오게 됩니다.
 
    /*
    연산
    ~1 = 0
    ~0 = 1
    ~0 = 1
    ~0 = 1
    ~0 = 1
    ~1 = 0
    ~1 = 0
    ~0 = 1
    */
}
cs



◎ 비트 이동 연산자


비트 이동 연산자는 총 << 과 >> 가지고있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
 
void main()
{
 
    /*
    비트 이동 연산자는 비트의 위치를 왼쪽 또는 오른쪽으로 온긴다고 생각하면 됩니다.
    A(1101)를 B = A<<2; 라 하면 B의 값은 0100이 됩니다.
    A를 왼쪽으로 2번 쉬프트 하면 11 0100 이 됩니다. 하지만 범위를 초과한 비트는 버려지게 됩니다.
    따라서 0100만 남아서 B의 값이 됩니다. ( A값은 변하지 않습니다. )
    */    
 
    //예제 소스    
    char Data = 0x76;         //16진수인 0x86은 2진법으로 표현하면 0111 0110 입니다.
    char Result01 = Data<<2;    //Data를 <<2 하게되면 1101 1000이 됩니다.
    char Result02 = Data>>2;    //Data를 >>2 하게되면 0001 1101이 됩니다.
    char Result03 = Data<<8;    //Data를 <<8 하게되면 0000 0000이 됩니다.
}
cs



참고 자료 1 : https://ko.wikipedia.org/wiki/%EB%85%BC%EB%A6%AC_%EC%97%B0%EC%82%B0

참고 자료 2 : http://www.tipssoft.com/bulletin/board.php?bo_table=FAQ&wr_id=598

참고 자료 3 : https://msdn.microsoft.com/ko-kr/library/336xbhcz.aspx





 



'프로그래밍 > Language' 카테고리의 다른 글

try, throw, catch 를 이용한 예외 처리 방법  (0) 2016.02.23
포인터에 대하여  (0) 2016.02.23
C언어 연산자에 대하여  (0) 2016.02.23
상수란 무엇인가?  (0) 2016.02.22
변수란 무엇인가?  (0) 2016.02.22
Posted by 시리시안
2016. 2. 23. 06:52

C언어 연산자

C연어 연산자는 C언어의 아주 기초적인 내용입니다.

아주 기초적이기 때문에 소홀히 하기 쉬운 부분이기도 합니다.

C언어에서 연산자가 상당히 많은 중요한 역할을 하고 있다 할 수 있지만, 주목받지 못하는 이유는 이해 하기가 너무 쉽고, 소프트웨어 관련 프로그램에서는 문법보다 많은 비중을 차지하지 못하기 때문입니다.

그럼에도 연산자를 알아야 하는 이유는, 당연히 C언어 코딩 과정이 게임을 만드든, 뭘 만드든 연산자와 함수를 통해서 이루어지기 때문이죠.

특히, 비트연산자는 하드웨어와 관련된 신호를 처리할 때 도움이 되는 개념으로 꼭 알아야 합니다.

 

 

※ 연산자 종류


 분류

연산자 

대입 연산자 

산술 연산자 

+, -, *, /, %

복합 대입 연산자 

 +=, -=, *=, /=, %=

증감 연산자 

 ++, --

관계 연산자 

 >, <, ==, !=, >=, <=

논리 연산자 

 &&, ||, !

조건 연산자

 ?:

비트 논리 연산자 

 &, |, ^, ~

비트 이동 연산자 

 >>, <<


 

◎. 대입 연산자는 오른쪽 값을 왼쪽으로 넣는것을 말합니다. 관계 연산자인 ==과 대입 연산자는 = 헷갈릴 수 있으므로 주의할것.

. 복합 대입 연산자는 왼쪽값에 오른쪽 값을 산술후 대입하는걸 말합니다. a+=1; 은, a에 1을 먼저 더하고(산술) 후에 값을 다시 a에 대입합니다

. 증감 연산자에 선 연산 후 증감, 선 증감 후 연산으로 나뉩니다. ++a 와 a++의 차이점을 알아두세요!

. 관계 연산자는 2개의 값을 비교할떄 사용합니다. 결과값은 1 또는 0 즉 참 또는 거짓으로 반환됩니다.

. 논리 연산자는 참과 거짓을 연산자에 맞춰서 연산하여 결과값을 1 또는 0 즉, 참 또는 거짓을 반환합니다.

. 조건 연산자는 관계연산자로 나온 결과값에 따라 반환값을 달리합니다.

 

 


 

. 대입 연산자


1
2
3
4
5
6
7
8
#include<stdio.h>
 
void main()
{
    int a;
    a = 1;    // 대입 연산자
}
 
cs

오른쪽 값을 왼쪽으로, 자료형에서 자동형변환이 일어날 때도 오른쪽에서 왼쪽순이었다.

 

. 복합 대입 연산자

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<stdio.h>
 
void main()
{
    int a;
    a = 0//대입 연산자
 
    //복합 대입 연산자 
    a += 1;    //( a = a+1)
    a -= 1;    //( a = a-1)
    a /= 1//( a = a/1)
    a *= 1//( a = a*1)
}
 
cs

 

오른쪽값과 왼쪽값을 연산해서 왼쪽에 넣는다.

 

 

. 증감 연산자

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
 
void main()
{
    int a;
    int b = 0;
    int c = 0;
    a = 0//대입 연산자
 
    //증감 연산자
    a++;    // a = a+1
    a--;    // a = a-1
 
    //앞뒤의 차이
    a = 1;
    b = ++a;        // 증감 연산자가 앞에 있다면 선 연산후 대입 즉 a에 +1이 되며 b에는 2값이 들어간다.
    c = a++;        // 증감 연산자가 뒤에 있다면 선 대입후 연산 즉 c에는 2값이 들어가며 a는 3이 된다.
}
 
cs

 



. 관계 연산자

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
 
void main()
{
    int a = 1;
    int b = 0;
 
    //관계 연산자
    // >, <, ==, !=, >=, <=
    //참이면 1반환 거짓이면 0을 반환한다.
 
    int result =0;
 
    result = a<b ;     //a가 b보다 작다. 거짓     result값 0
    result = a>b ;     //a가 b보다 크다. 참         result값 1
    result = a==b ;     //a와 b가 같다.      거짓    result값 0
    result = a!=b ;     //a와 b가 같지않다.참     result값 1
    result = a>=b ;     //a가 b보다 크거나 같다. 참 result값 1
    result = a<=b ;     //a가 b보다 작거나 같다. 거짓 result값 0
}    
cs

 

 

. 논리 연산자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
 
void main()
{
    int a = 1;
    int b = 0;
    
    //논리 연산자
    //&&, ||, !
    //논리 연산자는 참과 거짓을 연산자에 맞춰서 연산하여 결과값을 1 또는 0 즉, 참 또는 거짓을 반환합니다.
 
    int result = 0;
 
//&&연산자, And 연산자
    result = a == b && a>b;    // a 와 b가 같으면서 a가 b보다 크다  / 거짓 result값 0
    result = a != b && a>b;    // a 와 b가 같지않으면서 a가 b보다 크다  / 참 result값 1
 
//||연산자, Or 연산자
    result = a == b || a>b;    // a 와 b가 같거나 a가 b보다 크다  / 참 result값 1    
    //a==b는 거짓이여도. a>b가 참이기에 or연산자는 참을 반환한다.
    result = a == b || a<b;    // a 와 b가 같거나 a가 b보다 작다  / 거짓 result값 10
    //a==b는 거짓ㅣ며. a<b도 거짓이기에 or연산자는 거짓을 반환한다.
 
//!연산자, Not 연산자
    result = !(a>b);    // a가 b보다 크다 의 값은 참이나, !가 있기에 반대값인 거짓을 반환한다. result값 0
    result = !(a<b);    // a가 b보다 작다 의 값은 거짓이나, !가 있기에 반대값인 참을 반환한다. result값 1
}
cs



. 조건 연산자

실제로 if문때문에 잘 쓰이지 않는.. 불쌍한 연산자..

알맞게 사용한다면 코드가 간결해지고, 난무한다면 가독성이 떨어진다는 전설의 연산자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<stdio.h>
 
void main()
{
    int a = 1;
    int b = 0;
    
    //조건 연산자
    // ? :
    // 관계연산자로 나온 결과값에 따라 반환값을 달리합니다.
    
// 사용법
// (조건)? (참):(거짓);
// ?앞에있는 조건의 반환값에 따라 (참) 또는 (거짓)을 실행시키거나 반환한다.
 
    //    예제
    int result = 0;
 
    result = (a>b)? 10 : -10;    //a>b의 값이 참이므로 :기준 왼쪽 값을 대입하여, result값은 10이 된다.
 
    result = (a==b)? 10 : -10;    //a==b의 값이 거짓이므로 :기준 오른쪽 값을 개입하며 result값은 -10이 된다.
 
    //또한 이렇게 함수 자체를 넣을수도있습니다.
    (a<=b)? printf("a<=b는 참입니다") : printf("a<=b는 거짓입니다");
    //물론 위의 값은 a<=b가 거짓이므로 : 기준 오른쪽 인 printf("a<=b는 거짓입니다")가 실행되게 됩니다.
}
cs


 

.. 비트 연산자


비트 연산자는 내용이 길어 질수있기 때문에, 

다음 포스팅에서 작성하겠습니다.



참고 : http://baeseonha.tistory.com/category/C-programing/C%EC%96%B8%EC%96%B4%20%EA%B8%B0%EC%B4%88





'프로그래밍 > Language' 카테고리의 다른 글

포인터에 대하여  (0) 2016.02.23
C언어 연산자에 대하여 - 비트연산  (0) 2016.02.23
상수란 무엇인가?  (0) 2016.02.22
변수란 무엇인가?  (0) 2016.02.22
#Pragma의 사용법  (0) 2016.02.22
Posted by 시리시안
2016. 2. 22. 22:01

※ 상수의 정의와 특징

 

- 상수는 변환되지 않는 값을 말한다. 초기화가 되면, 다시 재정의가 불가능합니다.

- 상수는 변환되지 않는 값 (파이, 3.14~)을 정의하여 반복적으로 사용하기 위해 쓰입니다.

- 상수에 두가지가 있다. literal 상수와 symbolic 상수가 있습니다..

 

상수는 변환되지 않는 값입니다. 즉, 초기화가 되면 재정의가 불가능하다는 말입니다..

 

 

- literal 상수는 글자 그대로 의미가 있어서, 이름이 따로 정의되지 않은 상수를 말합니다.

우리가 흔히 말하는 매직넘버! 입니다. (코드에 숫자 그대로 적는걸 뜻합니다.)

 

printf("%d", 27);

"literal 상수 10진수 27을 10진수 27로 출력하겠다."

printf("%x", 0x27);

"literal 상수 16진수 27을 16진수 27로 출력하겠다." (10진수로는, 39이다.)

printf("%o", 027);

"literal 상수 8진수 27을 8진수 27로 출력하겠다." (10진수로는, 23이다.)

 

tip. literal 상수 앞에 0x, 0이 붙어 있을 때, 각 각 16진수 8진수로 상수 값이 정의 됩니다.

 

 

- symbolic 상수는, 상수를 기호화하여 변수처럼 이름을 지어쓰는 상수를 말한다.

특징은, 매크로 상수와 const 키가 사용된다는 점이다.  


 

const int num=100;

num= 1000;

"정수형 변수 num에 100이라는 상수를 저장하여 이 값을 절대 변환하지 않겠다."

" [에러] . 값을 변환하지 않겠다고 했는데, 재정의 되었으므로 오류."

 

const int ip;

ip=100;

" [에러]. 정수형 변수 ip를 초기화하지 않았으므로 에러가 발생했다."

"초기화는 const 상수 선언과 동시에 이루어 져야 한다."

 

 

const와 매크로 상수가 있는 이유는, 파이와 같은 고유 상수의 값을 헷갈리지 않도록 알기 쉬운 이름으로 정의하기 위해서입니다.

긴 프로젝트를 짜게 되는 경우, 고유 상수를 일일히 코딩하는 것은 비효율적이기 때문에 쉬운 문자로 대체하여 쓰여집니다.


참고 : .http://baeseonha.tistory.com/entry/C%EC%96%B8%EC%96%B4%EA%B8%B0%EC%B4%88-%EB%B3%80%EC%88%98-%EC%83%81%EC%88%98-literal%EC%83%81%EC%88%98-symbolic%EC%83%81%EC%88%98

 

 

'프로그래밍 > Language' 카테고리의 다른 글

C언어 연산자에 대하여 - 비트연산  (0) 2016.02.23
C언어 연산자에 대하여  (0) 2016.02.23
변수란 무엇인가?  (0) 2016.02.22
#Pragma의 사용법  (0) 2016.02.22
전처리기에 대하여  (0) 2016.02.22
Posted by 시리시안
2016. 2. 22. 21:51

변수란 무엇인가?

변수는 C언어의 기본 용어 중의 하나입니다.

지글 말하는것은 기초적인 변수 선언 방법을 말하는 것이 아니라, 변수의 기본적인 정의와 특성 이야기 하려고 합니다.

변수는 기초적인 것이므로, C언어를 조금이라도 배우거나 공부했다면 알겠지만, 그래도 이곳에서 정리를 하려 합니다. 

 

※ 변수의 정의와 변수 선언.

 

- 변수란, 데이터를 임시로 저장할 메모리 공간을 의미한다.

- 변수는 선언과 동시 초기화, 선언 후 초기화 모두 가능한다.

- 변수는 프로그램이 종료될 때, 저장된 데이터가 사라진다.

- 변수 선언은 정수형, 실수형, 문자형, 문자열형으로 나누어야 한다.

(int, char, double, char ..[], 문자열형은 고유 함수를 통해 변수에 저장하거나, 상수로 출력하는 방법이 있습니다. 기본 자료형으로 문자열을 변수에 저장하려는 경우 에러가 발생한다. 배열을 이용하거나, strcpy 함수 등을 써야 합니다.)


tip. 만약, 변수가 초기화되지 않아 데이터가 저장되지 않는다면, 쓰레기값이 들어간다.



밑의 구문을 보고 해석해보자.


int value= 10;

printf("%d", value);

"4 byte 정수형 변수에 10이라는 데이터를 저장하겠다. 그리고 10진수 정수로 value라는 변수에 저장된 데이터를 출력하겠다"

 

char string= 'a';

printf("%c", b);

"1 byte 문자형 변수에 a라는 데이터를 저장하겠다. 그리고 문자형으로 string에 저장된 데이터를 출력하겠다."

 

double dc= 3.1;

printf("%lf", c);

"8 byte 실수형 변수에 3.1이라는 데이터를 저장하겠다. 그리고 실수형으로 dc에 저장된 데이터를 출력하겠다."

 

 

- 변수는 초기화하고 나서 재정의가 가능합니다. 변수는 말 그대로 임의로 저장된 메모리 공간에 지나지 않으므로, 그 속에 저장되는 데이터 값은 언제든 변환이 가능합니다..


출처 참고 : http://baeseonha.tistory.com/entry/C%EC%96%B8%EC%96%B4%EA%B8%B0%EC%B4%88-%EB%B3%80%EC%88%98-%EC%83%81%EC%88%98-literal%EC%83%81%EC%88%98-symbolic%EC%83%81%EC%88%98

'프로그래밍 > Language' 카테고리의 다른 글

C언어 연산자에 대하여  (0) 2016.02.23
상수란 무엇인가?  (0) 2016.02.22
#Pragma의 사용법  (0) 2016.02.22
전처리기에 대하여  (0) 2016.02.22
C언어를 배워야 하는 이유  (0) 2016.02.22
Posted by 시리시안
2016. 2. 22. 21:29

#pragma

#pragma 는 ‘컴파일러에게 말하는 전처리기 명령’ 이라고 보시면 됩니다.

즉, #include 나 #define 처럼 전처리기에 의해 컴파일 이전에 처리되지만, 그 명령은 컴파일러에게 전달되기 때문이죠.

사실 pragma 는 C 언어의 기본 키워드라고 하기 보다는, 컴파일러에 종속적인 키워드라고 하는 것이 맞습니다. pragma 를 사용하는 문법은 컴파일러 마다 다르고 딱히 통일 된 것이 없기 때문입니다.



#pragma pack 사용


    - 기본적인 윈도우 환경에서의 데이터 정렬은 4byte를 기준으로 이루어지게 됩니다. 

 

struct A{ 

          char a;

          short b;

   };


위와 같은 구조체가 있다. 윈도우는 4byte가 가장 작은 메모리 할당량이다.

그러므로 어떠한 변수 하나를 잡기 위해서 무조껀 4byte를 기준으로 계산하게 된다.


위와 같은 구조체, 즉 short와 char을 선언하게 된다면, short = 2byte, char = 1byte 이므로 윈도우는 4byte를 할당 받아서

short에게 먼저 2byte 할당하고 남는 2byte중에서 char를 할당하게 된다.

즉, 3byte를 사용하기 위해서 4byte의 메모리를 사하게 되는 것이다.


하지만, 이것또한 컴파일러에 따라 달라 질 수 있다.Visual Studio는 기본적으로 8byte를 사용한다.

결국 위 구조체를 할당하기 위해서는 8byte가 필요하게 되는 것이다.


이에 따른 해결법으로 #Pragma pack을 사용 할 수 있는데,


#pragma pack(push, 1)

구조체

#pragma pack(pop)


위와 같은 방식으로 선언을 해준다면, 데이터 정렬이 변하게 되는 것이다. 위의 선언 (pack(push,1) 은 데이터 정렬 기준을 1byte로 한다는 것이다.

즉, struct A는 위의 환경에서는 3byte만이 필요하게 되는 것이다.

 메모리가 필요할 경우 무조건 1byte씩을 할당을 하게 되므로 불필요한 공간이 없이 필요한 공간만을 할당하게 되는 것이다.


주의 할점을 그후 #pragma pack(pop) 을 하지 않을 경우는 #pragma pack(push, 1) 로 선언된 이후의 변수 선언에 전부 적용이 되는 것이다. 

이것에 신경을 잘 쓰지 않으면 프로젝트가 엉망이 될 수 있다.

무조껀 1바이트씩하는게 좋은게 아니다. 주의!!!! 


예) 프로젝트 중간에 pack을 했다면 같은 값을 pack이 된 곳과 안된곳의 값이 다르게 표현이 되게 된다. 

이유는 구조체 자체의 메모리 할당이 서로 다르기 때문에 생기게 되는 곳이다. 

가장 유용하게 사용되는 부분은 네트워크 통신에 사용되는 packet을 정의할 때 가장 유용하게 사용된다. network packet은 서버 클라이언트에서 같이 사용하기 때문에 문제가 되는 점은 발견되지 않으며, network packet의 사이즈를 적절하게 해주기 때문에 더욱 유용한 것이다.



#pragma once 사용


이 명령은 컴파일러로 하여금 이 파일이 오직 딱 한 번만 include 될 수 있다는 것을 말해줍니다.


하지만 맨처음 말한것처럼 #pragma는  "컴파일러 마다 다르고 딱히 통일 된 것이 없기 때문입니다." 지원이 되는 컴파일러인지 확인하고 사용합시다.




참고 : http://itguru.tistory.com/103




'프로그래밍 > Language' 카테고리의 다른 글

C언어 연산자에 대하여  (0) 2016.02.23
상수란 무엇인가?  (0) 2016.02.22
변수란 무엇인가?  (0) 2016.02.22
전처리기에 대하여  (0) 2016.02.22
C언어를 배워야 하는 이유  (0) 2016.02.22
Posted by 시리시안
2016. 2. 22. 21:06

전처리기

 

- #include <stdio.h> 입출력 전처리기 호출

- #define 치환(정의) 역할

- #ifndef 매크로상수 재정의 방지, 조건부 실행

- #if () 조건부, 조건식에 따라 전처리를 수행

 

전처리기는 전에 처리하는 기능이 있다고 해서, 전처리기 이다. C언어 초반에 #include<stdio.h>를 코딩하고,

본격적으로 프로그래밍을 시도하는데, 그것의 의미를 알아두면, 전처리기를 보다 쉽게 이해할 수 있다.

 

 

> # include <stdio.h>

 

요약하면, "전처리기(#)야 include라는 파일에 있는 stdio.h 헤더파일을 미리 실행해죠" 이다.

stdio.h 는 include라는 파일에 있는 헤더파일 -C언어 함수들이 압축되어 있는 파일이다- 이다.

전처리기는 이 파일을 컴파일러가 기능을 수행하기 전에 미리 처리한다.

 

 



 

 

위의 visual studio 12.0의 include 파일에 들어있는 stdio.h 파일이다.

그럼, stdio.h 파일이 무엇이길래 먼저 처리하도록 지시하는 것일까?

 

stdio.h 파일은 Standard Input Output 의 입출력 해더파일이다.

컴파일러가 인간의 언어를 기계어로 바꾸는 과정을 수행하기 전에, 이 코드를 해석 가능하게 하기 위한

입출력 -printf(), scanf() 등- 문법을 미리처리하도록 하는 것이다.

 

tip. main()함수를 호출하고 종료시키는 일을 하는 것은 운영체제이다.

운영체제는 window xp, unix 등이고, 컴퓨터와 프로그램 사이를 원활하게 해주는 인터페이스(interpace) 역할을 한다.

 

 

> # define

 

#define으로 시작하는 전처리 문장을 매크로라고 한다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
 
#define byte int
#define name "조원우"
#define add(x,y) x*y
 
void main()
{
 
    byte a,b;
 
    scanf("%d,%d",&a,&b);
 
    printf("%s",name);
 
    printf("%d",add(a,b));
 
}
 
 
cs


 

1. #define byte int

"byte를 int 자료형으로 정의하겠다"를 의미한다. 즉,  int a; 라고 변수선언해야 할 것을, byte a; 라고 선언해도 이상이 없다는 것이다.

 

2. #define name "조원우"

"name을 조원우로 정의하겠다"를 의미한다. 즉, printf("%s", "조원우"); 인 것을, printf("%s", name); 으로 코딩해도 이상 없다.

 

3. #define add(x, y) x*y

"add(x, y)라는 함수는 x와 y를 곱한 것으로 정의한다" 를 의미한다. printf("%s", add(x, y)); 를 코딩하면, 곱한 값이 나온다.

 

#define은 여러가지 역할을 수행한다. 상수를 치환하고(2번), 자료형 -int, char, double- 을 정의하고(1번), 함수를 정의한다(3번). 나아가 #if, #ifndef 는 매크로 정의가 됬는가를 여부로 조건부 전처리를 수행한다.

 

 


 

 

> # if ()

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
 
#define DEFINES 1
 
void main()
{
    int num01 = 1, num02 = 2;
 
#if(DEFINES==1)
    printf("%d",num01*num02);
#elif(DEFINES ==0)
    printf("%d",num01/num02);
#else
    printf("%d",num01+num02);#
#endif
}
 
 
cs


 

1. #define DEFINES 1

"DEFINES 를 1로 정의한다"를 의미한다.

 

2. #if(DEFINES ==1)

"DEFINES 가 1이라면, printf() 를 수행해라"를 의미한다. 미리 정의된 DEFINES 의 값에 따라,

 #if 전처리기가 수행 될 수도 안 될 수도 있다.

 

3. #elif(DEFINES ==0)

"위의 조건이 다르고, DEFINES ==0이라면 아래 printf()를 수행해라"를 의미한다.

 

조건식이 참이면 해당되는 코드를 수행하고, 조건식이 거짓이면 건너띄는 구조이다.

 

 

> # ifndef

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<stdio.h>
 
#ifndef MUL
 
#define MUL
#endif
 
 
void main()
{
    int num01 = 1, num02 = 2;
 
#ifdef MUL
    printf("%d",num01/num02);
#endif
 
#ifndef MUL
    printf("%d",num01*num02);
#endif
 
}
 
 
cs

 

 

1. #ifndef MUL

"매크로 상수 MUL이 정의되어 있지 않다면 MUL을 만들어라" 를 의미한다. 아직, 치환 단계가 아닌, 만들기만 한 것이다.

 

2. #ifdef MUL

"매크로 상수 MUL이 정의되어 있다면, MUL을 다음과 같이 치환해라" 를 의미한다. MUL은 1*2로 2로 치환될 것이다. 이 함수는 MUL이 num*num1이라고 정의하지 않지만, 자동으로, MUL을 인식하기 때문에 따로 정의할 필요가 없다.

 

3.#ifndef MUL

"매크로 상수 MUL이 정의되어 있지 않다면, 다음과 같이 MUL을 정의해라" 의미한다.

 

 

전처리기는 크게 3가지 유형이다. 헤더파일을 전처리하는 것, 메크로를 처리하는 것, 조건부 처리하는 것 이렇게 3가지 유형이다. 

프로그램 상, 절대 변하지 않을 수치를 쉽게 치환 하고 싶거나,

 함수를 간단하게 정의할 때나,

 이런 것들을 재정의 하여 오류가 뜨지 않도록 코딩 할 때,

 전처리기가 필요하다.



출처 및 참고 : http://baeseonha.tistory.com/entry/C%EC%96%B8%EC%96%B4%EA%B8%B0%EC%B4%88-%EC%A0%84%EC%B2%98%EB%A6%AC%EA%B8%B0%EB%9E%80

'프로그래밍 > Language' 카테고리의 다른 글

C언어 연산자에 대하여  (0) 2016.02.23
상수란 무엇인가?  (0) 2016.02.22
변수란 무엇인가?  (0) 2016.02.22
#Pragma의 사용법  (0) 2016.02.22
C언어를 배워야 하는 이유  (0) 2016.02.22
Posted by 시리시안
2016. 2. 22. 20:34

왜 우리는 씨언어를 공부 해야 할까?

  

일단 각 대학에서 처음에 씨언어를 가리키는 이유를 말하자면

C언어가 프로그래밍언어의 기초이기에 C언어를 많이 가리킨다.

 

그렇다면 왜 C언어가 프로그래밍 언어의 기초가 됐을까?

다른 수많은 프로그래밍언어들이 C언어로 만들어졌거나 C언어를 모델로 했기 때문에 기초가 되었다.


그렇다면 왜 많은프로그래밍 언어들이 C언어로 만들어 졌거나 C언어를 모델로 했을까?

역사를 보자.


씨언어의 역사

 

그 이유는 당연한것이겠지만 C언어는 상당히 많은 프로그래머에 의해 사용되었기 때문이다.


C언어가 많은 사랑을 받은 이유는 C언어가 몇몇 장점을 가지고 있어서 인데


C언어 자체가 처음에는 정말 기초 적인것들만 정의 하고있었다.


또한 그 정의에 벗어나지만 않는다면 추가적인 확장이 가능했다.


그래서 C언어는 상당히 많은 유사 버전이 만들어졌고 C언어 이지만 서로 다른언어라고 할수있을 정도의 많은 C언어가 생겨날 정도였다.

 

미국표준협회ANSI에서 ANSI C 즉 표준 C를 정의 하였다.

 

이렇게 만들어진 C언어는 살아 있는 생명과도 같이 성장했다.

 

처음에 정의된 씨언어에서 점점 이것저것 새로운 프로그래밍 기술들과 이론들이 생겨날 때마다


 C언어에다가 붙였다. C언어의 안좋은 면이 발견되면 씨언어의 구조 등을 수정했다. 


C언어는 그래서 매우 강력하면서 매우 지저분한 프로그래밍 언어가 되었다-_- 

71년부터 지금까지 계속 수정에 수정을 거치고 있는 프로그래밍언어이기때문에


그 강력함은 이루 말할수없다.

 

72년인가 1년인가 이 C라는 프로그래밍언어로 PDP-11이라는 컴퓨터에서 돌아가는 UNIX라는 운영체제가 다시 만들어졌다.

(사실상 이때부터가 유닉스의 시작이며 컴퓨터소프트웨어 기술의 발전이 시작된다)

 

씨언어의 강력함과 간결함이 유닉스를 우수한 운영체제로 만들었고 유닉스는 현대 운영체제의 기본이 되었다.

리눅스는 유닉스를 약간베껴서 PC용으로 만든거고 윈도우는 베꼈는데 잘못베낀데다가 몇개만 베껴서 어정쩌정한놈에다가 그림을 입힌거다.

 

C언어는 중급언어이다 라는 말이있다


프로그래밍언어에는 기계가 바로 알아 들을수있는 기계어가 있는데 이는 0,1의 숫자의 조합이다.

이것을 영어 단어와 매치 시켜서 약간의 의미를 띄게 만든언어가 어셈블리이다.

여기까지가 저급언어이다. ( 로우 레벨 언어 )

 

그리고 저급언어 에서 벗어나 명령어가 좀더 의미를 갖게한( 이를테면 화면에 무엇을 출력해라 라고 하는 명령어는 basic이란언어에서는 print이다) 언어가 고급언어이다.

 

C언어는 분명 고급언어이다. 하지만 중급언어라고 불리우는 이유는 기계어처럼 하드웨어 적인 제어가 가능하며

(심지어 C언어속에서 어셈블리어를 사용할수있다) 고급언어의 특징을 모두 가지고 있기 때문이다.

 

 언어 이름의 유래


C언어 이름의 유래 100%사실 

옛날에 B언어라는 언어가 있었다. 그걸 모티브로 해서 만든언어가 C언어다-_-;;

 

C++언어 이름의 유래 100% 사실 

옛날에 C라는 언어가 있었다 거기에다가 1더했다는 의미로 증가 연산자++을 붙여 C++이되었다

혹은 C언어에 클래스 한개가 더해져서 C++이라는 설도 있고, C with Class였다가, 너무 길어서 CC라 부르다가 C가 2개니까 C++이라 는 설도 있다.


C#언어 이름의 유래 80% 사실 

옛날에 C++이라는 언어가 있었다 거기에다가 한개를 더 추가해 ++

C++   
  ++

이라고 만들었다-_-;; (++두개를 합치면 #모양이 나온다)

프로그래머들은 상상할수없을 만큼 귀찮은게 많은 존재이다-_-;

 


 

C언어 예상도

 

 

C언어어는 점점 사용빈도가 낮아지고 있다.

이유는 한 프로그램을 만들기에(실제로 우리가 사용하는) 너무 시간이 오래 걸린다는것이다.


하드웨어 제어에 상당히 능하지만 생산성이 낮다는 이유로 그것도 메리트가 낮아지고 있다.


이유는 이게 다다. 근데 첫번쨰 이유를 보자면...

시간이 오래 걸리는 이유는... 타자를 많이 쳐야 한다는말이다.

일부 프로그래머들이 죽기보다 싫어 하는 일이다.

그리고 기업입장에서도 업무 효율이 낮아지기 때문에 별로 좋아 하지 않는다.

하지만 하드웨어제어나 속도가 중요시 되는 프로그램 제작에는 앞으로도 계속해서 쓰일것이다.

요즘에 나오는 C#이나 JAVA같은 프로그래밍언어는 전반적으로 느리다.

 

 

 종합정리

 

 

C는 좋다.

강력한 성능을 가지고있다.

많은 프로그래밍언어가 C로 작성되었거나 C를 모티브로 한다.

하지만 업무효율이 낮다. (타자를 많이 쳐야 한다) 하지만 빠르다! 

앞으로도 많이 쓰일것이다.

C는 역시가 긴만큼 수많은 프로그램들이 C로 짜여져있다. 그것들을 공부하기 위해서라도

C는 반드시 해야한다-_-+



출처 : http://skmagic.tistory.com/entry/C%EC%96%B8%EC%96%B4%EB%A5%BC-%EB%B0%B0%EC%9B%8C%EC%95%BC%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0


'프로그래밍 > Language' 카테고리의 다른 글

C언어 연산자에 대하여  (0) 2016.02.23
상수란 무엇인가?  (0) 2016.02.22
변수란 무엇인가?  (0) 2016.02.22
#Pragma의 사용법  (0) 2016.02.22
전처리기에 대하여  (0) 2016.02.22
Posted by 시리시안