다시 오신 걸 환영해요
이번 강의에서는 C#에서 프로그래밍할 때 흔히 발생할 수 있는 실수에
관해 얘기해 볼게요
이 중 일부는 이전 과제에서 보셨을 겁니다
이미 이런 오류에 부딪힌 적이 있죠 하지만 이런
게 가장 흔한 실수 형식이에요
첫 번째는 너무 뻔해요 세미콜론이 빠졌네요
c의 모든 구문은 세미콜론으로 끝나요
그게 없으면 컴파일러가 불평할 거예요
세미콜론을 잘못 넣거나 아예 빼놓는 건 아주
흔한 오류예요 이 경우엔 세미콜론이 빠졌네요
If 문서가 있어요 if문 끝에 세미콜론을 넣었어요
이 때문에 프로그램의 행동이 완전히 달라지죠
컴파일 될 거예요
세미콜론을 빼먹거나 포함하지 않으면 컴파일하지 않아요
하지만 이 경우 j의 값은 항상 0으로 설정됩니다 if문
위에 세미콜론이 놓여있기 때문이죠
그래서 if문 후에도 세미콜론은 완벽하게 유효해요
null문을 나타내죠
따라서 컴파일러에 의한 오류가 없는 거죠 하지만
이건 문제를 일으킬 겁니다 j는 절대로 0으로 설정되지 않으니까요
이런 유형의 실수는 루핑에서도 흔하죠
루프가 있을 때 for 루프 끝에 세미콜론을
붙이는 거죠 대괄호가 없을 때도 있는데 대괄호가 있으면
오류가 날 수 있거든요 대괄호가 있으면요 아주 흔하죠
또 다른 것은 등호연산자와 등호연산자를 혼동하는 것인데요
등호 연산자가 문자열을 비교하는 게 아니라고
구체적으로 언급했죠 그래서 문자열을 비교할 때
등호를 쓰면 유효하지 않죠 레퍼런스를 비교할 거예요
하지만 실제로 변수에 값을 할당하고 =을 사용하는 대신에
컴파일러를 할당한다면 컴파일러가 되는 거죠
이제 두 항목을 비교해 보세요 if문 안에 있는
두 개의 정수처럼요 그리고 할당 연산자를 사용하는
대신에 컴파일러 오류는 없을 거예요 하지만
식은 항상 true로 평가하겠죠
= 기호를 사용할 때 혹은 사용하지 않을 때
이것은 if 문에서 만들어집니다 부울식 안에서요
뭔가를 실행하는 대신 할당하는
효과만 빼면 유효해요
이 예제에선
a가 2라면 a에 2를 할당하는 거예요
항상 true로 설정합니다. 왜냐하면 true니까요. 왜냐하면 배정을
할 때 절대 실패하지 않으니까요. printf는 항상 실행되죠
여기서 정말 해야 할 건 a===을 하는 거죠
컴파일러 오류를 만들지 않기 위해 = 기호를 사용하는
건 아주 흔한 일이에요
등호를 잘못된 상황에서 사용한다면
예상치 못한 행동도 나올
수 있습니다 하지만 배정에 잘못 사용한다면
컴파일러 에러가 발생할 수 있어요
하지만 조심하세요 등호가 아닌 등호니까요
프로토타입 선언을 생략하고 있어요
말씀드린 것처럼 사용하기 전에 항상 파일 상단에
기능을 지정하는 게 정말 중요해요
하지만 늘 이런 건 아니고 자주 있는 실수예요
일반적으로 발생하는 일은 컴파일러에 암묵적인 선언 오류가
생기는 것이죠
이 예제에서, 프로그램 후반부에 제곱근을 호출할
때 혹은 다른 파일에서 명시적으로 선언하지 않았을
때 정의가 되어 있다면 경고를
받게 될 거예요
컴파일러는 그 함수가 int를 반환한다고 가정하죠
프로토타입 선언은 모든 함수를 위한 맨 위에 두는 것이
가장 안전합니다 프로그램에서
올바른 헤더 파일을 명시적으로
혹은 암묵적으로 포함함으로써요
하지만 그걸 포함시키지 않으면 프로토타입 선언은 오류가
날 수 있어요
프로그램에 사용되는 C 프로그래밍 라이브러리 기능에 대한 정의가
포함된 헤더 파일을 포함하지 않는 경우에요
이 경우엔 코드를 재사용해야죠 printf 함수가 있을 수도 있고
출력을 보여주고 싶을 수도 있죠 하지만 표준 lib 헤더 파일은 포함하지 않아요
실수하는 거예요 컴파일러가 설명해 줄 거예요
그 기능에 문제가 생길
거예요
이 경우엔 이중 답이 제곱 루트 값 1이죠
이 프로그램에 수학이 포함 안 됐다면요 헤더 파일, 이건 제곱근이
정의되지 않은 에러를 발생시키죠
개체 파일을 링크하려고 할 거예요 계산이 안 돼요 네
제곱근을 호출했는데 구현이 안 됐다고 할 거예요
모든 함수가 호출될 때 올바른 헤더를 포함하도록
하세요 특히 표준 라이브러리에서요
문자열에서 문자 상수를 혼란시키죠
여기 텍스트가 작은따옴표 안에 = 하면
텍스트에 할당된 단일 문자죠
텍스트라는 변수가 있고 큰 따옴표를 할당할 경우
그건 문자열에 대한 포인터예요
그건 단 하나의 캐릭터에도 유효하지
않아요
여기서 문자열 상수를 문자
배열에 할당하는 것도 다뤘죠
등호로는 그렇게 할 수 없고 별 카피로
해야 한다는 것도요
이 경우 텍스트 = a라고 하면 포인터를 할당하는
겁니다 이것도 유효하지 않죠
여러분이 하실 일은 *텍스트 = a 혹은
*복사를 하는 겁니다 직접적으로 그렇게 할당하고 싶지 않다면요
요점은 아시겠죠?
작은 따옴표 안에 있는 것과 큰 따옴표 안에 있는 것은
완전히 다릅니다 문자열과 문자열이죠
첫 번째 경우, 텍스트는 보통 char 변수로 선언되죠
두 번째 경우에는 char에 대한 type-pinter로 선언되어야 해요.
포인터 이외에 그 포인터에 값을 할당하고
싶다면 참조를 해제해야 해요
사실 이건 틀려요 이게 포인터라면
주소를 할당하는 대신 문자열을 할당하는 거니까요
말이 안 되죠
잘못된 경계를 이용해 정렬했어요 경계를 벗어난 정렬은 예외죠
여기 100 크기의 정수 배열을 선언하고
몇 가지 변수 I와 합을 초기화했어요
루프를 통해 I = 1 I = 100보다 작다고 하죠
틀렸습니다 100의 크기는 배열 안에 100개의 요소가
있다는 뜻이니까요 하지만 배열은 0이에요
첫 번째 요소는 0이에요 A 배열에서 할당하거나
액세스할 수 있는 최대 인덱스는 99예요
등호보다 작을 거예요
여기서 범위 밖의 실수가 발생할 거예요
이건 유효한 서브스크립트가
아니에요 이 루프는 100까지 가거든요
1시에 시작하니까 아마 틀릴 거예요
이 배열의 첫 번째 요소를 원한다면 0부터 시작하세요
문자열 Null 캐릭터를 종료할 때 배열의
여분의 위치를 예약하는 걸 잊는
것도 흔한 문제죠
캐릭터 배열을 선언할 때 캐릭터 배열이 커야 해요 혼자 종료하는 캐릭터를 담을 수 있을 만큼요
그래서 제가 제안하는 건 생성할
때 크기를 배열에 넣지 말라는 거죠 초기화할 때요
초기화하지 않을 때만 크기를 입력하죠
같은 줄에서 초기화를 할 경우 c가 대신 작업하도록 합니다 자동으로
올바른 크기를 입력하고 null 터미네이터를 포함할 거예요
예를 들어 hello라는 문자열을 가지고 있다면 메모리 위치가
5개가 넘습니다 마지막에 Null 터미네이터가 있기 때문에 6개가 되는 것이죠
배열의 크기를 잊지 마세요
이건 포인터와 관련된 흔한 문제인데요 많이 다루진 않았지만
아주 흔한 거라서 언급하고 싶었어요
포인터에선 액세스하거나 지시할 때 포인터로
뭔가에 액세스하고 싶을
때 대시를 기호보다 크게 사용해야 해요
포인터 요소에 엑세스할 때 사용되죠
구조를 가리키는 포인터가 있다면 그게 접근 방법이죠
구조가 있다면 그건 포인터가
아니죠 그럼 .연산자를 이용해 액세스하세요
많은 경우 이 .연산자와 이 대시가 잘못 사용될
수 있어요
.n-pinters는 not-pinters보다 커요 이건
앞으로 예제에서 더 분명해질 거예요
스캔 전화에서 비포인터 변수를 생략하는 거요
scanf call은 두 번째 인수로 포인터를 기대합니다.
주소를 의미하고요.
우리가 데이터 타입, type int라는 변수를 선언할 때 그건 포인터가
아니에요
scanf가 int 변수에 데이터를 저장할 수 있게 하려면 ampersand를
입력해서 주소를 입력해야 해요
따라서 오류입니다
& & 전 번호가 없고 두 번째 인수가 F로 스캔되면
유효하지 않죠 &가 없는 유일한 경우는 캐릭터 배열 같은 포인터를
사용할 때죠
형식 문자열과 Scanf 다음에 나오는 모든 인수는 포인터여야만 하죠
초기화되기 전에 포인터 변수를 사용해서요
포인터를 생성하고 할당하는 예제가 여기 있네요
이건 올바른 할당이에요 값을 할당해 참조 해제하는 거죠
아직 안 한 건 포인터를 초기화해 메모리를 할당하도록
하는 겁니다 이건 C#에선
할 수 없어요
인다이렉션 연산자만 적용할
수 있어요 어떤 점 전에 별표나
변수를 어딘가에 지정하고 난 후에요
어딘가를 가리키고 있어야 하는데 지금은 null이에요 아무데도 가리키고 있지 않죠 메모리를
할당하지 않았으니까요
char 포인터는 어떤 것도 가리키지 않도록 설정되어 있어서 할당은 의미가 없어요.
세분화 결함을 일으킬 수 있어요
또 다른 흔한 오류는 switch 문에서 사례 말미에 브레이크 문을 생략하는 거죠
사건 종결에 브레이크가 포함되지 않으면 다음 사건까지 사형을 집행하죠
사례가 있는 곳에선 이게 평가돼요
브레이크가 없으면 바로 다음 케이스로
가서 그 안의 코드를 실행하죠
사건 진술서에는 항상 브레이크가 있어야 해요
다음 케이스에서 다음 케이스로 넘어가고 싶을 때 완전히
같은 일을 할 수도 있습니다. 이 경우에는 case문
안에 아무것도 없을 거에요.
사전 처리기의 정의 끝에 세미콜론을 삽입해요
Prerocessor 정의는 우물 정자로
시작하는 걸 기억하세요 전처리 장치는 컴파일러가 최적화를
하기 전에 실행되죠
프리프로세서 정의의 올바른 구문은 세미콜론이 포함되지 않아요
하지만 cu에선 항상 모든 것 뒤에 세미콜론을 넣는 습관을 들여요
하지만 상수 데이터를 정의할 때 세미콜론이
필요 없다면 이건 틀린 거예요
이런 식을 사용하면 구문
오류가 발생하죠
이렇게요 그래서 그걸 실제로 사용하려고
하면 끝에 세미콜론을 둬도 괜찮아요
하지만 프리프로세서가 실행되면 정의된 것을 정확히 삽입하죠
데이터 999 콜론에서 마지막을 담당할 거예요
컴파일러가 이것을 보고 오류를 발생시킬 것입니다
구문 오류죠
어떤 문장에든 괄호 닫기나 인용구 닫기 표시를 생략하는
건 아주 흔해요 이것도 괄호와 직접적으로
관련 있죠 중괄호로 시작했다가 끝내지 않는 거요 괄호도
마찬가지죠 이 경우 왼쪽 괄호로
시작하는 괄호가 2개 또는 3개인데 끝 괄호는
2개뿐이에요 오른쪽 괄호가 빠졌네요
컴파일러가 찾을 수 있는 구문 오류가 되겠죠
그래서 괄호를 사용해 방정식의 각 부분을 구분할 때 코드 줄을
좀 더 가독성 있게 만들죠
괄호를 사용하세요
하지만 모두 일치하게 하려면 괄호를
시작할 때 괄호를 닫을 때도 있어야 해요 중괄호도 마찬가지죠
중괄호를 시작하면 끝에도 중괄호가 있어야 해요
컴파일러가 너무 많거나 너무 적거나 둘 중 하나죠
컴파일러는 불만을 제기할 겁니다 아주 흔한 일이니까요
여기 두 번째 줄에도 종료 인용구가 없죠 이 print 문이요
엔딩 인용구가 없어요
컴파일러가 불평할 거예요
둘 다 컴파일 에러를 일으킬 거예요
컴파일러가 오류를 일으키기도 해요 어디서 오류가
발생하는지 모르거든요 일련의 줄에서 오류가 발생했다고 생각하죠
오류를 알려주는 라인은 오해의 소지가 있을 수 있어요
컴파일러가 그 다음 줄에 괄호를
쓰는지 아니면 따옴표를 쓰는지에 따라
식을 완성할 거예요
오류를 다른 줄로 옮길 거예요
거기서 에러가 발생했다고 불평할 거예요 하지만 실제 오류는
의도했던 곳보다 더 위에 있죠
많은 C 프로그래머들이 이런 실수를
해요
고치기 쉬워요 그걸 이해하고 이걸 연구한다면
만들면 안 된다는
걸 알 거예요 초보자한테 만드는 건 괜찮아요
하지만 코딩을 점점 더 연습할수록 괄호를 빼먹었거나
괄호를 빼먹었거나 괄호를 제대로 안 썼거나 괄호를
제대로 안 썼다는 걸 알게 되죠 포인터를 잘못 사용했어요 메모리를
할당하지 않았죠
이 모든 게 제2의 천성이 될 거예요 고마워요