이런 식의 구조체 사용도 아무 문제 없는지 궁금합니다.

lunarainbow의 이미지

typedef struct A {
    unsigned long int   a;
    unsigned long int   b;
} AA;


typedef B {
    unsigned int        Count;
    AA         List[1];
} BB;



	BB           *listptr = NULL;

	listptr = (BB*)malloc(sizeof(BB) + sizeof(AA) * 1000);

	while (1)
	{
		listptr->List[listptr->Count].a = 10;
		listptr->List[listptr->Count].b = 20;
		listptr->Count++;
	}

간단한 코드라 별다른 할말이 없네요. ^^;

제가 궁금한것은 이렇게 사용하는것도 아무 문제가 없는 것인지 여부입니다.

만일 malloc 할당시 잡아주는 AA구조체의 수가 무진장 커지던가 하면, 나중에 사용할 시 오류를 낸다던가 등의 위험성 여부 말입니다.

감사합니다. ^^

espereto의 이미지

제가 보기에는 문제없을 듯 합니다, 할당된 메모리 영역만 넘어가지 않게 한다면.

팜 프로그래밍을 좀 해 봤는데, 팜의 경우 상당히 많은 구조체들이 저런 식으로 쓰이는 것 같더군요. ( 저런 식으로 쓰는 경우를 팜에서 처음 봤기때문에 매우 당황스러웠습니다. :) )

예를 들어, 비트맵 구조체의 경우 비트맵 정보만 가지게 구성되어 있고, 비트맵 데이터는 구조체의 어느 변수에도 안 들어갑니다만, 비트맵 구조체의 다음 주소 영역에 비트맵 데이터가 들어가더군요. 비트맵 구조체 포인터가 pBitmap 이라면, 비트맵 데이터는 pBitmap+1 부터 들어가 있더군요.
lunarainbow님의 코드와 매우 비슷하게 쓰는 부분이 많았습니다.

wind772의 이미지

오호.. 메모리할당을 저렇게도 사용할수 있다는 것이..+_+
처음 알았네요...ㅋㅋ 소스 한참보고 나서야 어떻게 돌아가는지 알았으니...떠업..
그래도 오늘 새로운거 하나 알게 되네요~ ^^
나중에 써먹어야지...ㅡ_ㅡb

===================================================
중요한건 얼마나 아느냐가 아니라 그것에 대한 열정이다.

lunarainbow의 이미지

아... 아무 문제 없는 코드이군요. ^^

저는 보통 위와 같은 코드일 경우 AA 구조체의 포인터를 하나 선언하여 그걸 이용하여 주소 연산을 통하여 계산하곤 하였거든요.

답변 감사합니다. :D

익명 사용자의 이미지

데이터 버퍼관리시에 이런거 많이 쓰죠.

typedef struct 
{
 unsigned long Size;
 unsigned char DataPtr;
}t_Data;

int s_RecvBytes;
t_Data *s_Data;

