c프로그래밍/예습

C언어 6주차 예습

NetStat 2025. 4. 10. 19:56
반응형

전처리기

전처리기는 컴파일하기 전에 프로그램에 대한 일련의 작업을 수행하는것으로 일반적으로 main()함수 외부에 작성한다

기계어 코드를 생성하지 않으며 소스 코드를 컴파일하기 좋게 가공

 

#define문: 매크로 vs 함수같은 매크로

매크로 or 함수같은 매크로를 만들떄 사용한다 

매크로 (object-like macro)

매크로 상수라고도 함

define PI 3.14..

 

매개변수가 있는 함수같은 매크로

macros with arguments

매크로 함수라고도 한다

#define SUM(i,j) (i+j)

여기서 i,j가 매개변수 

 

매크로 도는 매크로 상수는 프로그램 전체에서 하나의 기호 상수를 다른 이름으로 대치시키도록 전처리기에게 알려준다

실제 매크로가 호출되면 호출된 자리에 정의된 기호 상수로 대치된다.

 

scanf 오류 삭제시키는법

warning 4996 오류가 발생할떄 사용한다.

보안관련 오류를 내뿜으면 나오는 오류로  막는방법은 

 

#define _SRT_SECURE_NO_WARINGS

사용방법은 반드시 첫번째 줄에 작성해야한다

#pragma warning(disable:4996) 을 사용해도 된다.

 

#pragma

컴파일러 기능을 지정하는 전처리기

 - 모든 c컴파일러에서 동작하는것은 아니다

Visual Studio에서 동작한다.

#pragma waring(disable:4996)  무시할수 있음

 

GCC 4.0이상에서 동작

GNU

 - GNU's Not UNIX

 

GCC(GNU C Compiler)

 - GNU 프로젝트의 오픈소스 컴파일러 컬렉션 리눅스 계열 플랫폼의 사실상 표준 컴파일러다

 - 리처드 스톨먼이 1987년에 만듬

 - C, C++, Objectlive-Cm Fortran, Ada, Go를 지원한다

 

MinGW(Minimalist GNU for Windows)

 - 윈도우용 GCC

 - Dev-C++

 

#define _SRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define ARRAY_SIZE 3
//개수가 달라지면 소스의 여기저기를 변경해야 하지만 ,define하면 여디만 변경하면 된다.
#pragma waring(disable: 4996) // _CRT_SECURE_NO_WARNINGS

int main(void){
    int i;
    int ch[ARRAY_SIZE];
    for(i = 0; i < ARRAY_SIZE; i++){
        printf("%d번째 수 입력 -->", i + 1);
        scanf("%d", &ch[i]);
    }
    for(i = 0; i < ARRAY_SIZE; i++){
        printf("%d", ch[i]);
    }
    printf("\n입력된 수=%d", ARRAY_SIZE);
    return 0;
}

전처리기는 컴파일전 동작이다.

 

사용하는 이유는 간단한데

아래의 코드처럼 배열크기를 여러군데에 사용하는 코드가 있다고 생각해보자

int ch[3];
for (i = 0; i < 3; i++) ...
for (i = 0; i < 3; i++) ...

 

나중에 배열크기를 수정하고싶으면 컨트롤 h를 사용해 일일히 수정해야한다

근데 매크로를 사용하면 

#define ARRAY_SIZE 3

상단에 이걸 사용하기만하면 배열크기를 3으로 만들수 있고

수정한번으로 전체 배열크기를 5로 바꿀수 있다.

#define문 : 매크로

매크로 또는 매크로 상수는 프로그램 전체에서 하나의 기호 상수를 다른 이름으로 대치시키도록 전처리기에게 알려줌

- 실제 매크로가 호출되면. 호출된 자리에 정의된 기호 상수로 대치됨

- define 매크로명 상수 or 문자열

  •  ex) define PI 3.14..
    • 프로그램 중에 PI를 찾아 컴파일하기 전에 모두 3.14..로 바꾸어준다
    • 그래서 컴파일되는 소스에는 더 이상 PI는 존재하지 않게된다.
  • 매크로 명은 모두 대문자, 단어 사이는 언더스코어_ 를 사용한ㄷ
    • PI,SIZE,ARRAY_SIZE,BUFFER_SIZE

