달력

5

« 2024/5 »

  • 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
2015. 10. 23. 07:37

void* 프로그래밍/자료구조설계2015. 10. 23. 07:37

void*

void포인터는 어떤 타입의 포인터든 다 받을 수 있는 포인터이다.

받는 것은 어떤 포인트형이든 다 받을 수 있다.

그런데 그 포인터에 접근할 때는 해당 포인트의 자료형에 맞에 접근해야 한다.

한마디로, 주소값이 void*에 들어갈때는 자유로우나 나올때는 알맞게 접근해야한다.

다음 예제를 보면 알기쉽다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
int main(){
    void* ptr;
 
    int i = 7;
    float f = 23.5;
 
    ptr = &i;
    printf("%d\n"*((int*)ptr));
 
    ptr = &f;
    printf("%f\n"*((float*)ptr));
 
    return 0;
}
 
cs

10줄과 13줄에 포인터가 int*와 float*f 로 형변환 시켜서 포인터에 접근한 것을 확인할 수 있다.

형변환 해주지 않으면 에러가 나서 컴파일이 안된다. 



'프로그래밍 > 자료구조설계' 카테고리의 다른 글

인터넷 check sum 함수의 구현  (0) 2016.02.08
다운  (0) 2016.02.07
열거형 enum  (1) 2015.10.23
윈도우에서 리눅스처럼 컴파일하기  (1) 2015.09.19
:
Posted by youjin.A
2015. 10. 23. 01:36

열거형 enum 프로그래밍/자료구조설계2015. 10. 23. 01:36

열거형이란 내가 사용할 데이터들의 집합이다. 예를들어 TRUE, FALSE나 색깔, 요일, 과일 등의 집합이다.

int와 같이 열거형에 키워드가 있는데 그것은 'enum'이다.


1. 열거형 정의

열거형은 다음과 같이 선언한다.

enum    열거형_이름    {멤버_변수들};

예를들어 enum daynames {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; 이렇게 선언할 수 있다.

이때 멤버변수들은 맨 좌측이 0이고, 좌측에서 우측으로 갈 수록 값이 1씩 커진다.

그런데 만약에 초기값을 Sun = 7 으로 했다면, 그 다음 변수는 1이 커져서 4가 된다.


2. 열거형 변수 선언

열거형 변수는 먼저 열겨형으로 선언한 멤버들만 저장할 수 있는 변수를 말한다.

구조체와 비슷하게 enum+열거형_이름이 자료형이라고 생각할 수 있기 때문에 열거형 변수는 다음과 같이 선언한다.

enum    열거형_이름    변수_이름

선언 후에는 자기 멤버만 넣을 수 있다.

 enum daynames today;
    today = Mon;



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>
 
enum daynames {Sun= 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
 
int main(){
    printf("Sun : %d\n", Sun);
    printf("Mon : %d\n", Mon);
    printf("Tue : %d\n", Tue);
    printf("Wed : %d\n", Wed);
    printf("Tue : %d\n", Tue);
    printf("Fri : %d\n", Fri);
    printf("Sat : %d\n", Sat);
 
    int remaining;
    enum daynames today, dday;
    today = Mon;
    dday = Fri;
 
    remaining = dday - today;
    if (remaining >= 0)
        printf("D-%d\n", remaining);
    else
        printf("D-day already came.\n");
 
    return 0;
}
cs


'프로그래밍 > 자료구조설계' 카테고리의 다른 글

인터넷 check sum 함수의 구현  (0) 2016.02.08
다운  (0) 2016.02.07
void*  (0) 2015.10.23
윈도우에서 리눅스처럼 컴파일하기  (1) 2015.09.19
:
Posted by youjin.A

윈도우에서도 리눅스처럼 visual studio나 이클립스같은 GUI가 없이 도스창에서 프로그램을 짜고 컴파일을 할 수 있다.

다만 리눅스에서는 초기에 컴파일 프로그램인 gcc가 깔려있지만

윈도우는 없기때문에 gcc를 직접 설치해 주어야 한다.

우선, 윈도우 도스창에서 컴파일 하기 위해 깔아야 하는 프로그램을 알아보자


<설치>

 1) MinGW

컴파일러로써 cmd창에 gcc명령이 먹히도록 한다.

MinGW는 http://www.mingw.org/ 에서 다운..

설치하고 난 후 환경변수설정을 해야 하는 데, 

환경 변수 설정은 시스템 변수가 아닌 사용자의 변수의 PATH에 C:\MinGW\bin을 넣어줘야 한다.

 

2) VIM