s_RecvBytes = recv(Handle, Buffer, sizeof(Buffer);

if(s_RecvBytes > 0)
{
  s_Data = (t_Data *)malloc( (sizeof(t_Data) - 1) + s_RecvBytes );
  s_Data->Size = s_RecvBytes;
  memcpy( &s_Data->DataPtr , Buffer, s_RecvBytes );
}
체스맨의 이미지

할당만 제대로 하면 아무 문제 없고, 매우 유용하기도 한 방법입니다.
gcc 는 아예 이것을 위해 구조체 내에서는 0크기짜리 배열 선언도
지원합니다.

struct _hello {
  int a;
  int world[0];
};

Orion Project : http://orionids.org

lunarainbow의 이미지

답변 감사 드립니다.

체스맨님과 minzkn 님의 코드를 합칠 수 있나요?

그러니깐.. 다음처럼 말입니다.

typedef struct 
{ 
unsigned long Size; 
unsigned char DataPtr; 
}t_Data; 

이것을

typedef struct 
{ 
unsigned long Size; 
unsigned char DataPtr[0]; 
}t_Data; 

이렇게 선언한 다음

s_Data = (t_Data *)malloc( sizeof(t_Data) + s_RecvBytes ); 

이렇게 해줘도 가능한 것인가요? ( sizeof(t_Data)  - 1 에서 (- 1)은 케릭터 하나의 크기만큼을 의미 하는것으로 이해하였습니다.)

라고 막 질문을 다시 올리려 하였는데.. 제출 버튼을 누르려다 말고 너무 눈치보이길래 직접 테스트를 해 보았습니다. (너무 거저먹는거 같은 심보인거 같아서...)

typedef struct
{
        int size;
        char buf[0];
} AA;

AA *p;

p = (AA*) malloc( sizeof(AA) + 1000);

printf("%d %d\n", sizeof(AA), sizeof(p));

이렇게 출력해 보았을때 모두 결과가 

4 4 

이렇게 나오네요

이 말은,


만일 이렇게 사용하고자 할때 size를 저장하여 두지 않는다면, 그것의 크기를 알 수 없게 된다


라는 것입니다.

그럭저럭 중요한 내용이 아닐까 싶습니다.

답변 주신 분들에게 다시 한번 감사 드립니다.

체스맨의 이미지

말씀하신 것은
void* p = malloc( 1000 );
p 가 얼만큼 할당된 포인터인지 알 수 있는 방법은 그 크기를
저장해 두는 수 밖에 없는 것과 같은 얘기입니다. 일반(표준)적으로 포인터에
얼마만한 크기가 할당됐는 지 얻을 수 있는 함수는 제공되지 않지요.

제가 제시한 예는 gcc 에서 그런 식으로 지원할만큼 자주쓰이는 방법이라는
을 보여드린 것이고, 실제로는 gcc 만을 위한 코드가 되므로, 표준적인
방법을 쓰는 게 좋습니다.

lunarainbow wrote:

s_Data = (t_Data *)malloc( sizeof(t_Data) + s_RecvBytes );

이렇게 해줘도 가능한 것인가요? ( sizeof(t_Data) - 1 에서 (- 1)은 케릭터 하나의 크기만큼을 의미 하는것으로 이해하였습니다.)

예 맞습니다. 만일 NULL terminated string을 위해 한바이트 더 필요하다면,
-1 해줄 필요가 없고, 오히려 하나 더 할당돼 있던 게 편할 수도 있죠.

Orion Project : http://orionids.org

saxboy의 이미지

저는 제일 위에 쓰신 코드가 뭐가 문제인지 잘 모르겠는데요. 제가 둔감한건가요 아니면 제가 습관이 이상한건가요... 이상... 요상...

lunarainbow의 이미지

제가 둔감한건가요 아니면 제가 습관이 이상한건가요... 이상... 요상... 전혀 그렇지 않습니다. ^^

단지 너무 틀에 억메인것이 흠이라면 흠일 수 있겠네요.

malloc 이라는것은 결국 메모리 할당에 불과합니다.

그점을 이용해서 내가 원하는 가변적인 메모리를 사용할 수 있도록 하는 것입니다.

그러니깐.. 어떻게 설명을 해야 할지..;;

만약 어떤 구조체를 만들려 한다고 생각해 보죠.

그런데 마침 그 안에는 어떤 랜덤한 길이의 스트링을 넣어야 할 필요가 있다고 해볼께요.

그런데 미처 예측하기 힘든 길이라면 어떻게 할까요?

물론 쉬운 해결책으로써 포인터로 선언하여 할당을 시키는 방법이 있습니다.

하지만 포인터를 둔다면, 그를 위해 한번 더 malloc을 호출해야 할 필요가 있게 되고, 불행히도 malloc은 많은 시간을 요구하는 작업이라 알고 있습니다.

그렇기 때문에 처음 어차피 malloc을 해야할 시점에서 한번에 잡아 버리는 것입니다.

이 방법의 좋은점은,

1. 메모리 할당 시간을 줄일 수 있다.
2. 명확한 길이를 줄 수 있다.
3. 가변적인 길이를 사용할 수 있다.

이정도쯤 될까요?

음.. 그러고 보니 이렇게 하는것도 나름대로 효율적이 될 수 있겠군요.

typedef struct 
{ 
    int age;
    char name[12];
    char *addr;
} AA;

AA *p;

p = (AA*)malloc( sizeof(AA) + ADDRESS_LEN );

p->addr = p + sizeof(AA);

strspy(p->addr, addr);

이렇게 size라는 변수를 두지 않고 일반 포인터를 사용하듯이 한번에 선언 하는것도 괜찮을것 같네요. ^^

이것은 위의 방법보다 좀더 나은점은, 위의 방법은 스트링(또는 기타 변수들)의 위치가 항상 마지막에 위치해야 한다는 것을 피할 수 있을 뿐만 아니라, 이러한 식으로 사용하는 변수가 몇개가 될지라도 모두 가능하게 해준다라는 것이겠네요.

여러 포인터 변수가 존재할 경우 유용한 구문이 되겠네요.

saxboy님 덕분에 저도 하나 더 알게 되었네요. 감사합니다. ^^

moonzoo의 이미지

typedef struct
{
unsigned long Size;
unsigned char DataPtr;
}t_Data;

일반적으로

unsigned char 를 쓰는 것과

char 로 쓸경우에 혹시 차이가 있나여?

char 대신 unsigned char 를 쓸때의 차이점이

궁금합니다.....

익명 사용자의 이미지

moonzoo wrote:
typedef struct
{
unsigned long Size;
unsigned char DataPtr;
}t_Data;

일반적으로

unsigned char 를 쓰는 것과

char 로 쓸경우에 혹시 차이가 있나여?

char 대신 unsigned char 를 쓸때의 차이점이

궁금합니다.....

이건 그냥 습관적인 경우가 더욱 비중이 있지만
문자열로 다루지 않는한 unsigned를 습관적으로 사용하는게
좋다고 주장합니다. 안그러면
괜한곳에서 int로 캐스팅되면서 값이 무지 커지거든요.

예를 들어서

char a = 0xff;
int b;
 
b = a;

fprintf(stdout, "%d', b);

이런거 신경쓰이니까

unsigned char a = 0xff;
int b;
 
b = a;

fprintf(stdout, "%d', b);

요렇게 합니다.
결과는 어떻게 나오는지 아시죠?

그냥 개발자마다 각자 신경쓰고 싶지 않는 부분이 있을텐데
이러한 캐스팅에서 오는 데이터 왜곡을 막기 위함이죠.. 그냥 습관입니다.

lunarainbow의 이미지

첫번째 결과

-1

두번째 결과

255

지금 테스트 해보니 이렇게 나오네요.

혹시나 싶어서 이렇게 바꿔서 테스트 해봤습니다.

        char a = 0xff;
        int b;

        b = a;

        printf("%8x\n", b);

결과는

ffffffff

휴우. 저도 평소엔 별로 의식하지 못하였던 부분이네요.

오늘 정말 많이 배우는 날이네요. ^^

지금 날씨도 좋은데, 정말 많이 배웠다라는 기분에 날아갈 것만 같아요 :D

정말 감사드립니다.

댓글 달기

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