C 이론(4)

Hi Beck·2023년 4월 23일

TIL-Language(C & C++)

목록 보기
5/34

전처리기 ~ 연산자 기초

1.들여쓰기하는 이유는 가독성을 위해서다.

2.변수의 이름은 성의있게 지어줘야된다.
(기능에 맞게 어느정도 지어줘야지 사용자가 편히 사용할 수 있음)

3.전처리기 중 #include는 '이 코드(예로 들어 stdio.h같은 애들)를 이 소스코드로 가져온다'라는 기능을 가지고있음.표준 함수들이 다 이 안에 있음

4.함수
사용자 정의 함수 : 내가 직접 만든 함수
라이브러리 함수 : 기본으로 제공되는 함수(=라이브러리가 제공하는 함수,=컴파일러가 제공하는 함수,=내가 만들지않고 어디서 가져오는 함수)
요즘은 기업에서 라이브러리함수를 자기네 스타일로 코드를 수정?해서 쓰는 세상이라 라이브러리 함수와 사용자 정의 함수의 경계가 모호해졌다.

5.함수는 입출력이 무조건 있는게 아니라 없을 수도 있는 것
결국은 어떤 프로그램의 기능을 내가 짜는거기 때문에 모양 및 기능에 따라 구조는 여러개임
코드는 위에서 아래로 한문장 씩 실행이 된다.

6.함수 호출 : 우리가 함수를 정의만 한다고해서 실행 시킬 순 없음.내가 함수를 직접 실행할때만 함수가 실행된다.
함수를 직접 실행한다 = 내가 함수를 필요한 곳으로 호출한다. = 함수를 호출
c언어는 함수의 호출로 이루어져있는 프로그램이다.
(자판기 상상하자 함수를 정의한단건 버튼을 누르면 음료수가 나옴/메인함수은 자판기/입력은 동전/출력은 음료수/함수를 호출하는건 닥터페퍼 수령을 목적으로 기능을 만들때 버튼을 누르면 음료수가 나오도록하는 버튼을 넣은 것과 같은 것)

7.프로그램의 시작점이자 종료점은 main함수
= 메인함수가 끝나면 프로그램도 끝난다는 소리임
-> 우리가 직접적으로 명령하지않는 이상 main문에서 실행하던게 끝나지않고 무한으로 계속 실행 됨.

8.자료형 B();
위와 같은 함수의 호출문에서 ()는 매게변수가 없으면 그냥 비어있는것이다.
(매게변수가 지정되어있었으면 그 매게변수를 넣어주면 되는 것이고)

여기서 함수를 호출할 때 매게변수를 넣어주는 것이랑 함수를 정의할 때 매게변수를 넣어주는 것은 다른것임.
함수를 정의할 때는 괄호 안에 자료형이 들어간다.(예시 int 변수이름 or void는 '없다'라는 자료형임.)
함수를 호출할 때 괄호 안에는 실제 값이 들어가야한다.예로 들어 내가 함수 B라는 애를 int 즉 정수형을 하나 받는 함수로 정의했다면(int N),함수를 호출할 때 옆 괄호 안에 숫자를 넣어주던지 혹은 int형 변수를 하나 넣어주던지
예시)
#inclue <stdio.h>

void testfunc(int n) <------- 함수를 이렇게 정의해놓았으면
{

}

int main() <------- 메인 함수에서 호출할때는 괄호 안에 값을 넣어줘야된다.
{

testfunc(3) <------- '3'이라는 숫자값을 넣어주거나

int num = 3;
testfunc(num);

}
또는 이렇게 변수를 선언하여 호출할때 괄호 안에 변수 값이 아닌 변수명을 넣어주던가하는 식임.(함수가 말하는 건 int형 변수를 받아 사용할거야라는 것)

Q.그렇다면 호출을 내가 필요할 때마다 여러번 호출해야하는지?