VIM은 메모장처럼 코드를 써 넣을 수 있는 에디터 프로그램이다.  (리눅스에서의 어디터 프로그램은 nano이다.)

vim은 여기서 다운 ...  http://www.vim.org/download.php

VIM을 설치하고 환경변수 를 설정해주면 cmd창 어디에서나 "VIM" 이라고 치면 이것을 실행할 수 있다.

cmd창에 vim "파일 이름"을 치면 입력한 파일 이름을 가진 파일이 현재 디렉토리에 만들어 진다.


3) make

c코드가 실행되는 .exe 파일로 컴파일되는 과정은 Prepocessin, Compilation, Assemble, Linking 네 단계를 거친다.

Preprocessing은 #include 한 헤더파일이나 #define 한 것은 붙이는 과정이다.

cpp main.c > main.i //Pre-procession only

Compilation은 c코드를 Assembly code로 바꾸는 과정이다. 

gcc -S hello.i //Compilation only

Assemble은 Assembly code를 기계어로 바꾸는 과정이다.

as -o main.o main.s // Assembling only

마지막으로 Linking은 기계어로 된 여러 파일로 만들어진 코드들을 하나로 합쳐 실행파일로 만드는 과정이다.

ld -o main.exe main.o ... additional library ... //Linking only


여기서 Linking과정을 제외한 preprocession, compiling, assembling과정을 한번에 해서 

c코드를 한번에 기계어고 바꾸는 과정을 빌드라고 한다.

gcc -c main.c //Object code main.o 출력

그 다음 실행코드를 만드는 것은 다음과 같이 하면 된다.

gcc -o main.exe main.o hello.c //Executable code 출력


어쨌든.... 컴파일 하려면 cmd창에 여러줄을 쳐야하는데 한 과정을 잘 못 하면 계속 다시 적어야 하기때문에 컴파일 과정을 한번에 해주는 유틸리티가 있는데 이것이 make이다.

make 프로그램은 http://gnuwin32.sourceforge.net/packages/make.htm 에서 다운가능하다.

다운한 다음에 C:\Program Files\GnuWin32\bin 로 path에 환경변수 설정을 한다.


<Let's do it>

이제 간단한 "hello world!"가 찍히는 프로그램을 실행하면서 어떻게 쓰는 것인지 알아보자.


1) vim

환경변수 path 설정을 했기 때문에 어떤 디렉토리에서는 vim을 실행시킬 수 있다.

cmd창이 있는 디렉토리에서 vim [파일이름]을 적으면 해당 이름을 가진 파일이 열린다.



vim에 들어갔으면 키보드의 i를 누르면 편집모드로 글을 적을 수 있다.


위와 같이 글을 다 적은 후에는 ESC를 누르면 명령어 모드로 바뀐다.

주요 명령어는 다음과 같다.

:w //저장

:w file.txt // file.txt 파일로 저장

:q //vim 종료

:wq //저장 후 종료



다음과 같이 코드를 적고 esc를 누른다음 :wq를 누르면 코드가 저장되고 해당 디텍토리에 파일이 만들어 진다.



마찬가지로 다음과 같이 hello.c와 hello.h를 만든다.



2) Makefile

c코드가 있는 같은 디렉토리에 Makefile을 만들어야 한다.



make의 기본규칙은 크게 Target, Depend, Command로 구성되어 있다.


