qsort 의 소스...

익명 사용자의 이미지

gcc에서 제공하는 qsort라는 함수의 소스가 어디에 있나요?
gcc 소스에 보면 다른 함수는 찾았지만 qsort 의 소스는 없내요..

일반적으로 qsort는 제귀호출을 하는 형식으로 알고 있습니다.
gcc에서 제공하는 qsort는 어떤 식으로 동작하는지 알고 싶어
그러거든요.. ^^

익명 사용자의 이미지

gcc보다는 glibc쪽에서 찾아야 할겁니다.

라이브러리함수니까요.

배석준 wrote..
gcc에서 제공하는 qsort라는 함수의 소스가 어디에 있나요?
gcc 소스에 보면 다른 함수는 찾았지만 qsort 의 소스는 없내요..

일반적으로 qsort는 제귀호출을 하는 형식으로 알고 있습니다.
gcc에서 제공하는 qsort는 어떤 식으로 동작하는지 알고 싶어
그러거든요.. ^^

antz의 이미지

qsort와 bsearch에 대한 소스는 여기서 찾을 수 있습니다.
http://www.gnu.org/manual/glibc-2.2.3/html_chapter/libc_toc.html

질문 있습니다.

int tel_cmp(const DupTel *c1, const DupTel *c2)
{
    return strcmp(c1->pTel, c2->pTel);
}

...
    result = bsearch(&target, stDupTel, nCount, sizeof(DupTel), tel_cmp);
    qsort(stDupTel, nCount, sizeof(DupTel), tel_cmp);
...

Quote:
orig_to_result.c: In function `put_deleted':
orig_to_result.c:242: warning: passing arg 5 of `bsearch' from incompatible pointer type
orig_to_result.c: In function `load_dup_data':
orig_to_result.c:322: warning: passing arg 4 of `qsort' from incompatible pointer type

예제와 같이 했는데. 다음과 같은 워닝이 발생하는 군요.
작동하는데는 이상이없습니다만, 컴파일마다 나와서요.
워닝을 없애려면 어떻게 해야할까요???

다음은 Glibc에 있는 예제입니다.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/* Define an array of critters to sort. */

struct critter
  {
    const char *name;
    const char *species;
  };

struct critter muppets[] =
  {
    {"Kermit", "frog"},
    {"Piggy", "pig"},
    {"Gonzo", "whatever"},
    {"Fozzie", "bear"},
    {"Sam", "eagle"},
    {"Robin", "frog"},
    {"Animal", "animal"},
    {"Camilla", "chicken"},
    {"Sweetums", "monster"},
    {"Dr. Strangepork", "pig"},
    {"Link Hogthrob", "pig"},
    {"Zoot", "human"},
    {"Dr. Bunsen Honeydew", "human"},
    {"Beaker", "human"},
    {"Swedish Chef", "human"}
  };

int count = sizeof (muppets) / sizeof (struct critter);

/* This is the comparison function used for sorting and searching. */

int 
critter_cmp (const struct critter *c1, const struct critter *c2)
{
  return strcmp (c1->name, c2->name);
}

/* Print information about a critter. */

void 
print_critter (const struct critter *c)
{
  printf ("%s, the %s\n", c->name, c->species);
}

/* Do the lookup into the sorted array. */

void 
find_critter (const char *name)
{
  struct critter target, *result;
  target.name = name;
  result = bsearch (&target, muppets, count, sizeof (struct critter),
                    critter_cmp);
  if (result)
    print_critter (result);
  else
    printf ("Couldn't find %s.\n", name);
}

/* Main program. */

int
main (void)
{
  int i;

  for (i = 0; i < count; i++)
    print_critter (&muppets[i]);
  printf ("\n");

  qsort (muppets, count, sizeof (struct critter), critter_cmp);

  for (i = 0; i < count; i++)
    print_critter (&muppets[i]);
  printf ("\n");

  find_critter ("Kermit");
  find_critter ("Gonzo");
  find_critter ("Janice");

  return 0;
}

The output from this program looks like:

Quote:
Kermit, the frog
Piggy, the pig
Gonzo, the whatever
Fozzie, the bear
Sam, the eagle
Robin, the frog
Animal, the animal
Camilla, the chicken
Sweetums, the monster
Dr. Strangepork, the pig
Link Hogthrob, the pig
Zoot, the human
Dr. Bunsen Honeydew, the human
Beaker, the human
Swedish Chef, the human

Animal, the animal
Beaker, the human
Camilla, the chicken
Dr. Bunsen Honeydew, the human
Dr. Strangepork, the pig
Fozzie, the bear
Gonzo, the whatever
Kermit, the frog
Link Hogthrob, the pig
Piggy, the pig
Robin, the frog
Sam, the eagle
Swedish Chef, the human
Sweetums, the monster
Zoot, the human

Kermit, the frog
Gonzo, the whatever
Couldn't find Janice.

antz의 이미지

답변 감사드립니다. :)

Quote:
>
> 저도 한가지 질문이 있는데
> qsort 에 전달할 비교함수로
>
> int intcmp(const int *, const int *);
>
> 를 넘겨줘도 되나요?
>

안 됩니다. qsort 의 비교 함수는 매개변수로 const void * 형을 갖습니다.
따라서, 호환되지 않는 함수 포인터를 전달하는 것은 정의되지 않은 행동을
일으키게 됩니다.

이 내용인것 같은데요. 이해가 잘 안됩니다.
설명 좀 해주셨으면 감사하겠습니다.
(잘못된 부분을 옳게 수정해 주시면 더 이해가 잘 될것 같습니다.)

Fe.head의 이미지

qsportㅇ의 원형은

void qsort(void *base, size_t nmemb, size_t size,
                  int(*compar)(const void *, const void *));

입니다.. 이것에 맞추어야 WARNING이 안뜨지요..

마지막인자인 함수포인터 원형을 보면

  int(*compar)(const void *, const void *)

이니..

 int intcmp(const int *, const int *); 

는 당연히 틀렸지요..

 int intcmp(const void *a, const void *b)
 {
        const int *pa = (const int *) a;
        const int *pb = (const int *) b;

        return *pa - *pb;
}

가 맞겠죠..

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

antz의 이미지

쉽게 설명해 주셔서 감사합니다. :D

워닝없이 잘 컴파일 됩니다.

체스맨의 이미지

Quote:
>
> 저도 한가지 질문이 있는데
> qsort 에 전달할 비교함수로
>
> int intcmp(const int *, const int *);
>
> 를 넘겨줘도 되나요?
>

안 됩니다. qsort 의 비교 함수는 매개변수로 const void * 형을 갖습니다.
따라서, 호환되지 않는 함수 포인터를 전달하는 것은 정의되지 않은 행동을
일으키게 됩니다.

안된다고 단정할 문제는 아닌것 같습니다.

intcmp 가 int (*)(const void*,const void*) 와 '동일'한 프로토타입은
아니지만, '등가'의 프로토타입입니다. 즉,

(int (*)(const void*,const void*))intcmp

와 같이 캐스팅해서 집어 넣으면 됩니다. 단, '등가'가 아닌 프로토타입
(인자가 다르거나 호출규약 등이 다른)의 함수가 위와같이 강제로 캐스팅
될 수도 있기 때문에 동일한 프로토타입을 쓰는 것보다는 약간의 위험성은
있다고 볼 수 있습니다.

어떤 방법을 쓰든 캐스팅은 일어나게 돼 있습니다.
위와 같이 함수 포인터를 캐스팅해서 집어 넣거나, 아니면
비교 함수 안에서 입력된 const void* 를 원하는 타입으로 캐스팅하거나.

동일 호출 규약을 쓰는 함수 포인터를 캐스팅해서 집어넣는 것이 문제가
발생할 수 있다면, 그것은 const void* 와 그것이 아닌 다른 타입의
포인터를 스택에 서로 다른 방법으로 push 하는 컴파일러가 있다는 것을
의미하는 것이겠죠.

Orion Project : http://orionids.org

전웅의 이미지

