변수선언의 위치에 따라 scanf()를 통한 입력값이 안들어오는 이상한 현상?

달파란의 이미지

간단한 소켓통신 프로그램을 짜다가 이상한 현상이 있어서 질문을 드립니다.

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define BUFSIZE 32
 
int main()
{
    int sock;
    struct sockaddr_in servAddr;
    char serv[8];     // 처음엔 여기에 선언
    char servIP[16];  // 처음엔 여기에 선언
    unsigned short servPort;
 
    int i;
    int amount;
 
    char msgBuffer[BUFSIZE];
    unsigned int msgLen;
    int bytesRcvd, totalBytesRcvd;
 
    printf("Connetion: ");
    scanf("%s %s %d", serv, servIP, &servPort);
    printf("%s %s %d\n", serv, servIP, servPort);
 
}

% gcc weird_scanf.c -o weird_scanf
% ./weird_scanf
Connetion: UK 127.0.0.1 5000
UK  5000  <= 127.0.0.1 안나옴

위 코드에서는 servIP 에 입력값이 안들어 오는 이상한 현상이 발생합니다.
그런데 아래와 같이 serv[8]와 servIP[16]를 선언한 위치를 바꾸니 servIP 에 값이 잘 들어옵니다...

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define BUFSIZE 32
 
int main()
{
    int sock;
    struct sockaddr_in servAddr;
    unsigned short servPort;
 
    int i;
    int amount;
    char serv[8];     // 위치 바꿈
    char servIP[16];  // 위치 바꿈
 
    char msgBuffer[BUFSIZE];
    unsigned int msgLen;
    int bytesRcvd, totalBytesRcvd;
 
    printf("Connetion: ");
    scanf("%s %s %d", serv, servIP, &servPort);
    printf("%s %s %d\n", serv, servIP, servPort);
 
}

% gcc weird_scanf.c -o weird_scanf
% ./weird_scanf
Connetion: UK 127.0.0.1 5000
UK 127.0.0.1 5000  <= 127.0.0.1 나옴

어떻게 이런 이상한 현상이 발생할까요??

kewlbear의 이미지

servPort가 unsigned short인데 %d를 쓰셨네요.

raxis의 이미지

kewlbear 님 말씀대로 scanf 에 %d 를 사용하는 오류를 범하셨네요.

%d 는 int 타입, 4byte 타입을 읽는 것이라고 봐야 하겠습니다.
servPort 는 2 byte 이기 때문에 scanf 실행과정상에 앞에 있는 변수를 깨먹었네요.
( 원 프로그램 상에서는 servIP 가 깨집니다. gdb 로 확인해 보심이.. )

2가지 방법이 있는데요. 첫번째는 servPort 를 int 타입으로 바꾸거나, 두번째 scanf 시에
short 타입이라고 알려줘야 겠네요. 제가 알고 있는 바로는 아래와 같이 하면 될겁니다.

scanf( "%s %s %hd", serv, servIP, &servPort );

도움이 되었으면 좋겠습니다.

mirr의 이미지

fflush(stin);
는 해보셨나용?
내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.

내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.

singlet의 이미지

fflush(stdin)은 이 문제와 전연 관계가 없을 뿐만 아니라 아예 틀린 문장입니다. fflush()는 입력 스트림인 stdin과 함께 쓸 수 없습니다. man page를 인용하자면:

NAME
       fflush - flush a stream
(...)
DESCRIPTION
       The  function  fflush()  forces a write of all user-space buffered data
       for the given <span>output or update</span> stream via the stream's underlying write
       function.  The open status of the stream is unaffected.

더 상세한 정보는 cinsk님의 한글판 C-FAQ 12.26 항목을 참고하세요.
haewoo의 이미지

scanf와 gets은 사용자가 의도하지 않는 오류와 해킹의 가능성이 존재하기 때문에 다른 방법을 사용하기를 권하고 있습니다.

다음과 같이 변경하시면 원하시는 결과를 얻으실 수 있습니다.

     fgets(buf, sizeof(buf), stdin);
     sscanf(buf, "%s %s %hu", serv, servIP, &servPort);

mirr의 이미지

앗...그렇군요....쪽팔립니다 ^^ 공부할께요 ^^

내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.

내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.

댓글 달기

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