<Targer>: <Depend>

<TAP 문자><Command>


Target은 생성하고자 하는 목적물을 지칭하고 

Depend는 Target을 만들기 위해서 필요한 요소를 기술하게 되고

Command는 일반 Shell 명령이 온다. 

여기서 주의할 것은 Comman 앞에 반드시 TAB문자가 와야 한다는 것이다.

Command 명령은 Depend와 Target의 파일생성시간(또는 변경된 시간)을 비교하여 Depand의 파일의 시간이 보다 최근일 경우에만 실행된다. 



다음과 같이 Makefile을 만들고 저장한다.

그리고 cmd 창에 "make run"이라고 치면 자동으로 컴파일되고 프로그램이 실행된다.

이러한 Makefile은 리눅스에서도 똑같이 쓸 수 있다.







참고

VIM 활경변수 설정

http://harveytoday.tistory.com/84

VIM 사용법

https://opentutorials.org/course/730/4561

http://www.morenice.kr/25

Makefile 만들기

http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/minzkn_make

'프로그래밍 > 자료구조설계' 카테고리의 다른 글

인터넷 check sum 함수의 구현  (0) 2016.02.08
다운  (0) 2016.02.07
void*  (0) 2015.10.23
열거형 enum  (1) 2015.10.23
:
Posted by youjin.A

visual studio 설치 설정


Hello world


:
Posted by youjin.A

구조체 포인터라고 해서 다를 것 없다.

int형 포인터 변수를 선언하듯이 선언하면 되고, int형 포인터를 통해서 접근하듯이 접근하면 된다.


-구조체 포인터

함수의 인자로 기본자료형 변수와 마찬가지로 구조체 변수도 포인터로 전달 할 수 있다.

이렇게 함수 내부에서 외부에 있는 구조체 변수에 직접 접근하기 위해 구조체 포인터를 쓴다.

구조체 변수의 포인터 선언 방식과 매개변수로 구조체 포인터를 선언하는 방식은 일반적은 변수의 포인터 선언규칙을 그대로 적용하면 된다.

또한 구조체 변수의 주소 값을 얻을 때고 & 연산자를 사용한다.


-포인터를 이용한 구조체 멤버의 접근

(*구조체_포인터).멤버 

여기에서 (*구조체_포인터)는 구조체 변수를 의미하게 된다.

멤버에 접근하는 데 ( )가 필요한 이유는 .연산자보다 *연산자의 우선순위가 낮기 때문이다.

그런데 포인터를 이용한 구조체 멤버의 접근을 간단히 처리하는 -> 연산자가 있는 데 다음과 같은 방식으로 접근이 가능하다.

구조체_포인터->멤버

즉, "(*구조체_포인터).멤버"는 "구조체_포인터->멤버"와 완전히 동일한 연산문이다.


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
#include <stdio.h>
#include <string.h>
 
#define NAME_LEN    30
#define    PID_LEN        15
 
typedef struct _person
{
    char name[NAME_LEN]; //이름
    char ID[PID_LEN]; //주민등록 번호
    unsigned int age; //나이
}person;
 
void ShowPersonData(person * ptr)
{
    printf("이름: %s \n", (*ptr).name);
    printf("주민등록번호: %s \n", (*ptr).ID);
    printf("나이: %u \n", ptr->age);
}
 
int main(void)
{
    person A_youjin = { "안유진""920720-2587412"24 };
    person * personPtr = &A_youjin;
 
    
    ShowPersonData(personPtr);
 
    while (1);
}
cs



:
Posted by youjin.A

1.구조체를 선언할 때 typedef 사용

구조체 변수를 선언 할 때에는 다음과 같이 한다.

struct      자료형_이름      변수_이름;

일반적인 자료형인 int나 double과 마찬가지로 [자료형_이름     변수_이름;] 이렇게 선언하고 싶을 것이다.

앞에있는 struct를 떼버리고...

그런데 typedef 선언을 이용하면 이것이 실제로 가능하다.