체스맨 wrote:
안된다고 단정할 문제는 아닌것 같습니다.

"안 됩니다" 라고 단정할 문제입니다.

체스맨 wrote:
intcmp 가 int (*)(const void*,const void*) 와 '동일'한 프로토타입은
아니지만, '등가'의 프로토타입입니다. 즉,

(int (*)(const void*,const void*))intcmp

와 같이 캐스팅해서 집어 넣으면 됩니다.

"등가"라면 왜 캐스팅이 필요하겠습니까? 다시 한번 말씀드리지만, 표준은
정상적인 C 프로그램은 거의 포인터와 관련된 캐스트 연산을 사용하지
않고도 잘 작동하도록 충분히 배려하고 있습니다.

int (*)(const void *, const void *) 와
int (*)(const int *, const int *) 는 "등가"도 아닌 완전히 호환되지
않는 (incompatible) 데이터형입니다. 일단, 위와 같이 강제 형변환을 통해
다른 함수로 함수 포인터가 전달되고, 그 함수 포인터가 함수 호출에 사용
된다면 그 결과를 "이식성 있는 단계에서" 예측할 수 없습니다. 더구나 이
경우에는 올바른 결과를 보장하기 위해서는 많은 가정들이 필요한 경우이기
에 섣불리 그와 같은 구조를 사용해서는 안 됩니다.

그동안 몇몇 논의가 되었던 "트릭"은 (이식성에 제한이 있다는 사실을 안다
면) 충분히 의존할만한 가치가 있는 것들이었지만 이번에는 그렇지 않습니
다.

체스맨 wrote:
어떤 방법을 쓰든 캐스팅은 일어나게 돼 있습니다.
위와 같이 함수 포인터를 캐스팅해서 집어 넣거나, 아니면
비교 함수 안에서 입력된 const void* 를 원하는 타입으로 캐스팅하거나.

올바른 방법은, int (*)(const void *, const void *) 와 호환되는 함수 포
인터를 전달한 후에, 해당 함수 안에서 전달받은 generic pointer 를 의미
있는 type 으로 변환해 비교하는 것입니다. 어떠한 경우라도 함수 포인터가
호환되지 않는 데이터형의 함수를 가리키는 상황에서 그 함수를 호출하기
위해 함수 포인터를 사용한다면, 결과는 정의되지 않습니다. 또, 이는 유용
한 "트릭"도 아니기에 고려해볼 가치도 없습니다 - qsort() 가 일반화되기
위해서 복잡하게도 generic pointer 를 도입하고 있다는 사실에 유의하시기
바랍니다.

체스맨 wrote:
동일 호출 규약을 쓰는 함수 포인터를 캐스팅해서 집어넣는 것이 문제가
발생할 수 있다면, 그것은 const void* 와 그것이 아닌 다른 타입의
포인터를 스택에 서로 다른 방법으로 push 하는 컴파일러가 있다는 것을
의미하는 것이겠죠.

또 다른 문제를 일으킬 수 있는 경우를 생각해 보겠습니다.

다른 포인터와는 달리 generic pointer 에 특별한 제한을 가하는 환경도 있
습니다 - 제 책에 실례를 들어 두었습니다. 그러한 환경에서는 generic
pointer 와 다른 object pointer 의 내부 표현 (internal representation)
이 호환되지 않습니다. 이 경우, void * 형 값으로 이루어지는 다른 포인터
형의 type punning 은 전혀 엉뚱한 결과를 만들어 낼 수 있습니다.

유사한 이유는 calling convention 에도 적용됩니다. generic pointer 가
더 특이해야 하는 경우라면, 함수 호출의 convention 에서도 generic
pointer 와 일반 object pointer 가 차별화될 수 있습니다.

말씀하신 정도의 "트릭"을 원하신다면 차라리 깔끔하게 어셈블리어를 사용
하는 것이 낫다고 생각합니다.

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

체스맨의 이미지

다음 사이트에,

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

다음 내용이 있습니다.

Quote:

119-121(§5.11): The qsort discussion needs recasting in several ways. First, qsort is a standard routine in ANSI/ISO C, so the rendition here should be given a different name, especially because the arguments to standard qsort are a bit different: the standard accepts a base pointer and a count, while this example uses a base pointer and two offsets.

Also, the comparison-routine argument is not treated well. The call shown on p 119, with an argument

(int (*)(void*,void*))(numeric? numcmp : strcmp)

is not only complicated, but only barely passes muster. Both numcmp and strcmp take char * arguments, but this expression casts pointers to these functions to a function pointer that takes void * arguments. The standard does say that void * and char * have the same representation, so the example will almost certainly work in practice, and is at least defensible under the standard. There are too many lessons in these pages.

프로토타입을 맞춰서 넣는 것은 기본적으로 취해야 할 일이지만,
함수포인터 캐스트가 유용할 때도 있습니다. 위와 같은 예는 매우
단적이지만요.

Orion Project : http://orionids.org

전웅의 이미지

체스맨 wrote:
다음 사이트에,

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

다음 내용이 있습니다.

Quote:

119-121(§5.11): The qsort discussion needs recasting in several ways. First, qsort is a standard routine in ANSI/ISO C, so the rendition here should be given a different name, especially because the arguments to standard qsort are a bit different: the standard accepts a base pointer and a count, while this example uses a base pointer and two offsets.

Also, the comparison-routine argument is not treated well. The call shown on p 119, with an argument

(int (*)(void*,void*))(numeric? numcmp : strcmp)

is not only complicated, but only barely passes muster. Both numcmp and strcmp take char * arguments, but this expression casts pointers to these functions to a function pointer that takes void * arguments. The standard does say that void * and char * have the same representation, so the example will almost certainly work in practice, and is at least defensible under the standard. There are too many lessons in these pages.

프로토타입을 맞춰서 넣는 것은 기본적으로 취해야 할 일이지만,
함수포인터 캐스트가 유용할 때도 있습니다. 위와 같은 예는 매우
단적이지만요.

일단, errata 를 반영하지 않은 K&R2 는 엄밀한 부분에서 표준을 따르지 않
는 부분이 다소 있습니다. 이는 뉴스그룹에서도 여러번 반복된 논의고 뉴스
그룹에서 표준 C 를 공부하며 활동하는 다수의 사람이 K&R2 에 존재하는 문
제를 찾아냈다는 점이 반증하는 사실입니다.

하지만, "이러한 사실을 무시하더라도" 정작 중요한 사실을 간과하고 계십
니다. 인용하신 errata 에서 bold type 으로 표시될 부분은 그 앞의

Quote:
The standard does say that void * and char * have the same representation

도 포함되어야 합니다. 현재 문제가 되고 있는 부분과 K&R2 errata 에서 언
급된 부분을 예로 비유해 보겠습니다. 현재 문제가 되고 있는 부분은,

int func(int a, int b);

int another_func(void)
{
    func(123, 456);
}

/* 다른 소스 파일에서 */
int func(float a, float b)
{
    printf("%f, %f", a, b);
}

로 표현할 수 있습니다. 반면, K&R2 errata 에서 언급된 부분은 다음과 같
이 표현할 수 있습니다:

int func(int a, int b);

int another_func(void)
{
    func(123, 456);
    /* ... */
}

/* 다른 소스 파일에서 */
int func(unsigned a, unsigned b)
{
    printf("%u, %u", a, b);
}

일단, 두 경우 모두 표준의 엄격한 해석에 따르면 정의되지 않은 행동이지
만, 함수의 calling convention 로 인한 문제가 없다고 가정한다면, 후자의
경우 int 와 unsigned int 의 양수에 대한 representation 이 호환되기에
(이 호환은 표준에 의한 보장입니다) 현실적으로 문제를 일으킬 가능성이
그나마 적습니다.

즉, 이미 말씀드렸듯이 int * 와 void * 는 전혀 표현의 호환성이 보장되지
않지만, char * 와 void * 에 대해서는 표준이 보장합니다. 실제로 아래와
같은 type punning 을 하는 함수 호출이 C90 에서는 엄격하게는 정의되지
않는 행동이었지만,

