기초적인 c문제...

cjy1126의 이미지

#include <stdio.h>

int fn(char []);

int main()
{
     char str[] = "345";

     printf("main = %d\n", sizeof(str));
     fn(str);

     return 0;
}

int fn(char str[])
{
     printf("%s\n", str);
     printf("fn = %d\n", sizeof(str));

      return 0;
}

결과값입니다.

main = 4
345
fn = 2

이렇게 되는 이유가 char str[]이 넘어올때 포인터로 넘어와서 인가요?

2군데서 &str로 주소를 찍으니까 main은 65520, fn은 65518이 나오네요.

그럼 원래값이랑 넘겨진값이 다른것 같은데...

함수의 인자가 넘어가면서 char는 int로 바뀌는거랑 관련이 있는건가요?

아니면, str[]를 배열 전체가 아닌 첫주소만 넘겨서인가요?(저는 이것같은데... 메모리가 어떤식으로 되는지 모르겠네요. stack이라서 나중에 생긴 배열을 가르키는 포인터의 값이 더 작은건가요?)

이것 저것 너무 어설프게 알아서 힘드네요.

함수의 인자가 char에서 int로 바뀐다는거랑 제 코딩의 str이 어떤식으로 변한건지 답변 부탁드립니다 :oops:

sunyzero의 이미지

메인에선 당연히 해당 array의 크기인 4가 잡힙니다.(맨끝 널종료 포함)

그리고 함수로 넘겨줄때는 array의 시작주소가 넘어가니까 2가 맞습니다.(그런데 도스에서 프로그래밍 하시나 봅니다. 16bit 주소체계인것을 보니...)

근데 함수 인자가 char -> int로 바뀐다는게 무슨 말씀이신지?
서브함수는 원래 포인터를 받는 것으로 선언된것 맞습니다.

========================================
* The truth will set you free.

cjy1126의 이미지

처음에 dos에서 c를 배워서 tc가 너무 편해서요.

vi를 잘못쓰는 이유도 있지만요 ^^;

형변환이 된다는 말이 2군데서 나오는데, 같은 의미인지는 모르겠습니다.

the c programming language 2nd 42쪽에 나오는 말인데요.

함수호출에 의해 매개변수가 함수로 전달될 때에도 형변환이 일어난다. 함수선언부분(function prototype)이 없으면 char, short, int, float는 duoble로 된다. 이것이 바로 함수가 char이나 float로 호출될 때에도 함수 매개변수들을 int와 double로 지금까지 선언해온 이유이다. (앞 예제 다 뒤져도 이런 예제가 없네요 -_-);

그리고 전에 이곳하고 백두대간 c에서 봤을때 char 인자가 넘어갈떄 int로 변환되서 넘어가서 다시 char이 된다는식으로 들었거든요. 아닌가요? :oops:

xjiwoox의 이미지

main()에선 변수 str이 배열로 선언되어 있으므로 sizeof() 연산의 결과 4가 나옵니다.("345\0")

fn()에선 str이 포인터로 선언되어 있으므로(함수 인자 선언시 배열형태로 선언하더라도 포인터형으로 간주) sizeof() 연산의 결과는 해당 시스템의 포인터 크기에 의해 결정됩니다. cjy1126님의 경우 2가 나온걸 보면 도스환경인 것 같네요.(near pointer)

형변환은 main() 함수에서 fn(str)을 호출할 때 발생되는군요.
(char *)str -> (int)str
도스환경에선 int나 pointer나 둘 다 2byte이고 정수값이므로 에러 없이 컴파일은 되겠지만 가능하면 명시적으로 형변환을 해주시거나 main() 시작 전에 fn() 함수의 proto type을 선언해 주시는 것이 좋습니다. 그렇지 않으면 컴파일러는 선언되지 않은 함수의 모든 인자가 int형이라고 간주하고 형변환을 하게 되거든요.
fn() 함수의 관점에서 보자면 호출되는 시점에서 넘어오는 값은 int형으로 넘어오겠지만 이 역시 int -> pointer로의 형변환이 같은 2byte에 정수값이므로 에러 없이 컴파일 됩니다. 그리고 원래의 데이터값이 char *(pointer)가 맞으므로 수행결과도 정상적으로 나타나구요.

s(˘∼˘*)z,·´″"`°³о$ √(´∀`√)... (˘ヘ˘ㆀ)a

sunyzero의 이미지

그래서 항상 함수의 원형을 선언해주는 것이 좋다고 하는 이유가 있는 것입니다.

gcc에선 원형없이 컴파일하면 implicit declaration of function 이라고 워닝을 쭉쭉 뱉어내죠... 항상 원형을 써주는 버릇을 들이는게 좋습니다.

========================================
* The truth will set you free.

김충길의 이미지

sizeof 는 컴파일 타임에 결정되는 연산자입니다.

메인경우 4바이브 배열이라 4.
fn 경우엔 포인터라 2.

screen + vim + ctags 좋아요~

cjy1126의 이미지

이해가 안되는 부분들...

1. 원형을 선언하라고 하시는게 int change(char str[3]);

이렇게 선언하라는건가요?

이렇게 선언해도 결과는 같게 나오거든요.

지금 제가 넘긴게 str[] 니까 포인터를 넘긴거라고 써주셨는데...

함수 인자 선언시 배열형태로 선언하더라도 포인터형으로 간주

2. 포인터라고 명시했는데, int로 넘어오나요?

fn() 함수의 관점에서 보자면 호출되는 시점에서 넘어오는 값은 int형으로 넘어오겠지만

3. 주소로 안받고 main()에서와 같은 배열 자체로 받는 방법은 없나요?

Prentice의 이미지

안녕하세요, 검은해라고 합니다.

질문자님께서 모르고 계신 것처럼 보여서 글을 씁니다. 이미 알고 계시다면 죄송합니다.

char foo[]; 처럼 배열을 선언하셨을때 foo는 foo[0]의 주소를 말합니다. 즉 foo는 foo[] 배열의 첫 요소를 가리키는 포인터가 됩니다. 보통 포인터와 다른 점이 있다면 포인터 변수가 아니라 정말 순수한 주소값으로서의 포인터라는 점입니다.

올려주신 소스는 아래와 같이 수정해도 동일한 소스일 것입니다. str과 input의 차이에 대해 생각해보세요.

#include <stdio.h>

int fn(char []);

int main()
{
     char str[] = "345";

     printf("main = %d\n", sizeof(str));
     fn(str);

     return 0;
}

int fn(char input[])
{
     printf("%s\n", input);
     printf("fn = %d\n", sizeof(input));

      return 0;
}
datamind의 이미지

1. int change(char str[3]) 해도 결과는 동일...
-> char str[] 와 char str[3] 는 C 에서는 동일한 것임.

2. 포인터라고 명시했는데, int로 넘어오나요?
-> 포인터가 인티저의 메모리 크기를 갖는다는 말이겠죠..

3. 주소로 안받고 main()에서와 같은 배열 자체로 받는 방법은 없나요?
-> 주로로 받는게 가장 좋은 방법이죠,,
그게 싫다면, 구조체를 사용하세요..
그런데 별로 권장하고 싶지 않네요..

#include <stdio.h> 

struct  array_st {
   char a[3];
};

int fn(struct array_st c); 

int main() 
{ 
     struct array_st b;
     
     strcpy( b.a, "a" );
     printf("main = %d\n", sizeof(b)); 

     fn(b); 

     return 0; 
} 

int fn(struct array_st c) 
{ 
     printf("%s\n", c.a); 
     printf("fn = %d\n", sizeof(c)); 

     return 0; 
}

댓글 달기

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