typedef    struct    자료형_이름    새롭게_축약된_자료형_이름;        

이 선언에 의해서 새롭게_축약된_자료형_이름 이 struct    자료형_이름 을 대신 할 수 있는 것이다.

이 후 변수를 선언할 때, 컴파일러에 의하여 struct    자료형_이름 새롭게_축약된_자료형_이름이 둘 다 사용될 수 있다. 


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>
 
struct point
{
    double    xpos;
    double    ypos;
};
 
typedef    struct point point;
 
int main(void)
{
    point p1;
    struct point p2;
 
    p1.xpos = 0.1, p1.ypos = 0.2;
    p2.xpos = 2.4, p2.ypos = 2.5;
 
    printf("X축 거리: %g \n", p2.xpos - p1.xpos);
    printf("Y축 거리: %g \n", p2.ypos - p1.ypos);
 
    while (1);
}
cs



2.구조체의 정의에 포험되는 typedef

위의 코드에서는 구조체의 정의와 typedef선언을 별도로 하고 있다.

하지만 이 둘을 다음과 같이 묶어서 선언할 수 있다.

 struct   point

{

   double xpos;

   double ypos;

};

typedef   struct point point;

 typedef  struct  point

{

    double  xpos;

    double  ypos;

}  point;


아래의 코드는 위의 코드를 오른편에 선언방식으로 대체한 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
 
typedef struct point
{
    double    xpos;
    double    ypos;
}point;
 
int main(void)
{
    point p1;
    struct point p2;
 
    p1.xpos = 0.1, p1.ypos = 0.2;
    p2.xpos = 2.4, p2.ypos = 2.5;
 
    printf("X축 거리: %g \n", p2.xpos - p1.xpos);
    printf("Y축 거리: %g \n", p2.ypos - p1.ypos);
 
    while (1);
}
cs


:
Posted by youjin.A








:
Posted by youjin.A
2015. 9. 4. 17:43

구조체의 정의 프로그래밍/C언어2015. 9. 4. 17:43

구조체를 사용함으로써 여러 변수를 하나로 묶어 새로운 자료형을 정의 할 수 있다.

 


-구조체 정의

struct     자료형_이름

{

   변수 선언1;

   변수 선언2;

   변수 선언3;

};


배열도 변수이기 때문에 구조체의 멤버가 될 수 있다.

 



-구조체 변수 선언

struct      자료형_이름    변수_이름;


또는 다음과 같이 구조체를 정의함과 동시에 구조체 변수를 선언 할 수 있다.


struct     자료형_이름

{

   변수 선언1;

   변수 선언2;

   변수 선언3;

}변수_이름1, 변수_이름2, 변수_이름3;




-구조체 변수의 초기화

구조체 변수의 초기화 방법은 배열의 초기화와 유사하다.

단순히 멤버의 순서대로 초기화할 대상을 나열하면 된다.

그래서 초기화 과정에서는 문자열 저장을 위해서 strcpy()함수를 호출 하지 않아도 된다.

 



-구조체 변수의 멤버에 접근

​구조체_변수_이름.멤버_이름




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
#include <stdio.h>
#include <string.h>
 
struct person //구조체 정의
{
    char name[20];
    char phoneNumber[20];
    int age;
}man1, man2; //구조체 변수 선언
 
int main(void)
{
    //struct person man1, man2; //구조체 변수 선언
        
    /*구조체 변수의 초기화*/
    struct person man3 = {"홍길동""010-1234-8697", 84};     
    
    /*구조체 멤버에 접근*/
    strcpy(man1.name,"안유진");
    strcpy(man1.phoneNumber,"010-4085-8697");
    man1.age = 23;
        
    /*구조체의 scanf 사용*/
    printf("이름을 입력하세요: "); scanf("%s", man2.name);
    printf("전화 번호를 입력하세요: "); scanf("%s", man2.phoneNumber);
    printf("나이를 입력하세요: "); scanf("%d", &man2.age);
 
    /*구조체의 printf 사용*/
    printf("이름: %s \n", man1.name);
    printf("전화번호: %s \n", man1.phoneNumber);
    printf("나이: %d\n\n", man1.age);
 
    printf("이름: %s \n", man2.name);
    printf("전화번호: %s \n", man2.phoneNumber);
    printf("나이: %d\n\n", man2.age);
 
    printf("이름: %s \n", man3.name);
    printf("전화번호: %s \n", man3.phoneNumber);
    printf("나이: %d\n", man3.age);
    
    return 0;
}