int func();

int another_func(void)
{
    char *a, *b;    /* 초기화 가정 */
    func(a, b);
}

int func(void *, void *) {   /* ... */   }

C99 에서는 (char * 와 void * 의 표현 호환성을 현실적으로 반영하여) 적
법한 구조로 보장됩니다.

일단, K&R2 의 errata 는 책의 해당 부분이 "잘못되었기" 때문에 나온 것이
며 (그런 errata 가 없다면 책 표지의 "ANSI-C" 문구는 "Almost ANSI-C" 로
바뀌어야 할 것입니다) strcmp() 같이 char * 를 받는 함수를 qsort() 에
전달하는 것에 대한 설명 역시 개인적으로는 일종의 "변명" 이라고 생각합
니다 - 만약 DMR 이 책을 집필할 때 표준의 해당 부분을 제대로 이해했다면
애초에 strcmp() 를 위한 간단한 wrapper function 을 도입했을 것입니다.

또한, 현실적으로 qsort 와 관련된 부분이 성능에 큰 영향을 주는 주요한
부분이고 또 그때 존재하는 wrapper function 의 overhead 가 무시할 수 없
는 상황이라고해도, 포인터 표현에 대한 중요한 한 가지 가정이 표준에 의
해 보장되는 K&R2 의 예는, 전혀 무관한 포인터 사이의 type punning 이 일
어나는 지금의 경우에 적용될 수는 없다고 생각합니다 - DMR 이 해당 구조
가 현실적으로 큰 문제를 일으키지 않을 것이라고 생각하는 근거가 char *
와 void * 의 표현 호환성에 있음에 유의하시기 바랍니다. 그리고, 진정으
로 qsort 가 이식성을 확보하기 위한 wrapper function 을 도입하기 어려울
만큼 성능에 중요한 부분이라면, 차라리 잘 알려진 quick sort 나 그 외의
sort 알고리즘을 사용해 application-specific한 정렬 함수를 만들어 사용
하길 추천합니다. qsort() 는 일반적인 경우를 다루기 위해 좋은 알고리즘
을 쓰고도 성능에 많은 손해를 보는 함수 중 하나입니다.

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

체스맨의 이미지

혹시 표준에 둘의 호환성을 보장하는 근거도 나와있는지요?
예상컨데, 표준에서 void* 와 char* 의 호환성을 보장할 수 있었던
것은 char 가 단일 바이트이기 때문에, 할당된 주소의 어느 부분을
가리켜도 그 내용을 참조하는데 있어 어떠한 시스템에서도
bus error 와 같은 문제를 일으키지 않기 때문이라고 생각합니다.

즉, 표준이 보장하는 void* 와 char* 의 호환성은,
오직 두타입에 대해 sizeof(void*)==sizeof(char*)를 보장한다는
것으로는 생각되지 않습니다.

만일 모든 일반적인(예를 들어 도스의 far 나 huge 같은 특수한
경우가 아닌) 포인터 타입의 크기가 같다면, int* 가 인자라 해도
입력한 포인터들의 주소 정렬에 문제가 없다면 (제대로 코딩 됐다면)
문제가 발생하지 않을 것이라 생각합니다.

만일 저런 코드가 만든 실행파일이 문제를 일으키는 시스템이
있다면 알려주셨으면 합니다.

Orion Project : http://orionids.org

전웅의 이미지

체스맨 wrote:
혹시 표준에 둘의 호환성을 보장하는 근거도 나와있는지요?
예상컨데, 표준에서 void* 와 char* 의 호환성을 보장할 수 있었던
것은 char* 가 단일 바이트이기 때문에, 할당된 주소의 어느 부분을
가리켜도 그 내용을 참조하는데 있어 어떠한 시스템에서도
bus error 와 같은 문제를 일으키지 않기 때문이라고 생각합니다.

