포인터에서 출력하는 부분이 이상합니다..(말로설명하기 힘들군?

yanggak의 이미지

#include <stdio.h>

int main()
{
     float f=4.123;
     int *pa;
     printf("%f\n", f);
     pa = &f;
     printf("%f\n", *pa);
     return 0;
}

출력값 :
4.123000
4.122998

도대체 왜이렇게 나오는지 모르겠어요..
컴파일에 물론 warning메시지는 나오는데..
같은 메모리를 access해서 4바이트 가져오는데..
같은값이 출력되는거 아닌가요?

nthroot의 이미지

#include <stdio.h>

int main()
{
    int i = 1;
    float f = 1;

    printf("%08x\n", i);
    printf("%08x\n", f);

    printf("%f\n", i);
    printf("%d\n", f);

    exit(0);
}

형에 따라 같은 4바이트안에 저장되는 방식이 달라서 그렇구요.

yanggak님이 첨부하신 소스파일에서
printf("%f\n", *pa);

이부분에서 pa 는 int형 포인터 이므로 포인터가 가리키는 곳에 저장된 값은 float으로 저장했지만 printf 함수에 인수로 넘어갈때 *pa에 의해서 int형으로 참조된 상태(값의 해석이 변형)로 돌려주기 때문에 %f로 출력을 한다 해도 이미 잘못 참조된 값이 넘어가게 되구요.

------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.

doldori의 이미지

출력값 : 
4.123000 
4.122998 

저는 이렇게 비슷하게라도 나온 게 더 신기한데요. :shock:
컴파일러가 똑똑하다고 해야 하나...
이런 걸 볼 때마다 느끼는 거지만 printf/scanf는 정말 문제가 많은데
다른 대안도 없으니... C++로 코딩할 때는 절대로 안씁니다.
yanggak의 이미지

음...우선 int형과 float형이 같은값이라도 저장되는 형식이 다르다는것은
알구있는데요...

위와 같이 가리키는것은 에러라고 알고있습니다. 컴파일러가 좋은건지...

제가 궁금한건...printf문으로 인자값이 넘겨질때 같은 메모리를 참조하는
것인데 이를 바이너리로 검사하면 같은 값이잖아요...

그렇다면 printf() 에 같은 바이너리값이 넘겨지는것 같은데..
이를 위와 같이 출력하니...
printf()문제라면 좀더 자세히 알려주실수 없을까요?

If you can dream it,
you can do it

doldori의 이미지

가정: sizeof(int) == sizeof(float) == 4, sizeof(double) == 8

printf 내부에서는 pa가 가리키는 메모리를 참조하는 것이 아닙니다.
*pa가 int형이므로 그 값(4.123을 float로 나타낸 비트열을 int로 해석한
값. 당연히 쓰레기값)이 넘어값니다. printf 내부에서는 이 값이 원래 무슨
형인지 전혀 알지 못합니다. 출력 서식(%f)를 보고 판단할 수밖에 없죠.
%f는 넘어온 값이 double임을 나타냅니다. 따라서 원래 넘어간
값 뒤의 4바이트까지 더해서 8바이트를 double형으로 해석합니다.
역시 쓰레기값이 되겠죠. 비슷한 값이 나와서 신기하다고 한 이유가 이겁니다.
다른 컴파일러를 쓴다면 출력 결과가 어떻게 될지 전혀 예상 못하죠.
그러니까 printf/scanf를 쓸 때는 입출력 서식과 변수의 갯수/형을 맞춰주는
것은 전적으로 프로그래머의 책임이고 컴파일러는 도움을 주지 못합니다.
(똑똑한 컴파일러라면 해줄 수도 있겠지만 그런 운에 맡길 수야 없지요.)
이것은 가변인자 함수의 특성이라 어쩔 수 없네요. 그래서 저는 가변인자 함수를
가능한 한 피합니다.

아참, 그리고 pa = &f 처럼 int*를 float*로 변환하는 결과 역시 이식성이 없습니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.