#define문 : 함수같은 매크로(function-like macro)

  • #define 매크로명(매개변수)(치환리스트)
    • 매크로명 다음에 괄호가 오고 괄호 안에는 매개변수
    • 치환리스트의 매개변수들은 부작용 방지를 위해 일일히 괄호로 묶어 준다
  • #define sum3(i,j,k) ((i)+(j)+(k))
    • 프로그램 중에 sum3(매개변수1, 매개변수2,매개변수3) 부분을 ((매개변수1)+(매개변수2)+(매개변수3))과 같은 형태로 바꾸는것이다
  • 두 개의 수를 제곱하는 SQUARE라는 매크로 함수
    • #define SQUARE(a)((a)*(a))
  • 매크로 함수는 매개변수의 자료형에 관계업이 하나의 매크로 함수로 구현이 가능하다는 장점이 있다.
  • 일반 함수로 구현하면 함수 호출시 해당함수로 넘어가서 실행하고 돌아오는 시간상의 지체가 있는데 비해 매크로 함수는단순히 치환되는 것이므로 속도가 빠르다
  • 부작용 방지를 위해 치환리스트의 매개변수에 귀찮더라도 일일이 괄호로 묶어 주어야 한다
  • 요즘은 C99부터 지원하는 inline함수를 더 많이 사용
    • inline키워드를 함수 정의부 앞에 붙이면 함수 호출시에 해당 함수로 넘어가서 실행하고 돌아오는 시간상의 지체가 없음
    • visual studio에서는 일반 함수를 자동으로 inline으로 만들기도 함

 

 

예제 코드 

#define AA   2 //매크로 상수, 매크로
#define sum3(i,j,k) ((i)+(j)+(k)) //매크로함수, 함수같은 매크로
int main(void){
    printf("%d\n", sum3(AA,4,6));
    printf("%d\n",sum3(AA,4,6)/2);
    printf("%f\n",sum3(1.2,2.3,3.4));   
    printf("%d\n",AA);
    return 0;
}

 

define AA 는 2다

sum3 는 매크로와 함수같은 매크로이며 

#define sum3(i,j,k) ((i)+(j)+(k)) 여기서 i j k 를 순서대로 더한다는 뜻이다 

 

실행결과

    printf("%d\n",sum3(AA,4,6)/2);

여기서 매크로 함수의 부작용이 나타나는데 내가 원한 매크로는 첫번쨰 괄호의 ()덧샘을 먼저하길 바랬는데

위의 식은 6/2 를 먼저한다 그래서 이런 부작용을 방지하기 위해

((AA,4,6))/2 로 해줘야 부작용 없이 매크로 함수를 이용할 수 있다

 

#include 문

  • 파일을 프로그램에 포함시키고자 할 때 사용하는 전처리기
  • 각종 라이브러리 함수(printf())등의 프로토 타입 (원형, 선언)이나 구조체의 데이터 형 선언 등이 들어 있는 헤더 파일을 프로그램에 포함시키고자 할 때 많이 사용한다
  • #include<파일명>
    • #include<stdio.h>
    • 컴파일 전에 stdio.h 파일을 프로그램에 포함(추가) 해 달라는 것이다
  • "<"과">" 는 표준 헤더 파일을 표준 헤더 디렉터리에서 찾아 포함시키는 경우에 사용한다
  • 표준헤더 파일이 아닌 프로그래머가 만든 파일을 포함시킬 때는 다음과 같이 한다
  • #include "파일명"
    • incldue "c:\header_file\asd.h"
    • #include "stdafx.h"
    • #include "resource.h"
      • 디렉터리를 생략하면 현재 작업 디렉터리나 표준 헤더 디렉터리에서 파일을 찾는다
  • 표준 헤더 파일도 큰 따옴표를 이용하여 포함시킬 수 있지만 비추한다

 

#include <stdio.h>

  • stdio.h파일을 컴파일하기 전에 프로그램에 포함시키라는 의미이다.
  • stdio.h파일을 열어보면 다음과 같은 코드들이 있따
    • int__cdecl printf(const char * );
    • printf함수의 매개변수는 문자열이고 ,개수는 가변이며, 기턴값은 int이다
    • printf()함수의 선언 혹은 원형(prototype)
    • c언어에서 표준 라이브러리 함수는 사용하기 전에 반드시 선언해야한다
    • 함수 선언은 함수의 사용법이다

printf() 함수의 선언 (프로토타입)

  • stdio.h 파일을 보면 다음과 같은 코드를 볼 수 있다.
    • _CRTMP int cdecl printf(const char*)
  • 이것을 printf()함수의 선언 혹은 프로토 타입이라고 한다
  • 함수의 프로토타입은 함수의 사용법
  • 함수이름(printf),입력(매개변수,const char*) 출력(리턴형,int)에 관련된 정보를 제공하는 문장

 

printf함수의 리턴값은 ?

int main(){
    int x;
    x = printf("hello world\n");  // "hello world"를 출력하고, 출력한 문자 수를 반환함
    printf("%d\n", x);            // 첫 번째 printf가 반환한 값을 출력함
    return 0;
}

 

hello world
12

실행값을 보면 12가 나오는데 헬로월드까지 11자에 \n은 한문자 취급이여서 12가 나온다

 

