main 내에서의 sizeof(arr), 함수 내에서의 sizeof(arr)

mrx@Google의 이미지

int sum_array(int arr[],int n)
{
printf("%d\n",sizeof(arr));
}

void main(){
int arr[2];
printf("%d\n",sizeof(arr));
}
sum_array 함수에서 sizeof의 인자 arr은 포인터 변수이고 포인터 변수의 크기를 반환합니다.
main 함수에서 sizeof의 인자 arr도 포인터 변수인데 main 함수에서는 배열의 크기를 반환합니다.

sizeof의 인자가 포인터 변수로 동일한데 컴파일러는 어떻게 구분하고 서로 다른 크기를 반환하는지 궁금합니다.

익명 사용자의 이미지

Quote:
main 함수에서 sizeof의 인자 arr도 포인터 변수인데

아닙니다.

Quote:
sizeof의 인자가 포인터 변수로 동일한데

따라서 이것도 아닙니다.

====

C언어에서, 배열은 포인터가 아닙니다. "대부분의 경우" 배열이 그 배열의 첫 원소를 가리키는 (lvalue가 아닌) 포인터로 자동 변환되는 규칙이 있을 뿐입니다.

그 "대부분의 경우"의 몇 안 되는 예외 중 하나가 sizeof의 피연산자로 쓰일 때입니다.

main 함수의 arr는 int 2개짜리 배열이고, sizeof(arr)는 int 2개짜리 배열의 크기를 내놓습니다.

아, 그리고 규칙이 하나 더 있습니다. 함수 매개변수의 타입이 "T에 대한 배열"일 경우, 그 타입은 "T에 대한 포인터"로 조정됩니다. 그리고 그 매개변수에 sizeof를 적용하면, "T에 대한 포인터" 타입의 크기가 나옵니다.

그래서 sum_array 함수 안에서의 arr의 타입은 "int에 대한 포인터"라고 보셔도 됩니다.

종합해 보면, main함수가 sum_array 함수를 호출할 때 겉으로 보기에는 배열을 넘겨주고 배열을 받는 것처럼 보이지만, 사실은 포인터가 넘어가고 포인터로 받는 것입니다.

C언어의 배열이란 참 오묘하지요. C++11에서 std::array를 왜 만들었는지 알 것 같지 않습니까?

익명 사용자의 이미지

전 그냥 배열도 포인터에 가깝다고 이해하고 있었는데...
a[10] 이런 거는 {} 탈출하면 해제되는 메모리고,
*a = malloc (10) 이런 거는 {} 탈출해도 남아 있는 메모리라 free()로 명시적으로 해제.
어차피 a[0], a[1], 이런 식으로 접근 가능하고,

int *p;
int a[10];
p = a; 인지 p = &a[0]; 인지 이런 게 아직도 헷갈리긴 하네요.

익명 사용자의 이미지

Quote:
전 그냥 배열도 포인터에 가깝다고 이해하고 있었는데...

대충 그렇게 이해하고 있어도 대충 사용하는 데엔 문제 없습니다.

C언어에서 배열 타입은 뭐 좀 해 보려고만 하면 포인터로 바뀌어 사라져버리곤 하니까요.

그렇다곤 해도, 개념상 배열은 포인터와 다른 것이고, 그 차이가 미묘하게 드러나는 코드가 간혹 있습니다.

보여주신 것과 같이 sizeof를 적용할 때가 바로 그런 코드 중 하나입니다.

Quote:
a[10] 이런 거는 {} 탈출하면 해제되는 메모리고,
*a = malloc (10) 이런 거는 {} 탈출해도 남아 있는 메모리라 free()로 명시적으로 해제.

그건 배열이 아니어도 마찬가지죠.

Quote:
어차피 a[0], a[1], 이런 식으로 접근 가능하고,

이는 Array subscripting 연산자인데, 이름과는 다르게 사실은 포인터를 피연산자로 받는 연산자입니다.

배열에 대해서도 사용 가능한 이유는 배열이 포인터로 변하기 때문이죠.

Quote:
int *p;
int a[10];
p = a; 인지 p = &a[0]; 인지 이런 게 아직도 헷갈리긴 하네요.

둘 다 됩니다.

전자는 배열이 포인터로 변환되기 때문에, 후자는 그냥 int 타입 원소의 주소를 얻은 것이기 때문에 가능하죠.

그 결과도 똑같습니다.

익명 사용자의 이미지

와~~~~~~~~~~~~~ 명쾌한 설명 고맙습니다.

mrx@Google의 이미지

배열이 첫번째 원소를 가리키는 포인터다! 라고만 알고있었는데 사실 이는 "대부분의 경우" 자동 변환되는 규칙이었고 sizeof가 "대부분의 경우에 대한" 예외였군요.
감사합니다

익명 사용자의 이미지

여기서 퀴즈: sizeof()는 함수일까요? 아닐까요?

정답은 "아니다"입니다. http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf 6.5.3.4를 참조하세요.

익명 사용자의 이미지

sizeof 가 함수가 아니란 건 예전부터 알고 있었는데, sizeof 는 컴파일 타임에 결정된다... 아마도 그렇게 배웠던거 같은데, 매크로는 아니고요. 근데 좀.. 특이하게 작동하는거 같더라구요.

int  a[10];
int *b;
 
sizeof (a);
sizeof (b);

이렇게 하면 값이 얼마가 나올까~~~~~욧
뇌피셜로 함 써보는데,,

sizeof (a) 는 sizeof (int) * 10 의 값이 나올거 같고,
sizeof (b) 는 sizeof (int *) 의 값이 나올거 같다는...

뇌피셜이었습니다. ㅋㅋㅋ

익명 사용자의 이미지

제 기억에는

int *b = malloc (sizeof (int) * 10);
sizeof (b);

이렇게 했을 때, sizeof (int *) 의 값이 나왔던거 같습니다.
sizeof 라는게 좀 특이하긴 특이하더라구요.
당연히 ㅋㅋ 위에 소개하신 스펙 문서는 보지 않았습니다.
그거 볼 시간에 절세미남미녀들의 라이브 실방 보는게 ... 유익하다는 가치관을 갖고 있기 때문에요.
ㅋㅋㅋ

Stephen Kyoungwon Kim@Google의 이미지

sizeof는 복잡한 static analysis나 IR generation 없이 컴파일 타임에 그 값을 결정할 수 있어야 합니다. variable length array도 그 값을 결정하는 expression이 컴파일 타임에 결정되고, 그 expression이 복잡하지도 않습니다. array type의 A는 한 번 assign이 되면 다시 다른 버퍼로 assign 되는 일이 벌어지지 않지만, 포인터는 런타임에 컨트롤 플로우에 따라 얼마든 다른 사이즈의 버퍼가 할당될 수 있습니다. 그걸 컴파일 타임이 추적하기가 간단한 일은 아니죠.

그래서 Parsing 해서 AST를 만들면, 그냥 단순히 b의 타입 정보만 보고 처리하는 겁니다. 같은 이유로 C++의 inheritance에서 virtual이 아닌 method는 객체가 아니라 포인터 타입에 의해 결정됩니다. 객체 타입에 의해 method가 불리는 건 C++에서는 자연스럽지 않기 때문에 뭔가 거창한 트릭이 필요합니다.

댓글 달기

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