게시글
질문&답변
9.8 팩토리얼 예제 질문
안녕하세요? 질문&답변 도우미 Soobak 입니다. #include long loopfrac(int n); long recruFrac(int n); int main() { int abc = 8; printf("%d\n", loopfrac(abc)); printf("%d\n", recruFrac(abc)); return 0; } long loopfrac(int n) { long i; for (long i = 0; i 0) return n * recruFrac(n - 1); else return; } 첨부해주신 코드를 정리해보면 위와 같은데요.우선, Recursion 을 사용하여 구현 하신 함수long recruFrac(int n) { if (n > 0) return n * recruFrac(n - 1); else return; }에서 return; 은 반환값이 없는 함수에서 사용하는 것입니다.long 자료형의 값을 반환해야 함수이므로, 경고 혹은 정의되지 않은 동작을 초래할 수 있으므로 올바른 값을 반환하도록 해주셔야 합니다.수정해보면, 종료 조건에서 return 1; 을 통해 1 을 반환할 수 있도록 하여야 됩니다. Loop 를 사용하여 구현하신 함수long loopfrac(int n) { long i; for (long i = 0; i 를 살펴보면,우선, long i 변수가 함수 내부에서 한번, for () 문 내부에서 또 다시 한 번, 중복 선언이 되어있습니다.그리고, for() 문의 조건을 살펴보면 i 가 0 에서 시작하여 i 조건 동안 계속해서 i-- 을 호출하여 1 씩 감소합니다.또한, i 가 처음에 0 이므로 i *= n 은 0 이 되어, 누적 곱셈이 이루어지지 않습니다.팩토리얼 계산에서는 누적 곱셈이 필요하므로,long loopfrac(int n) { long result = 1; for (long i = 1; i 와 같이 수정해보시면 좋을 것 같습니다.
- 1
- 1
- 22
질문&답변
unsigned as signed-데이터 type의 변환?
안녕하세요? 질문&답변 도우미 Soobak 입니다. scanf() 함수의 형식 지정자에 의해 변수의 자료형이 변환된 것은 아닙니다.scanf() 함수는 입력값을 변수에 저장할 때 비트 단위 그대로 저장 합니다.이 때, unsigned int 와 signed int 는 동일한 메모리 크기를 가집니다.따라서, 변수의 자료형은 unsinged int 그대로이지만 scanf() 함수에서 signed int 처럼 해석하여 저장하고, printf() 함수가 signed int 처럼 해석하여 출력하기 때문에 -123 이 그대로 입/출력 되는 것입니다.즉, 변수의 자료형이 변환되는 것은 아니며 형식 지정자에 따른 해석 방식으로 인한 것입니다.
- 1
- 2
- 10
질문&답변
portable type?
안녕하세요? 질문&답변 도우미 Soobak 입니다. Portable type 은 다양한 플랫폼 환경에서 동일하게 동작하도록 '호환성을 보장' 하는 자료형을 의미합니다.C언어에서 기본 자료형은 플랫폼 환경에 따라서 크기가 달라질 수 있는데요, Portable type 은 이러한 차이를 해결하고 '이식성(Portablility)' 을 확보하기 위해 도입된 자료형입니다.예를 들어서, int 자료형의 경우 일반적으로 크기가 4 바이트이지만, 특정 플랫폼 환경에서는 2 바이트 일 수도 있습니다. 이렇게 플랫폼에 따라 달라질 수 있는 데이터 크기에 대하여 프로그래머가 신경쓰지 않도록 도입된 자료형이 Portable type 입니다.해당 강의 중 intmax_t 는 해당 플랫폼에서 표현할 수 있는 가장 큰 크기의 정수형 타입을 나타내며, 어떤 플랫폼에서도 동일한 의미를 가지므로 이식성이 보장됩니다. (플랫폼에 따라서 intmax_t 는 long long 으로 정의될 수도, long 으로 정의될 수도 있지만, 프로그래머가 이를 신경 쓰지 않아도 됩니다.)그리고, printf() 나 scanf() 함수에서 이러한 자료형을 처리하기 위한 것이 j Modifier 입니다.보다 자세한 내용을 복습해보고 싶으시면, 강의 3.9 고정 너비 정수 의 초반 부분 교수님 설명을 참고하시면 이해에 도움이 되실 것 같습니다.
- 1
- 1
- 13
질문&답변
6.16 %zu 와 %zd
안녕하세요? 질문&답변 도우미 Soobak 입니다. sizeof 연산자의 결과는 size_t , 즉, 부호없는 정수형입니다.따라서, 정확하게는 %zu 형식 지정자를 사용하는 것이 일반적입니다. (강의 4.2 sizeof 연산자, 4.8 변환 지정자의 수식어들 참고)하지만 %zd 를 사용하는 경우에도 size_t 를 같은 크기의 부호 있는 정수형으로 변환하여 결국 같은 값을 출력하게 됩니다.저 또한 %zd 사용에 대한 이유가 궁금하여 찾아본 결과, ssize_t 와 같은 부호 있는 타입을 사용하는 경우에 대한 일관성 유지를 위해서, 혹은 디버깅과 편의를 위해 사용하기도 한다고 합니다. 참고 자료 링크https://stackoverflow.com/questions/65650987/usage-of-zd-vs-lu-for-sizeof
- 1
- 1
- 25
질문&답변
const 상수와 define 상수
안녕하세요? 질문&답변 도우미 Soobak 입니다. Visual Studio 뿐만 아니라, 컴파일러에서 C언어 표준이 c90 또는 c99 으로 설정되어있는 경우 모두 발생할 수 있는 문제입니다.즉, 코드를 컴파일 할 때 컴파일러에 설정된 '지켜야하는 표준' 에 따라서 발생하는 문제입니다.따라서, gcc, clang 등 다른 컴파일러에서도 C언어 표준을 c99 이하로 설정한다면 해당 문제가 발생합니다.보통, C언어에서는 상수를 #define 을 통해서 정의하여 사용합니다.이미 잘 학습하신 것으로 생각되지만, 강의 4.8 명백한 상수들 에서 해당 내용을 다루오니 참고해보시면 도움이 되실 것 같습니다.
- 1
- 2
- 24
질문&답변
float, double, long double의 형식 지정자는 모두 %f?
안녕하세요? 질문&답변 도우미 Soobak 입니다. 네, printf() 함수에서 float 자료형은 항상 double 로 변환되어 처리되고, 형식지정자 %f 를 사용하여 출력합니다.형식 지정자 %lf 에 대한 설명도 옳습니다.다만, long double 에 대한 형식지정자의 경우에는 이어지는 강의 4.8 변환 지정자의 수식어들 에서 학습하시게 되는데요, 형식지정자 %Lf 를 사용하여 출력합니다.강의 4.8 변환 지정자의 수식어들 의 8:30 부분의 표를 살펴보시면 이해에 도움이 되실 것 같습니다.
- 1
- 2
- 13
질문&답변
그래서 manifes constants란?
안녕하세요? 질문&답변 도우미 Soobak 입니다. 코드에서 상수 값을 명확하고 의미 있는 이름으로 정의하여 가독성을 높이는 것을 의미합니다.강의에서의 예시처럼 #define PI 3.141592 과 같이 정의하여,int area = PI * rad * rad; 와 같이 사용하는 경우처럼 상수 값에 의미 있는 이름을 부여하여 목적을 명확히 강조하는 것입니다.int area = 3.141592 * rad * rad; 와 같이 상수를 바로 사용할 수도 있지만,2147483647 대신 INT_MAX 라고 이름을 붙여서 사용하는 것이 의미를 더 명확히 하고 유지보수를 쉽게 할 수 있도록 해줍니다.참고로, 상수를 이름 없이 사용하는 경우에 대해서 매직 넘버 라고 표현하기도 하며, 매직 넘버를 많이 사용하는 것은 코드의 가독성을 떨어뜨리는 측면에서 지양해야 하는 코드 스타일 중 하나입니다.
- 1
- 2
- 18
질문&답변
헤더 가드 이름에 관해서요
안녕하세요? 질문&답변 도우미 Soobak 입니다.좋은 질문이시네요.어떤 것으로 하여도 상관은 없지만, 상황에 따라서 기준을 정하여 사용합니다.주로 팀의 관례에 맞추어 사용하기 때문에, 어떤 기준을 사용하더라도 팀에 잘 맞추어 갈 수 있도록 헤더 가드의 의미와 목적에 초점을 맞추어 학습하며 이해하는 것이 좋다고 생각합니다. 보통 파일 이름을 기반으로 example.h 의 경우 #ifndef EXAMPLE_H 와 같이 사용하는 경우가 많으며, 경로를 포함하여 src/utils/example.h 의 경우 #ifndef SRC_UTILS_EXAMPLE_H 등과 같이 사용하기도 합니다.여러 프로젝트를 동시에 다룰 때에는 프로젝트 명까지 포함하여 사용하기도 합니다.헤더 가드의 목적은 충돌을 방지하기 위함이므로, '고유성' 을 지키는 것이 가장 핵심적인 부분임을 고려하시면 추후 어떤 이름을 사용하셔도 헤더 가드의 목적에 맞게 잘 사용하실 수 있으시리라 생각됩니다. 추가적으로, 팀에서 사용하는 관례에 맞게 자동으로 코드 스타일과 헤더 가드 등을 정리해주는 포매터를 사용하기도 하며 #prgma once 를 사용하여 간단하고 효율적으로 헤더 파일을 관리하기도 합니다.
- 1
- 2
- 21
질문&답변
10.18 강의에서 복합 리터럴의 주소
안녕하세요? 질문&답변 도우미 Soobak 입니다. 복합 리터럴은 표현식이 평가될 때 이름이 없는 객체(익명 객체)를 메모리에 생성합니다.그리고 생성된 익명 객체의 메모리 주소를 반환합니다.이 때, 복합 리터럴 자체가 메모리 주소를 가지므로, 이를 포인터에 대입할 수 있는 것입니다.오히려, 복합 리터럴은 이름이 없으므로 직접 접근할 수 없어 포인터를 통해서 접근하는 것이 일반적입니다. 에시로 들어주신 ptr = 1024; 에서 ptr 의 자료형이 int* 이라고 하였을 때, 문제가 발생하는 이유는 조금 다릅니다.int* ptr; 에서 ptr 은 'int 자료형을 가리키는 메모리의 주소' 를 값으로 가져야 합니다.하지만, 1024 라는 상수 리터럴은 메모리 주소가 아닙니다.즉, 1024 는 '메모리 주소를 의미하지 않는 단순한 정수 값' 이지만, 포인터는 '메모리 주소' 를 저장해야 하므로 문제가 발생할 수 있는 것입니다. 어려우시거나 궁금하신 부분이 있으시면 편히 댓글 달아주세요.
- 1
- 2
- 21
질문&답변
배열의 data type
안녕하세요? 질문&답변 도우미 Soobak 입니다.좋은 질문이시네요.네, 자료형은 char 로 유지하여야 합니다.이는 C언어에서 문자열은 '문자(char)의 배열' 로 표현되기 때문입니다.강의에서 char fruit_name[40]; 은 문자 40개를 저장할 수 있는 배열을 선언하는 것입니다.배열을 선언할 때 사용하는 자료형은 배열이 저장할 개별 원소들의 자료형이므로, 문자열을 문자의 배열로 처리하기 위하여 자료형은 여전히 char 이어야 합니다.다만, C언어에서 이러한 문자열(문자들의 배열)을 처리할 때에 널 문자('\0') 라는 문자를 문자열의 종료 문자로 사용한다는 독특한 점이 있습니다.널 문자, 그리고 C언어에서 문자열을 처리하는 방식에 대해서는 해당 섹션에서 이어지는 강의들, 특히 4.3 문자열이 메모리에 저장되는 구조, 에서 보다 자세하게 학습하시게 됩니다.형식 지정자를 %c 에서 %s 를 바꾼 이유는 %c 는 '하나의 문자' 에 대한 형식 지정자이고, %s 는 '널 문자가 포함된 문자 배열' 을 처리할 때 사용되는 형식 지정자이기 때문입니다.
- 1
- 1
- 25