말씀하신 내용은 과거 char * 가 generic pointer 의 역할을 했던 이유이며,
char * 가 character pointer 와 generic pointer 의 역할을 모두 했었기에
진단 메시지에 대한 현실적 조율을 위해 표준이 void * 를 도입하면서 당연
히 void * 와 char * 는 같은 표현 (그리고 같은 정렬 제한) 을 갖게 되었
습니다. char * 와 void * 에 대한 간단한 역사적 사실은 얼마전 이곳에서
제가 설명했던 것으로 기억하고 있습니다.

체스맨 wrote:
즉, 표준이 보장하는 void* 와 char* 의 호환성은,
오직 두타입에 대해 sizeof(void*)==sizeof(char*)를 보장한다는
것으로는 생각되지 않습니다.

"같은 표현" 은 단지 크기만 같다는 뜻이 아닙니다. 같은 비트열을 type
punning 을 통해 다른 type 으로 해석했을 때 동일한 의미를 갖는다는 사실
을 의미합니다. void * 와 char * 에 대해서는 같은 표현과 같은 정렬 제한
이 보장되지만, 위에서 문제가 되었던 int * 와 void * 에는 그런 보장이
전혀 없습니다. 정렬 제한이 문제를 일으킬 수도 있으며, 다른 표현을 사용
할 경우 동일한 비트열은 전혀 다른 의미가 될 수 있으며 (따라서, type
punning 의 결과는 invalid pointer 를 만들 수도 있습니다) 크기조차 다를
수도 있습니다 - 즉, sizeof(int *) != sizeof(void *) 가 가능하다는 뜻입
니다.

체스맨 wrote:
만일 모든 일반적인(예를 들어 도스의 far 나 huge 같은 특수한
경우가 아닌) 포인터 타입의 크기가 같다면, int* 가 인자라 해도
입력한 포인터들의 주소 정렬에 문제가 없다면 (제대로 코딩 됐다면)
문제가 발생하지 않을 것이라 생각합니다.

크기와 정렬 제한도 문제가 없어야 하지만 같은 비트열이 같은 의미를 가져
야 합니다 - 이것이 "같은 표현, 같은 정렬 제한" 이 의미하는 바입니다 -
int * 와 void * 가 크키와 정렬 제한이 같다고 해도 표준에 의해
unspecified 로 규정되어 있는 포인터의 내부 표현은 다를 수 있습니다.

님께서 가정하고 계시는 상당히 엄격한 int *, void * 의 호환 관계는
uniform pointer 라고 부르는 것입니다. 즉, 모든 object pointer 가 (혹은
function pointer 도) 같은 표현, 같은 정렬 제한을 갖는 환경을 말합니다.
그리고, uniform pointer 는 표준이 보장해주는 사실이 아닙니다.

체스맨 wrote:
만일 저런 코드가 만든 실행파일이 문제를 일으키는 시스템이
있다면 알려주셨으면 합니다.

이미 그런 시스템 (void * 와 다른 object pointer 의 내부 표현이 다르거
나 아예 크기가 다른 경우 등) 이 실존한다고 말씀드렸습니다:

전웅 wrote:
다른 포인터와는 달리 generic pointer 에 특별한 제한을 가하는 환경도 있
습니다 - 제 책에 실례를 들어 두었습니다.

지금 제가 제 책을 가지고 있지 않고, 다른 사람 컴퓨터 앞에 앉아 있기에
인용을 해드릴 수는 없습니다 - 죄송합니다.

그리고, 계속되는 논의 속에 묻혀서는 안 되는 중요한 사실이 있습니다.
void * 와 char * 가 아무리 동일한 표현, 정렬 제한을 보장받는다고 해도
int (*)(char *) 와 int (*)(void *) 는 "호환되지 않는" 데이터형이라는
사실입니다. 이 사실 하나만으로도 충분히 OP 와 K&R2 의 프로그램은 "잘못
된" 프로그램입니다. 즉, 현실적으로 잘 작동한다면 이는 "우연" 일 뿐이며
다른 환경에서의 작동은 보장받지 못합니다 - 그나마 K&R2 의 예는 char *
와 void * 에 대한 표준의 보장 덕에 "at least defensible under the
Standard" 하다는 사실에는 어느 정도 동의합니다.