A.함수는 그 안에 있는 코드가 한 번 다 실행하고나면 사라진다.
답변 전에 알아야되는 개념 한가지가 있는데 뭐냐면 C언어코드는 무조건 한줄씩 실행이 된다했고,만약 내가 아래와 같은 상황에서 함수를 호출한다했을 때

void testfunc(int n)
{
n = 5;
n = 6;
n = 7;
}

int main()
{
testfunc(3)

int num = 3;
testfunc(num);
}

테스트펑크를 호출할 때 3을 넣으면 위에 함수를 정의했던게 작동될 것인데,n에 3이 넣어지고 함수 밑에 같이 정의되었던 n = 5;, n = 6;, n = 7;가 차례대로 한줄씩 실행될 것이다.그래서 n을 계속 덮어 씌어줄것이다. 3에서5,5에서6,6에서7 이렇게 바꾸고 나서 이 함수가 끝난다.그러고나면 남는 결과는
7일 것 같지만 7은 실행한 함수와 함께 사라진다.

지금 메인에선 testfunc(3)가 실행되고 위에 함수가 날라가고 다음 아무것도 없는 줄로 넘어와있는 상태다.그렇기 때문에 testfunc(3)와 정의된 함수 testfunc는 사라지는 것

void testfunc(int n)의 int n의 수명은 바로 밑 {} 이 안에서만 존재한다.n이 {}를 벗어나면 없는 애인 것

이런 변수(n)을 지역변수라한다.{ }의 범위를 지역이라했을때 변수는 지역 안에서만 산다.

어찌됐든 testfunc(3)이 호출이 되면 8이 되고 그 다음으로는 int num = 3;이 실행되어 num은 3이고, testfunc(num);에다가 다시 num을 넘긴다.
num은 3이니깐 3을 위 함수에 넘긴다.5,6,7하고 사라짐

질문에 대한 본 답변
이런 개념을 바탕으로 호출을 내가 필요할 때마다 여러번 호출해야하는 것에 대한 여부는 정의되어있는 함수는 고정이고, 호출된 함수는 일회용이다.호출되면 그 변수값이 위에서 적용되어 그 함수의 범위 안에서돌면서 실행되고 소멸되고 그 밑에 동일명의 함수가 있으면 역시 그 변수값이 정의된 함수의 자료형 변수에 대입되어 함수가 작동하고 실행된 후 사라짐
<여기서 알아야할 것은 testfunc(3)와 testfunc(num)은 엄연히 다른 존재의 코드여서 하나로 호출한 함수가지고 여러 변수값을 넣고 실행시키는게 아님>

Q.근데 여기서 지금 남는값이 없지않나?
A.여기서 결괏값을 남기고싶으면 그때 반환형을 써주는 것이다.어디에?
정의한 함수에(지금은 보이드니깐 이걸 int로 써주고 밑에 return 써주기)

int testfunc(int n)
{
n = 5;
n = 6;
n = 7;

return n;
}
반환이란건 뭐냐 -> 이 함수 내부(괄호안)에 있는(=안에서만 사는) 지역변수 n을 -> 밖으로 빼주는 것

그렇다면 testfunc(3)를 호출함으로서 밖으로 반환한 것은 어딨냐?
반환형을 받아오는 방법이 있다.
-> testfunc(3) 앞에 변수를 달아주는 것이다.
변수를 선언하는데 값을 함수로 달아주는 것
int test = testfunc(3)

반환한 것이 어딨냐라는 것보단 내가 이 호출을 통해 반환한 값을 받아오고(=사용)싶을때 어떻게하냐면 변수 선언문을 이용하는 것이다.

test라는 메모리공간에 testfunc(3)라는 데이터를 담는데있어서 값이 아니라 함수 호출문 자체를 담은 것임.이 함수호출(오른쪽)을 왼쪽에 대입하는건데 어떻게 함수를 변수에 대입하는거냐면

함수를 호출하면 결과값(=반환값)이 존재한다.이 함수를 호출했을 때 반환하는게 뭐냐면 return n의 n값을 반환해준다.

