c언어 실수와 정수에 관련해서 런타임 오류 도와주세요...ㅠ

kimsunboy의 이미지

#include <stdio.h>
 
int main()
{
   double a;
   int b;
 
   a=4.123;
   printf("a의 실수값:%lf\n",a);
   printf("a의 정수값:%d\n",(int)a);
   b=4;
   printf("b의 실수값:%lf\n",b);
   printf("b의 정수값:%d\n",b);
 
   printf("실수값으로 출력해보기:%lf\n",(5/9)*(a+b));
   printf("정수값으로 출력해보기:%lf\n",(a+b));    
 
   return 0;
 
}
<code/>
에 대해 정수과 실수에 관련해 공부를 해 보려고 이것저것 하다 컴파일을 했는데...
 
a의 실수값:4.123000
a의 정수값:4
b의 실수값:4.123000
b의 정수값:4
실수값으로 출력해보기:0.000000
정수값으로 출력해보기:8.123000
 
이렇게 출력이 됩니다. 변수b에 4라는 값을 넣었는데 실수값으로 출력하는 과정에서 제가 생각하기에 4.0이 나와야 할 것이 왜 4.123이 나온건지에 대해 도와주세요ㅠㅠ

익명 사용자의 이미지

아래 블로그에 설명이 잘 되어 있습니다.
https://dokkiblog.tistory.com/80
https://moolgogiheart.tistory.com/58

kimsunboy의 이미지

앗 감사합니다

Stephen Kyoungwon Kim@Google의 이미지

b를 (double) b로 타입 캐스팅 해서 printf를 부르면 4.0000 어쩌고가 출력됩니다. 그렇지 않으면 4.123이 출력되요.

제 생각엔 printf가 variadic function이기 때문에 생기는 일 같습니다. 이걸 질문자 분이 이해하시기 쉽지 않을 것 같은데.. 익명 사용자님은 이미 이해하셨겠고요.

C에는 variadic function이라는 게 있습니다. 임의의 타입의 객체를 임의의 갯수대로 넘겨주는데, 넘겨 받은 쪽에서 뭐가 넘어오는지 알아야 합니다. printf는 varidic function의 일례입니다.

printf는 뭐가 넘어오는지 알기 위해서 format string을 이용합니다. 이 경우에는 %lf가 있으니 double이 넘어 오겠거니 생각하죠. 그런데 실제 넘긴 건 int인 b 입니다.

"%lf"는 언어 차원의 뭔가가 아니라 그냥 printf 하고 약속한 거라서 컴파일러는 printf가 double을 기대하고 있음을 알지 못합니다. 그냥, 아무 거나 몇 개고 넘겨도 되는데 지금 int가 넘어간다고만 생각하죠.

int는 대충 4바이트를 차지합니다. double은 8 바이트를 차지하죠. 그리고 int가 4바이트에 0과 1을 놓는 방식은 double과 상이합니다.

따라서 컴파일러는 caller가 int 타입의 상수 4를 의도하는 4 바이트를 셋팅해서 printf에 넘겨주도록 코드를 생성한 거고, printf는 %lf를 보고 b가 넘어온 자리의 크기가 4가 아니라 8 바이트라고 생각하면서, 거기에서 8 바이트를 가져다가 double처럼 해석을 하게 됩니다.

그래서 차이가 생기는 거 같습니다.

첨언하자면 int를 기대할 때 int를 정확하게 처리하도록 되어 있겠지만, double 대신 int가 넘어올 때 어떻게 처리할지는 정의가 안 되어 있을 수도 있습니다. 그래서 나이브하게 printf를 구현한다면 int의 4 바이트 + 다음 쓰레기값 4바이트를 묶어 double로 해석한 결과를 출력할 텐데 반드시 그렇다고 볼 수는 없겠고요.

그리고 좀더 자세히 말하자면, caller쪽 코드는 variadic argument를 stack에 쌓고 시작 주소만 넘겨주거나 할 겁니다. callee 쪽에서는 그 시작 주소를 받아서, 적절하게 하나 하나 떼어 내어 받아가야 합니다. 흔히 하는 방법은 첫 인자로 string 같은 거 넘겨주고, 거기에 뭐뭐가 들어 있는지 정보를 적으면, callee는 첫 인자는 string으로 해석해서 먼저 넘어오는 인자들의 타입과 순서를 확인한 뒤, 거기에 맞춰 하나씩 떼어 쓰는 거겠죠.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.