전처리기 개요 #if~#endif

  • 해당 부분을 컴파일 할 것인지 하지 않을 것인지를 판단하는 전처리기
  • #if ~ endif
    • 조건이 참인지를 검사하여 참이면 #if와 #endif 사이의 모든 소스 코드를 컴파일
    • #elif는 else if의 줄임말이다
    • 조건1이 참이면 문장1이 컴파일 거짓이면 조건2를 검사하며 참이면 문자2가 컴파일 된다
    • 조건2도 거짓이면 문장 3이 컴파일 된다
#if 조건1 문장1
	#elif 조건2 문장2
    #else 문장3
#endif

 

 

실습문제

 

매크로를 활용하여 이름과 4과목의 성적을 입력받아 이름,총점,평균 출력 하기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//매크로를 활용하여 이름과 4과목의 성적을 입력받아 이름,총점,평균 출력 하기
#define AVERAGE(x,y,z) ((x+y+z)/3.0) //매크로 지정 

int main(void){
    int kor, eng, math, total;
    double avg;
   
    printf("총점과 평균을 구하는 프로그램 입니다 \n");
    printf("수학 점수를 입력해주세요 : ");
    scanf("%d", &math);
    printf("영어 점수를 입력해주세요 : ");
    scanf("%d",&eng);
    printf("국어 점수를 입력해주세요 : ");
    scanf("%d", &kor);
    total = kor + eng + math; // 대입(할당)
    avg = AVERAGE(kor,eng,math); // 대입(할당)
    printf("당신의 총점은 %d 이며 평균은 %.1f 입니다.",total,avg);
    
    return 0;
}

자바처럼 계산식을 main아래 단에 바로 썼더니 오류가 났다

절차지향이라 순서가 매우 중요하니 계산 순서를 꼭 유의해야한다

printf에 &을 썻는데 이러면 큰일난다 scanf야 메모리를 지정해주어야하니 써주는게 맞고

printf는 값만 가져오면 되는거여서 사용하면 안된다.

 

정리

  • 전처리기 개요
    • 전처리기는 컴파일 하기전에 프로그램에 대한 일련의 작업을 수행하는 것으로 일반적으로 main()함수 외부에 작성
    • 전처리기는 기계어 코드를 생성하지 않으며 소스 코드를 컴파일하기 좋게 가공
    • 모든 전처리기는 #기호 를 명령어 앞에 붙이고 마지막에 문장의 끝을 나타내는 세미콜론 기호를 사용하지 않는다.
  • #define
    • 매크로(macro)와 함수같은 매크로를 만들 때 사용 
    • 매크로는 프로그램 전체에서 하나의 기호 상수나 자료형을 다른 이름으로 대치시키도록 전처리기에게 알려주고 실제 매크로가 호출되면 호출된 자리에 정의된 기호 상수나 자료형으로 대치시키도록 전처리기에게 알려주고, 실제 매크로가 호출되면 호출된 자리에 정의된 기호 상수나 자료형으로 대치
    • 두개의 수를 제곱하는 SQUARE라는 함수같은 매크로
      • #define SQUARE(a)((a)*(a))
      • 프로그램 중에 SQUARE(매개변수) 부분을 컴파일 전에 ((매개변수)*(매개변수))와 같은 형태로 바꾼다
  • #pragma
    • 컴파일러 기능을 지정하는 비표준 전처리기
      • #pragma warning(disable:4996)
      • #pragma once
  • #include(문)
    • 컴파일하기 전에 특정 파일을 프로그램에 포함시키고자 할 때 사용
    • #include <stdio.h> // #"stdio.h"라고 써도됨
    • 혹은 #include "c://... 주소로 적어도 된다
    • 디렉터리를 생략하면 현재 작업 디렉터리나 표준 헤더 디렉터리
  • 조건부 컴파일
    • #if같은 조건부 컴파일 명령어는 해당 부분을 컴파일 할 것인지  않을 것인지를 판단하는 전처리기다
    • 조건이 참인지를 검사하여 참이면 #if와 #endif 사이의 모든 소스 코드를 컴파일
  • 기타 전처리기
    • #define에 의해 이미 정의된 매크로를 취소하는 #undef
    • 컴파일 동안 에러가 발생하면 컴파일 작업을 중단하고 행 번호와 파일 이름을 포함하는 에러 메세지를 출력하는 #error
  • #은 매크로 함수의 매개변수를 문자열로 만듦
  • ##은 두 개의 토큰을 결합시킬때 사용
  • 미리 정의된 매크로
    • 미리 정의된 매크로(predefined macro)는 프로그래멀르 위하여 컴파일러가 미리 제공하는 매크로이다.

반응형