그런고로 "int test = testfunc(3)"과 "int test = 7"이 같다고 생각하면 된다.

Q.근데 여기서 이해가 안되는게 int test = testfunc(3)나 int test = 7는 7이 들어간 테스트라는 메모리공간인건데 변수 선언만 했을뿐이지 결과값으로 남는다는게 잘 와닿지가 않는다.

A.다시 공부한 결과,반환값은 반환값일뿐(결과값=반환값) 변수선언만 한게 맞고 그 이후에 우리가 한건 아무것도 없다.개념의 차이를 정확히 알아야한다.
함수의 반환값은 그 함수를 호출했을때의 결과값일뿐!!!!!
결과값을 데이터라고 생각하고 매개변수와 혼동하지말자!
매개변수는 함수의 인자로 들어가는 변수들임

반환값이 메게변수로 쓰일 수 있는 존재다?(X)
쓰일 순 있지만 이렇게 정의내리는 것보단 반환값은 다른함수에서도 쓰일 순 있지만 메인함수에서 쓰이는애다.
이렇게 정의내리는게 맞음

함수는 반환값이 일정하다 안하다 -> 일정하지않다.왜냐면 매개변수가 2개인 경우도 있어서 입력값에 따라 결과값이 다를 수 있음

함수는 한번 정의해놓은거고 난 그걸 호출하는 거니깐 함수는 언제나 똑같이 동작해야된다.(자판기에서 버튼을 두 번 눌렀는데 다른 음료수가 나올 수 없는 것처럼)=호출할 때 마다 똑같이 동작(=기능이 같아야한다)해야되는게 함수다.
내가 함수를 정의할 때 매게변수는 다르게 줄 수 있는데(위의 3,num처럼 혹은 다른 상수로)다르게 줘도 결국은 함수가 정의한 것에 따라 돌아가게됨

int test = testfunc(3) test에 testfunc(3)값을 넣었을땐 에러가 나지않는데 밑에

int num = 3;
testfunc(num);
얘는 리턴 값을 받아오긴하는데(얘는 어디 변수에다가 저장해놓는 것도 아니여서) 결과값만 남고 거기서 끝.

근데 이렇게해도 에러는 나지않는다.반환형이 있는데 불구하고, 반환값을 가져와서 진행하지않는다해도 에러는 안난다.결국 아무것도 아닌 코드

즉 int num = 3; testfunc(num);는 숫자 7;과 같은 것임 (어차피 테스트펑크는 함수에서 7을 리턴할것이니깐) 7;만 써놓는다고 에러나진않음(;제대로 찍었으니깐)근데 아무런 역할이 없는 숫자코드일뿐

-> 결론은 내가 뭔가 유의미한 값을 남기고싶으면 함수의 반환자료형과 리턴을 셋팅하고 변수에 대입하는 식으로 유의미한 값을 생성해야되는건데 이 반환값들이 유의미하다는 것은 이걸 다른 기능에 쓰이는 존재가 될 수 있단 것을 의미함

내가 만약 한 함수로 여러 데이터값들을 넣어 출력하고싶으면
int testfunc(int n,int n2,int n3)처럼 매개변수 하나 더 넣어주는 식으로 하면됨

중요한건 어떤 매게변수든 함수는 똑같이 동작해야된다는 것

9.return 0;에서 0은 성공을 말하는건지? 맞다면 아직 성공하지도 모르는데 왜 이렇게 쓰는건지?
-> 보통 프로그램에선 반대로 1이 성공이고 0이 실패임.근데 메인함수에서만 return 0을 성공으로 본다.이걸 왜 우리가 판단하는것처럼 느껴져 의문을 품는것에 대한 답변을 하자면 메인함수에 우리가 쭉 프로그램을 짜는데 정상종료를 해줘야되는데 그 역할을 하는게 return 0이다.즉 리턴이 없으면 프로그램은 비정상 종료가 되었다고 생각한다.이러면 프로그램이 비정상동작을 할 수 있음.(강제종료시 나오는 창같은거)
=여기서 return 0을 성공했냐 실패했냐의 여부로 생각한다기보단 "여기까지 오면 프로그램을 성공적으로 끝냈으니깐 종료해줘"이런 뜻의 성공으로 봐야된다.