다시 한번 강조해서 말씀드리지만, 논의 중인 부분이 이와 같은 사실을 무
시할만큼 성능에 중요한 경우를 만나기도 어렵지만, 설사 만난다고 해도
wrapping function 의 overhead 가 그토록 마음에 걸리는 경우라면 차라리
일반화를 위해 성능을 포기하는 qsort() 사용을 재고해 보시길 강력히 추천
합니다. 실제로 "세 값의 중위" 알고리즘을 쓰는 일반화된 qsort() 는 단순
하게 rightmost 값을 pivot 으로 잡는 특수화된 quick sort 구현보다 느립
니다.

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

체스맨의 이미지

예, 포인터 크기가 서로 다를 수 있다면 문제는 당연히 발생하겠지요.

그렇다면 sizeof(void*)==sizeof(char*)는 항상 보장되고,
이 값은 다른 어떠한 포인터들의 sizeof 값보다 크겠군요.

전웅님 글에 의해 uniform pointer 라는 용어를 알게 되었네요.
더불어 또다시 제가 구현했던 코드들의 일부를 수정해야 할 일이
생겼습니다. :?

더불어 주제와 많이 빗나갔지만 질문을 하나 하겠습니다.

sizeof(void*)!=sizeof(int*) 일 수 있지만, 예를들어
sizeof(int*)!=sizeof(float*) 인 시스템이 있는지요?
특히, sizeof(struct _a*)!=sizeof(struct _b*) 인 시스템이
있는지요? 이것은 제게 좀 중요한 문제입니다.

-------------------------
생각해보니, 그런 시스템은 없을 것 같군요. :)

Orion Project : http://orionids.org

전웅의 이미지

체스맨 wrote:
예, 포인터 크기가 서로 다를 수 있다면 문제는 당연히 발생하겠지요.

그렇다면 sizeof(void*)==sizeof(char*)는 항상 보장되고,

예, 이는 표준에 의한 보장입니다.

체스맨 wrote:
이 값은 다른 어떠한 포인터들의 sizeof 값보다 크겠군요.

이는 표준에 의한 보장은 아니지만, char *, void * 의 특성을 생각한다면
현실적으로 충분히 의존할 수 있는 가정입니다. 단, "이론적으로는"
sizeof(int *) > sizeof(void *) 도 불가능한 것은 (즉, 표준이 금지하는
것은) 아닙니다.

체스맨 wrote:
전웅님 글에 의해 uniform pointer 라는 용어를 알게 되었네요.
더불어 또다시 제가 구현했던 코드들의 일부를 수정해야 할 일이
생겼습니다. :?

더불어 주제와 많이 빗나갔지만 질문을 하나 하겠습니다.

sizeof(void*)!=sizeof(int*) 일 수 있지만, 예를들어
sizeof(int*)!=sizeof(float*) 인 시스템이 있는지요?

이론적으로는 가능하지만, 현실적으로는 본 적도, 들어 본 적도 없습니다.
현재 작성되어 있는 프로그램이 이 가정에 의존한다면 굳이 고치지 않아도
현실적인 문제는 없다고 생각합니다.

체스맨 wrote:
특히, sizeof(struct _a*)!=sizeof(struct _b*) 인 시스템이
있는지요? 이것은 제게 좀 중요한 문제입니다.

구조체 포인터는 제게도 중요합니다. :) ADT 를 구현하는 경우 구조체 혹은
공용체 포인터의 표현, 정렬 제한의 호환 문제가 중요하기에, 표준은 (엄격
하게는 C99 부터는) 모든 구조체 포인터는 같은 표현과 같은 정렬 제한을
갖도록, 또 유사하게 모든 공용체 포인터는 같은 표현과 같은 정렬 제한을
갖도록 요구합니다. 호환되지 않는 구조체형으로 type punning 을 통해 멤
버에 접근하는 것은 잘못된 행동이지만, 말씀하신 두 구조체 포인터의 크기
와 정렬 제한 그리고 내부 표현이 동일하다는 것은 보장되는 사실입니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

댓글 달기

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