브래의 슬기로운 코딩 생활
C 언어 문법 정리 - 식별자, 리터럴(상수), 자료형, 변수, 전처리기, 연산자 본문
입출력 스트림 객체 cout, cin
- iostream 파일을 프로그램에 포함하면 자동으로 열리는 자동 스트림(stream) 객체
- #include <iostream>
- cout << // 화면으로 출력하는 객체, printf()
- cin >> // 키보드로부터 데이터를 입력 받는 객체, scanf()
여러 변수 값 출력(printf vs cout)
- printf("%d, %d, %d\n" ,a,b,c); //C
- cout<<a<<','<<b<<','<<c; //C++
printf()함수의 여러 가지 사용 예
입력함수 : scanf()
- 지정된 형식에 따라 키보드로부터 데이터를 입력받는 함수
- scanf("형식문자열",&변수1, &변수2,….);
scanf()사용 시 visual studio 오류
- error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To
disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
#define _CRT_SECURE_NO_WARNINGS 추가
- 주의 반드시 첫번째 줄에 작성
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
.
.
입력 스트림 객체 cin
- 키보드로부터 데이터를 입력받는 객체
- cin >>변수명;
식별자와 명명 규칙
- 식별자(identifier)란 변수, 함수, 구조체 등에 부여하는 이름
- 영문자(A∼Z, a∼z), 숫자(0∼9), 밑줄(_)만 가능
- 한글이나 밑줄(_)을 제외한 특수 문자는 불가능
- 첫 글자는 반드시 영문자 또는 밑줄로 시작
- 밑줄은 첫 글자로 가능하지만 특별한 의미를 갖는 미리 만들어진
식별자들이 밑줄로 시작하는 경우가 많으므로 사용하지 않는 것이 좋음
- 예약어(if, for, int 등)는 식별자로 불가능
- C 언어는 대문자와 소문자를 구분하는 언어이므로 Max와 max는 다른 식별자
변수 명
- 명사, 소문자
- student, my_age(snake case), myage, g_num_errors(전역변수)
- 카멜 표기법(camel case, JAVA에서 권장): myAge, typeName, camelCaseVar(lower camel case)
매크로 명
- 명사, 모두 대문자, _
- #define MAX_STUDENT
const 상수 명
- 명사, 첫 글자와 의미가 바뀌는 부분은 대문자, 나머지는 소문자(upper camel case)
- const int DaysInWeek=7;
구조체 명, 열거형 명
- 명사, 첫 글자와 의미가 바뀌는 부분은 대문자, 나머지는 소문자(upper camel case)
함수 명
- 동사, 첫 글자와 의미가 바뀌는 부분은 대문자, 나머지는 소문자(upper camel case)
- AddNumber(), DeleteName()
식별자의 예
- 식별자로 올바른 예
counter, var1, s_p, top_of_page, LastName, _SUM1
- 식별자로 잘못된 예
리터럴 (literal) - 문자 그대로
- 상수
정수형 리터럴
- 10진 정수 리터럴은 우리가 일상적으로 접하는 정수
- 8진 정수 리터럴은 0에서 7까지만 사용하는 8진수로 구성된 수
- 16진 정수 리터럴은 10진수 10에서 15에 해당하는 수를 표현하기 위해서 A(a)에서 F(f)까지의 영문자를 사용
- long형 상수의 경우에는 숫자 뒤에 대문자 L이나 소문자 l을 더 씀
실수형 리터럴
- 부동소수점(floating point)상수
- 소수점을 포함하는 수로 정수형보다 더 크고 작은 수를 정확하게 표현할 수 있음
문자형(character) 리터럴
- 줄여서 char형
- 1바이트의 메모리에 저장
- 작은 따옴표(' ')로 묶어 사용하는 하나의 문자
- 실제 메모리에 저장될 때는 해당 ASCII(American Standard Code for Information Interchange)코드 값으로 저장됨
ASCII
- American Standard Code for Information Interchange
- 문자를 컴퓨터에 7비트로 인코딩(2진수로 저장)하는 방법
- 7비트 인코딩으로, 33개의 출력 불가능한 제어 문자들과 공백을 비롯한 95개의 출력 가능한 문자들로 총128개
- 출력 가능한 문자들은 52개의 영문 알파벳 대소문자, 10개의 숫자, 32개의 특수 문자, 하나의 공백문자
- 65=A / 97=a
이스케이프 시퀀스(확장 문자열)
- 이스케이프 시퀀스(escape sequence)는 탈출 문자 또는 확장 문자열이라고도 함
- 역슬래쉬(\ )와 영문자나 특수문자로 이루어진 문자 조합
- 두 개의 문자로 보이지만 두 개의 문자가 하나의 의미를 갖는 단일 문자(1byte)
문자열(string) 리터럴
- 여러 개의 문자 모임
- 2개(한글은 한 개) 이상의 문자
- 큰 따옴표(" ")로 묶어서 표현
- 각 문자가 한 바이트 씩 저장됨
- 문자열 리터럴 "ABCD"는 각각 2진수로 메모리에 저장됨
- 문자열 리터럴에서는 문자열의 끝을 의미하는 NULL 문자가 제일 뒤에 자동적으로 붙여짐
- " " 안에 escape sequence 사용 가능: "홍길동\n"
- 'A'와 "A"의 차이 = 문자 vs 문자열 = 1바이트 vs 2바이트
자료형(data type)
- 자료형(data type)은 처리, 저장하고자 하는 자료의 형태
기본 자료형(basic type)
문자형, 정수형, 부동형, 열거형(enum)
유도 자료형(derived type)
배열(array), 함수(function), 구조체(structure), 공용체(union), 포인터(pointer)
void형
값이 없음을 표시하는 자료형
void play(void){ }
변수(variable) 선언문
- 자료를 저장하도록 할당된 기억장소의 이름을 변수(variable)라 함
- 변수는 프로그램이 실행되는 동안 가변적인 자료를 저장하기 위한 기억장소의 이름으로 모든 변수는 사용하기 전에 선언을 해야 함
- 변수 선언 방법은 변수명 앞에 자료형을 씀
변수 선언 예
변수 하나씩 선언
- int num; //정수형 변수 num선언
- char ch; //문자형 변수 ch선언
- double average; //double형 변수 average선언
동일한 자료형을 갖는 두 개 이상의 변수는 콤마(,)로 변수와 변수를 구분하여
한번에 선언
- int num1, num2, num3; // 구두점 콤마
같은 방법으로 다음과 같은 변수 선언도 가능
- double sum, ave, number;
- char ch1, ch2;
변수 선언과 초기화
변수 선언
- char ch;
- int num;
- int num1, num2;
- double sum, average;
변수를 선언하면서 초기화
- char ch='A';
- int num=0; //정수 리터럴 0을 정수형 변수 num의 초기값으로 함
- int num1=2, num2=5;
- double sum=10.0, average=4.5;
변수에 값을 저장할 때는 대입(배정, 할당)연산자인 "="를 이용
- int num; //변수 선언
- num=10; //값 할당
- num이 10과 같다는 뜻이 아니고, 10을 num변수의 값으로 할당 (메모리에 저장)하라는 의미
선언문의 위치
- C언어에서 모든 선언문은 실행문 보다 앞에 있어야 했음
- C99부터는 실행문 다음에 선언문이 올 수 있음
- C++에서도 실행문 다음에 선언문이 올 수 있음
- 하지만 선언문은 되도록 실행문 앞에 작성하는 것이 프로그램을 이해하기에 좋음
선언문의 사용 목적
- 자료형을 미리 컴파일러에게 알려 주어 기억 장소를 확보
- 사용자가 자료형이나 변수명을 잘못 사용하였을 때 발생하는 오류를 쉽게 검출할 수 있도록 함
기본 자료형의 종류 : 문자형(char)
기본 자료형의 종류 : 정수형
C99에서 추가된 정수형
C99에서 추가된 정수형은 long long int와 _Bool형
- long long int형은 최소 8바이트로 규정
- C99에서 추가된 _Bool형은 boolean형으로 0이나 1만을 저장하는 부호없는 정수형 (0이 아닌 다른 값은 모두 1로 바뀌어 저장됨)
- C 언어에서는 0은 거짓, 0이 아니면 모두 참
기본 자료형의 종류 : 실수형
실수형(부동형, floating type)의 크기와 종류
변수를 상수화 : const
- const키워드를 이용하면 변수를 상수화할 수 있음
- 자료형 앞에 const를 추가하면 되고 초기값을 변경할 수 없음
자동 형 변환
자료형이 서로 다른 혼합 연산에서는 기억 장소의 크기가 큰 쪽으로 통일시켜 연산이 이루어짐. 이것을 자동 형 변환(implicit arithmetic conversions)이라 함
전처리기 (preprocessor)
- 전처리기(preprocessor)는 컴파일하기 전에 프로그램에 대한 일련의 작업을 수행하는 것으로 일반적으로 main()함수 외부에 작성
- 기계어 코드를 생성하지 않으며 소스 코드를 컴파일하기 좋게 가공
- 모든 전처리기는 #기호(구두점)를 명령어 앞에 붙이고 마지막에 문장의 끝을 나타내는 세미콜론(;) 기호를 사용하지 않음
- stdio.h 등의 표준헤더 파일에서 많이 볼 수 있고 #include, #define이 대표적
#define문 : 매크로 vs. 함수같은 매크로 - 매크로(macro), 함수같은 매크로를 만들 때 사용
매크로(object-like macro)
매크로 상수라고도 함
#define PI 3.141592
매개변수가 있는 함수같은 매크로(function-like macro)
Macros with arguments / 매크로 함수라고도 함
#define SUM(i,j) (i+j) / 여기서 i,j가 매개변수
#include문
- 파일을 프로그램에 포함시키고자 할 때 사용하는 전처리기
- 각종 라이브러리 함수(printf() 등)의 프로토타입(원형, 선언)이나 구조체의 데이터 형 선언 등이 들어 있는 헤더 파일을 프로그램에 포함시키고자 할 때 많이 사용
- #include <stdio.h> = 컴파일 전에 stdio.h파일을 프로그램에 포함(추가)해 주세요!
- "<"과 ">"는 표준 헤더 파일을 표준 헤더 디렉토리에서 찾아 포함시키는 경우에 사용함
- 표준 헤더 파일이 아닌 프로그래머가 만든 파일을 포함시킬 때는 다음과 같이 함 // #include "파일명"
연산자
연산자의 우선순위(precedence)와 결합성(associativity)
- 결합성(associativity)
- 우선순위가 같은 연산자의 결합 방향
- 연산자의 우선순위
- 한 수식에 연산자들이 여러 개 있을 때 우선순위가 제일 높은 것은 괄호 안의 수식
- 괄호들이 중첩되어 있을 때는 내부 괄호가 우선순위가 높음
- 사칙연산은 *, /, 그 다음이 +, -이며 우선순위가 같으면 다음과 같이 왼쪽에서 오른쪽으로 연산을 진행
- 대입 연산자(=, +=, -= 등)는 오른쪽에서 왼쪽으로 실행
- a*b한 결과를 x에 대입하는 것으로 오른쪽에서 왼쪽으로 실행
- 괄호 연산자(())가 우선순위가 가장 높고, 콤마 연산자가(,)가 가장 낮음
산술연산자
- 산술 연산자에는+, -, *(곱셈), /(나눗셈)와 나눗셈의 나머지를 계산하는 %연산자
- *, /, % 연산자는 우선순위가 같고 +, - 연산자보다 우선순위가 높음
- 결합 방향은 수학에서와 같이 왼쪽에서 오른쪽
- 10/4의 결과는 2.5가 아닌 2
- C 언어에서는 자료형이 서로 다른 혼합 연산에서는 기억 장소의 크기가 큰 쪽으로 통일시켜 연산이 이루어짐(자동 형 변환(implicit arithmetic conversion))
- a%b는 a를 b로 나누었을 때 나머지를 구함(modulo)
증가, 감소 연산자
- 산술 연산자로 피연산자가 하나인 단항 연산자
- 이 연산자는 피연산자의 값을 1만큼 증가(++)나 감소(--)시킴
- ++, --연산자는 피연산자의 좌측이나 우측에 쓸 수 있음
- 피연산자 앞에 쓰는 경우는 전치(전위, prefix)
- 피연산자 뒤에 쓰는 경우는 후치(후위, postfix)
cast 연산자
- 이미 지정된 자료형을 다른 자료형으로 일시적으로 강제로 바꿀 수 있는데 이것을 명시적 형 변환이라고 하며 이때 cast 연산자 사용
- 변환시키고자 하는 값이나 변수 앞에 해당 자료형을 괄호로 묶어 주면 됨
- (자료형)값_이나_변수
- 우선 순위가 두 번째로 높은 연산자
- 숫자 3은 int형이지만 (double)3은 일시적으로 double형 3.0
- 'A'는 문자이지만 (int)'A'는 숫자(ASCII코드 값) 65
- int형 65는 숫자이지만 (char)65는 ASCII코드 값 65에 해당하는 문자 'A'
sizeof 연산자
- sizeof 연산자는 변수나 자료형, 배열 등이 차지하는 메모리 영역의 크기를 바이트(byte) 단위로 얻음
- 자료형의 크기를 알고 싶을 때는 반드시 괄호를 사용해야 하며 변수는 괄호를 생략해도 됨
- sizeof 변수_나_배열명
- sizeof(자료형)
- 상수 문자열의 경우 널 문자(\ 0, 1바이트)를 포함한 길이가 나옴
- 한글은 한 글자가 2바이트
- sizeof("대한민국")은 9(마이크로소프트 윈도우)나 13(uft-8)
- 배열은 sizeof(배열명)을 쓰고, 자료형×방의 크기가 계산되어 나옴 (배열은 한 방 당 4바이트)
삼항 조건 연산자 ( ? : )
- ternary conditional operator
- 항이 3개여서 3항 연산자라고도 하며 if~else문을 한 줄로 간결하게 표현할 수 있음
- 수식1 ? 수식2 : 수식3
- 수식1의 조건이 참이면 수식2를 실행하고, 거짓이면 수식3을 실행
대입 연산자
- 대입 연산자는 "변수=수식"과 같이 대입하는 연산
- 수식의 값을 변수에 대입하는 연산자
혼합 대입 연산자
- 산술 연산자와 대입 연산자를 혼합하면 다양한 혼합 대입 연산자를 만들 수 있음
변수=변수+수식;
변수+=수식;
- 다음은 같은 표현
a=a+5; a+=5; // a의 값을 5 증가
x=x-3; x-=3; // x의 값을 3 감소
num=num*2; num*=2; // num의 값을 2배
total=total/2; total/=2; // total 값을 나누기 2
a=a+1; a+=1; a++; ++a; // a의 값을 1 증가
a=a-1; a-=1; a--; --a; // a의 값을 1 감소
- 혼합 대입 연산자는 -=, *=, /=, %=, <<=, >>=, &=, ^=, |=
x=x*(y+5);
x*=y+5;
관계 연산자 : <, <=, >, >=
- 관계 또는 비교 연산자는 루프(loop)나 조건문(if) 등에서 크기나 조건 등을 비교할 때 사용하는 연산자
- 크기를 비교하는 <, <=, >, >=연산자
- 연산 결과가 참이면 1, 거짓이면 0이 나옴
- 정수형과 실수형 뿐만 아니라 문자형 데이터도 대소 관계를 비교할 수 있음
(문자형 데이터들의 크기를 비교할 때는 해당 ASCII코드 값으로 비교함)
관계 연산자 : ==, !=
- 같은지를 비교하는 ==연산자 // 참이면 1 거짓이면 0
- if(num=1) printf("남성"); //주의
=를 한번 쓰면 값을 저장하는 대입 연산자가 되므로 전혀 다른 결과가 나오게 됨 / num에 1을 저장하면 num의 값이 참(0이 아니므로)이므로 조건식이 참이 됨 / if(num==1) printf("남성");로 수정해야함
- 같지 않은지를 비교하는 !=연산자
논리 연산자 : &&, ||, !
&&(AND), ||(OR), !(NOT)
- &&와 ||는 두 개의 피연산자가 필요
- &&연산자는 두 피연산자가 모두 참일 때 참
- ||연산자는 둘 중 하나만 참이면 참
- !연산자는 한 개의 피연산자 필요
- !연산자는 피연산자가 참이면 거짓으로, 거짓이면 참으로 만듦
관계 연산자+논리 연산자
- score값이 90이상~95 미만이면 A출력
- if(90<=score<95) // X
- 관계 연산자는 우선순위가 같으면 왼쪽에서 오른쪽으로 연산을 진행하는 결합성을 가짐
- C언어에서는 다음과 같이 표현 // if(score>=90 && score<95) : O
비트 연산자(bitwise operator)
- 수를 2진수로 바꾼 후 비트별로 연산
비트 시프트(bitwise shift) 연산자
- 우측의 숫자만큼 좌측 혹은 우측으로 비트를 시프트시킴
- 양의 정수의 경우 좌측(<<시프트 연산자)으로 한 비트씩 시프트시킬 때 마다 원래 값의 두배
- 우측(>>시프트 연산자)으로 한 비트씩 시프트시킬 때 마다 원래 값의 1/2배
- 시프트시킬 때 빠져나가는 비트가 1이면 overflow나 underflow가 발생하여 2n배의 곱이나 나누기가 되지 않음
- 90<<2는 90을 2진수로 만든 후 왼쪽으로 2번 시프트하므로 360 (90×2×2)이 됨
- 시프트 연산자의 피연산자는 정수형만 가능
- 부호있는 정수형도 가능하지만 일반적으로 부호없는 형만 사용
기타 연산자
[] 첨자 연산자
배열 / a[b] / int x[10]; x[0]=1;
구조체 멤버 접근 연산자
Structure reference / a.b (일반구조체변수.멤버)
Structure dereference / a->b (포인터구조체변수->멤버)
* 간접참조연산자
포인터 변수의 저장 주소로 가서 값을 가져옴
Indirection / int x=10, y;int *px=&x; y=*px;