결론 : main함수에는 무조건 return 0;을 써준다고 생각하자!!!!(이걸로 무조건)
번외로 반환을 하기싫으면 메인 좌측 반환 자료형에 void를 써주면 리턴을 안써줄 수 있음 설정에 따라 에러날 수 있어서 왠만하면 쓰지말자(상황에 따른것)

10.코드 = 문장

11.변수 = 프로그램이 사용하는 데이터(=임의의 어떤 값들)를 일시적으로 저장할 목적으로 사용하는 메모리 공간 = 저장하는 값들을 써놓는 공간들
얘네는 메모리 공간에 덮어씌워주면 되니깐 언제나 변할 수 있다.

변수는 데이터의 종류에 따라 여러 타입이 존재한다.(void도 자료형임)
데이터를 담는 형태 = 자료형(data = 자료)

int num = 5;
= 난 정수형 변수 하나를 생성하고 그걸 num이라고 부르겠다.그리고 num안에 5라는 자료를 넣어준 것

11.변수의 이름 짓기(TO 가독성)
식별자 = 변수나 함수의 이름
식별자를 만들때는 이름도 중요하지만 문법적인 것도 중요!

1.길게X
2.특수문자X
3.띄어쓰기X(컴퓨터는 공백을 기준으로 한단어로 인식한다.그러면 변수가 2개오는걸로 인식해서 에러남.이럴땐 언더바 활용)
4.앞에숫자X C언어 기본코드 중복X (int printf x int int x)
5.같은 이름의 변수가 있는데 하나는 소문자 다른 하나는 대문자로 되어있을 때 이 둘은 서로 다른 변수다.이것뿐 아니라 한글자라도 소문자 대문자가 다르면 그냥 다른 코드라고 생각하자.

자세한건 회사 컨벤션(코드 규칙)마다 다름(귀동냥으로 터득해야되는 경우도 있음)

언리얼에선 보통 코드가 대문자로 이뤄져있다.

12.변수선언
-> 자료형 변수식별자;
Q 근데 우리가 보는 보통 변수는 자료형 식별자 = 0; 이런식아닌가?
A 엄연히 말해서 대입해주는건 '초기화(=reset)'과정을 해준 것이다.
선언만 하면 알수없는 값이 들어있는거니깐(초기화 습관 들이기)

13.자료형
알아야되는 자료형
정수형 - int short long(차이:자료를 담을 수 있는 크기, 무조건 너무많은수를 담아낼 수 없으니깐 나눠놓은 것)

크기랑 최대숫자가 얼만지는 다음 수업에서

실수형 - float double
flaot 소수점 4번째 자리
double 소수점 8번째 자리

수학적으로의 실수말고 프로그래밍에서의 실수는 소수라고 생각하자.

문장형 - char(케릭터형 차형이라고 하는 사람도 있음)
한글,영어

이외의 자료형은 학습하면서 알기

14.상수는 상수라고 지정해야되나? 상수는 꼭 숫자여야되나?
상수는 논리적으로 변할 수 없는 수여서 보고 생각하면 됨
변수도 상수로 상수화가 될 수 있는데 상수가 꼭 숫자뿐만 아니라 문자일 수 있음.이런 경우가 있다는 것을 일단 알고있기.

15.수식 = 계산식
연산자 = 연산 시켜주는 애

%연산 = 나머지 연산
-> 우리가 나누면 몫과 나머지가 생기는데 프로그램에서의 나누기는 몫만 뱉어준다. 그럼 나머지는? 그래서 나머지 연산을 따로 만들어줬다.
프로그램에선 사칙이 아닌 오칙연산을 사용한다.

몫을 구할때 -> 나누기 연산 x/y(=div)
나머지를 구할때 -> 나머지 연산 x%y(=mod)