:
Posted by youjin.A

컴파일 할 때, 특정 조건에 따라 소스코드의 일부를 삽입할 수 있는 지시자들이 있다.

이 지시자에서 조건을 만족하지 않아서 삽입되지 않은 코드는 오류가 있더라도 전체 프로그램은 컴파일 오류가 생기지 않는다.


1. #if... #endif : 매크로가 참이면

#if (매크로)

코드

#endif

매크로가 참이라면 코드가 소스에 삽입되고, 거짓이면 코드는 삭제된다.

매크로 부분에 연산자는 사용가능하나 변수는 사용할 수 없다.

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
#include <stdio.h>
#define ADD    
#define MIN    
 
int main(void)
{
    int num1, num2;
    //int add = 0, min = 1;
 
    printf("두 개의 정수 입력: ");
    scanf_s("%d %d"&num1, &num2);
 
 
 
#if ADD
    printf("%d + %d = %d\n", num1, num2, num1 + num2);
#endif // ADD
 
#if MIN
    printf("%d - %d = %d\n", num1, num2, num1 - num2);
#endif // MIN
 
    return 0;
}
 








2. #ifdef... #endif : 매크로가 정의되어 있다면

#ifdef (매크로)

코드

#endif

매크로가 #define으로 정의가 되어 있다면 코드가 삽입된다.

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
#include <stdio.h>
#define ADD    0
#define MIN    1
 
int main(void)
{
    int num1, num2;
    //int add = 0, min = 1;
 
    printf("두 개의 정수 입력: ");
    scanf_s("%d %d"&num1, &num2);
 
 
 
#ifdef ADD
    printf("%d + %d = %d\n", num1, num2, num1 + num2);
#endif // ADD
 
#ifdef MIN
    printf("%d - %d = %d\n", num1, num2, num1 - num2);
#endif // MIN
 
    while (1);
}
 
cs

3. #ifndef... #endif : 매크로가 정의되지 않았다면
#ifndef (매크로)
코드
#endif
위의 #ifdef... #endif와 비슷하지만 이 지시자는 매크로가 정의되지 않았다면 코드를 삽입한다.

4. #else의 삽입 : #if, #ifdef, #ifndef에 해당
#if (매크로)
코드1
#else
코드2
#endif
#if의 경우 매크로가 참이거나, #ifdef의 경우 매크로가 정의되어 있거나, #ifndef의 경우 매크로가 정의되어 있지 않으면 코드1을 삽입하고 아니면 코드2를 삽입한다.  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#define HIT_NUM 6
 
int main(void)
{
#if HIT_NUM == 5
    puts("1");
#else
    puts("2");
#endif
 
    while (1);
}
 
cs
위 코드를 실행하면 2가 출력된다.

5. #elif의 삽입 : #if에만 해당
#if (매크로1)
코드1
#elif (매크로2)
코드2
#endif

#else + if인 것으로 조건을 추가할 수 있다.

#if의 경우에만 사용할 수 있다.

매크로1이 참이면 코드1을 수행, 매크로1이 거짓이고 매크로2가 참이면 코드2를 수행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#define HIT_NUM 6
 
int main(void)
{
#if HIT_NUM == 5
    puts("5");
#elif    HIT_NUM == 6
    puts("6");
#else
    puts("nope");
#endif
 
    while (1);
}
 
cs


:
Posted by youjin.A