정보처리기사 공부하면서 정리한 내용입니다.
C언어의 컴파일 과정
- .c → 전처리기 → .i
전처리 구문을 처리하는 과정
- ex. .c 파일로 코드를 짤 때. 맨 위에 #include<stdio.h> 를 넣는것.
- 여기에 printf 등의 많이 쓰는 함수가 들어있다. 이걸 내가 만든 것과 합쳐주는 것이 전처리기의 역할.
- .i → 컴파일러 .s
고수준 언어를 저수준 언어로 변환하는 것. (번역)
기계어와 가장 가까운 형태의 언어로 바꿔준다.
- .s → 어셈블러 → .o
완전히 기계어로 바꾸어 준다.
- .o → 링커 → .exe
여러 개의 오브젝트 파일을 합치거나, 라이브러리를 합치는 역할.
변수
변수 생성 규칙 및 특징
- 사용 불가
- 예약어(키워드)
- 공백 포함
- 언더바 이외의 특수문자
- 제한
- 첫 글자는 영문과 언더바(_)만
- 대소문자를 구분한다
데이터 타입 (자료형)
자료형 - 메모리크기 - 데이터범위
- 문자형
- char
- 1Byte
- -128 ~ +127
- char
- 정수형
- short
- 2Byte
- -32768 ~ +32767
- int
- 4Byte
- -214783648 ~ +214783647
- long
- 4Byte
- -214783648 ~ +214783647
- short
- 실수형
- float
- 4Byte
- double
- 8Byte
- float
변수의 종류
지역변수
함수/블록 안에서 선언하는 변수
함수/블록 종료와 함께 메모리상에서 소멸한다
초기값이 없으면 쓰레기 값이 들어간다
스택 영역에 저장된다
void main(){ //프로그램의 처음은 main
if(1){ //1은 true
int num1 = 10; // num1이라는 변수에 10이라는 값 넣기
printf("%d", num1); // 결과는 10
}
printf("%d", num1); // num1이라는 변수가 존재하지 않음
}
전역변수
함수 블록 밖에서 선언하며 전체 함수에 영향을 미친다.
프로그램이 종료될 때 메모리상에서 소멸한다
초기값이 없으면 0 값이 들어간다
데이터 영역에 저장된다
int num1; // 전역변수 num1 선언
void main(){
num1 = 10; // num1에 10 넣어줌
printf("%d", num1); // 10 출력
func(); // func 실행 (num1에 20넣음)
printf("%d", num1); // 20 출력
}
void func();{
num1 = 20; // num1에 20 넣어줌
}
정적변수
static으로 선언하며 선언된 블록 내에서만 사용 가능
함수가 종료되어도 소멸되지 않고 값이 유지된다
프로그램이 종료될 때 메모리 상에서 소멸
초기값이 없으면 0이 입력되고 단 한번만 초기화
데이터 영역에 저장된다
void main(){
add(10); // ①add 실행
add(5); // ②add 실행
add(3);
}
int add(int i){
// ①i 에 10 넣음
// ②i에 5 넣음
static int sum = 0;
// ①정적변수 sum 선언
// ②정적변수가 저장되어 있으면 이 값을 무시하고 저장되어있는 값 불러옴 (10)
sum = sum + i;
// ①0+10
// ②10+5
printf)"sum:%d\\n", sum);
// ①sum:10(엔터)출력
// ②sum:15(엔터)출력
}
동적변수
메모리 동적할당으로 생성되는 변수 (필요할 때마다 그때그때)
Run time 시간에 메모리 할당
- 런타임이란?
- 프로그램이 실행되고 있을 때를 뜻한다
무조건 포인터를 사용해야 한다
힙 영역에 저장된다
📌 연산자
단항연산자
++, --
a++, ++a ← 앞에 오느냐, 뒤에 오느냐에 따라 시행 순서가 다르므로 주의.
EX
#include<stdio.h>
int main(){
int a = 5, b = 5;
a *= 3 + b++;
printf("%d %d", a, b); // 40 6
return 0;
}
- a와 b에 각각 5를 대입한다
- 대입연산자인 *= 의 우선순위가 제일 낮다는 걸 알수있다.
- 따라서 3 + b++ 먼저 수행한다.
- ++ 의 우선순위가 가장 높지만, 뒤에 있으므로 식 수행 뒤 b를 1 증가시킨다.
- 3 + b 는 8
- b를 1 증가시켜서 b는 6이 된다.
- 따라서 a *= 8 을 풀어쓰면 a = a * 8
- a값인 5 * 8 = 40 → a의 값은 40이 된다
논리연산자
- ! : NOT 부정한다
- !9 라면
- 값이 있는 것을 부정한다 (참을 NOT 시켜버림)
- 따라서 거짓(0)
- 값이 있는 것을 부정한다 (참을 NOT 시켜버림)
- 9 라면
- 값이 있다
- 따라서 참(1)
- 값이 있다
- !9 라면
- && : AND. 비교. 좌-우 두 값이 둘 다 참일 때만 참(1)
- 좌항 값이 거짓인 경우 우항은 연산하지 않는다 ⭐
- || : OR. 좌-우 두 값 중 하나만 참이라면 참(1)
- 좌항 값이 참인 경우 우항은 연산하지 않는다 ⭐
EX
y = 3 + 2 * ( x = 7 / 2);
- 모든 변수가 int형이라고 가정할 때 각 변수들의 값은?
- 모든 값이 int = 정수
- ( ) 가 가장 우선순위가 높다
- = 가 가장 낮으니 나누기부터
- 정수 / 정수는 정수다!
- x = 3
- 9를 y에 대입한다
- y = 9
📌비트연산
비트연산자 종류
&
: AND 2개가 다 참일 때만 참 [논리곱]
- 5 & 3
- 5 = 0101
- 3 = 0011
- 0, 0 → 0
- 1, 0 → 0
- 0, 1 → 0
- 1, 1 → 1
- 0001 에 8421을 씌우면 1
|
: OR 2개 중 하나만 참이어도 참 [논리합]
- 5 | 3
- 0, 0 → 0
- 1, 0 → 1
- 0, 1 → 1
- 1, 1 → 1
- 0001 위에 8421을 씌워준다
- 결과 4, 2, 1 자리에 1이 있다
- 4 + 2 + 1 = 7
^
: XOR(exclusive or) 둘 중 하나만 틀려야지 참 [배타적 논리합]
- 5 ^ 3
- 0, 0 → 0
- 1, 0 → 1
- 0, 1 → 1
- 1, 1 → 0
- 8421 모자를 씌워주면
- 0110 이니까 4 + 2 = 6
~
: NOT
- ~5
- 양수라면 하나 더하고 -를 붙인다
- ~16 = -17
- 음수면 하나 빼고 +를 붙인다
- ~-16 = 15
- 양수라면 하나 더하고 -를 붙인다
>>
: 우시프트!
- 10 >> 2
- 10을 2진수로 바꾸면 1010
- 2개의 비트만큼 오른쪽으로 밀라는 뜻
- 1010 → 10이 된다
- 십진수로 바꾸면 2가 된다.
<<
: 좌시프트!
- 10 << 2
- 뒤에 0을 붙여주면 된다
- 2니까 0 두개 00을 붙여준다
- 1010 → 101000이 된다
- 십진수로 바꾸면 40이 된다.
EX
#include<stdio.h>
void main(){
int x = 0x11; //16진수 11
// 16진수 11을 2진법으로 바꾸면 00010001
// 10진법으로 바꾸면 17
int y, z;
y = x & 0x0f; // 0x0f는 00001111
// AND 연산 결과값은 00000001
// 10진수로 바꾸면 1 이걸 y에 대입
z = x | 0x0f;
// OR 연산을 하면 00011111
// 10진수로 바꾸면 16+8+4+2+1 = 31이 z에 대입된다
printf("x=%d, y=%d, x=%d, x, y, z);
// x=17, y=1, z=31
}
앞에 0x를 붙이면 16진수, 0을 붙이면 8진수
- 0x0f
- 앞자리는 000
- f는 다 차있는 것. 따라서 f는 1111
- 16진수인 경우 0~9를 숫자로 쓰고
- 10=A, 11=B~ 15=F가 된다
- 10진수로 바꿀때는 32 16 8 4 2 1 모자를 씌우면 된다