대입연산
x=x+1;은
"변수 x의 값을 하나 증가시키고 그 값을 좌측 x에 덮어씌워라"과 같다.
1을 넣으면 2가되고 2를 좌측 x에 대입(한줄에 하나의연산만 하는게 아니라 여러개의 연산을 할 수 있음!)

16.인수(=argument) = 메게변수,인자,파라미터 용어가 굉장히 많음(+argument)

17.printf에 문자열(=문장)을 표현할 때는 큰따옴표를 쓴다.문자를 표현할 때는 그냥 따옴표를 쓰면 됨

18.scanf = 내가 화면에 입력한 값들을 받아와서 코드에 넣어주는 애
뒤에는 보통 '형식지정자'와'&변수식별자'가 들어간다.

19.변수값을 출력할 때
임의의 값을 입력했다는 가정 하에 만약 3과 5를 더하고싶으면 더한 값인 8을 sum이라는 변수에 저장했을 때 sum의 값을 출력하면되는데

우리가 printf를 쓸 때 여기에 8을 넣어줘야지 출력이 된다.
근데 여기서 문제가 되는게 sum이라는게 유저의 입력값에 따라 달라지기에 8을 넣으면 또 안된다.그래서 이 sum이라는 변수를 출력하는 방법을 고안한게 뭐냐
-> 바로 printf를 쓰되 printf("형식 제어 문자열", 관련 변수식별자)로 써주는 것

형식 제어 문자열에는 형식 지정자라는게 들어가는데 자료형마다 %d,%f,%c,%s(더많음)로 나눠져있다. %는 나머지 연산에 쓰이는 것뿐만 아니라 형식지정자의 기능도 있다.-> 문자열에 안에 있는 %는 형식지정자다!

형식지정자 -> 형식을 지정하는애 -> 자료형=자료의형식 -> 자료형을 지정해준다 ->
%d = 정수를 10진수로 출력한다
%f = 소수점이 있는 실수로 출력한다
&C = 문자 형태로 출력한다('')
&s = 문자열 형태로 출력한다("")

20.printf 쓰는법

예시
printf("학번 %d인 학생의 성적 %f이다.\n". number, height);

학번이나 성적같은 다 다를 수 있는 요소들을 한 코드 내에서 표현하고 싶을때 즉, 이 프로그램을 누가 키더라도 이 동작은 똑같았으면 좋겠다했을 때 코드 한 줄로 깔끔하게 쳐야 됨

이 한 줄 안에는 두 가지 요소가 들어가야되는데
첫번째는 정수나 실수 등 자료형의 요소를 지정할 수 있는 코드가 들어가야 됨
그게 바로 형식제어문의 존재 의의
형식제어문 안에는 넣고 싶은 값들의 자료형에 맞는 형식지정자들을 넣어야함.

두번째는 요소들이 고정값이 아니라 다 달라질 수 있기에 여러가지 값을 받을 수 있는 부분을 커버해줄만한 요소가 들어가야 됨
지금 변수값을 출력하는것인데 그럼 변수는 어디에 써주냐?
형식제어문 뒤에 써준다.

이렇게 넣어주면 위의 예시처럼 되는건데 %d의 자리에 number변수의 값들이 들어간다.그리고 %f엔 뒤에 하이트의 값들이 들어감
여기서 알아야할 건 변수의 순서는 형식지정자의 순서와 동일하게

"고정된값만 도출하는게 아닌 입력한 값에 따라 다양한 결과를 도출하는게 프로그램이다"
"계산값뿐만 아니라 여러 상황의 결과를 도출할 수 있어야 됨"

21.scanf 쓰는법
얘도 프린트에프처럼 뒤에 변수가 값을 받아와서 형식 제어 문자열의 형식지정자에 넣어주는 식이긴한데 큰 차이는 '&'(=엔드,엔퍼센트,엔드연산자 등 여러가지)가 있다는 것이다.printf는 변수만 넣었고 scanf는 &변수를 넣은 것

엔드연산자가 뭐냐면 굉장히 중요한 개념임
프린트에프는 썸을 문자열에 넣어 문자열을 화면에 출력하는 방식(컴퓨터가 우리에게)
근데 스캔 에프는 내가 컴퓨터에게 주는 것 바로 내가 의도한 값을 입력하기위해서 엔드연산자는 이럴때 입력한 값을 컴퓨터에게 전달해주는 기능을 한다.자세히 보면 엔드연산자 안에는 주소값이라는 개념이 있는데(이건 다음시간에) 일단은 변수에 꼭 엔드를 붙힌다라고 기억하자!

22.덧셈 프로그램을 짜보자.
전처리기 코드 및 메인함수를 셋팅하자

일단 입력값들을 담을 변수 선언부터 하자(X,Y)
그리고 덧셈이니깐 합친 데이터를 받아줄 변수를 선언하자(sum)
(초기화 꼭 해주기 int x; 이렇게 선언하면 안됨)

메인 안에 뭘 넣어야될 지 생각을 해보면 변수값을 출력하기 위한 요소 두가지인 자료형을 지정해줄 수 있는 '형식제어문자열'과 여러가지 입력값을 넣을 수 있게해주는'변수 식별자들'을 넣어줘야됨

그리고 우리가 이걸 입력하라고 써줘야되고 사용자가 입력을 할 수 있게끔
printf랑 scanf 함수를 써줘야됨
입력값을 유도하기위한 문구를 printf로 출력해주고 scanf 함수로 입력을 받는다. 그리고 변수 결과값이 나오는 결과의 변수식별자(여기선 sum)의 연산식 선언 및 printf 함수가 필요

scanf의 인자는 입력값 그자체니깐 "형식지정자"가 들어가고 그 뒤에 입력한 값을 받아 가져올 곳이 필요하기에 쉼표치고 &변수식별자를 쳐줘야한다.(식별자에 입력값을 받아옴
변수의 값이 형식지정자에 들어가서 그 값이 나오는 것)

즉 입력을 해서 반환을 해서 받아온 값을 컨트롤하는 과정이 아니라 진짜 입력한 값을 &식별자에 때려넣음

printf와 scanf를 넣는데 주의할 점 : 아래처럼 입력값을 한번에 넣어주는게 아니라 입력값수만큼 따로 따로 출력문과 입력문 코드를 쳐줘야된다.

잘못된 예시
printf=("x와y값을 입력하시오.:");
scanf=("%d,%d", x, y)

sum = x+y;
printf("x와y의합:%d", sum);

정상
printf=("x값을 입력하시오.:");
scanf=("d%", &x);

printf=("y값을 입력하시오.:");
scanf=("d%", &y);

sum = x+y;
printf("x와y의합:%d", sum);

그리고 마지막으로 이 값을 외부로 반환해줘야되니깐
return 0;까지

23.코드4996에러 해결법
원인 : 구버전 함수여서 안전하지않으니 신버전 함수를 써라 _CRT_SECURE_NO_WARNINGS를 써라.(=보안에 관한 경고를 받지않겠다는 뜻)
해결 : #define _CRT_SECURE_NO_WARNINGS를 맨 윗줄에 쳐주면된다.

scanf함수가 여러번 쓰면 프로그램 의외의 곳에 문제가 생길 수 있어 해킹을 방지하고자 마이크로소프트사에서 추천을 안하는 것임 회사 들어가면 새로운 코드 써야됨

24.디버깅하면 프린트에프에 중단점을 찍고 F10을 눌러 다음 줄을 실행했는데 화살표가 사라짐 그럼 스켄에프가 실행이 안되는건가 싶지만 스켄에프는 사용자가 값을 입력할 때까지 기다린다.사실상 화살표가 있지만 보이게되면 코드가 실행되는걸로 보이니깐 숨겨놓은거임

profile
Emotional realizer

0개의 댓글