2012-09-04 5 views
1

나는 메모리 할당과 관련하여 memcpy()의 결과를 어떻게 알고 싶습니다. 코드와 관련하여문자 배열 메모리 할당

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

typedef struct { 
    char myname[7] ; 
} transrules; 

trans typedef struct { 
    char ip ; 
    int udp; 
    transrules rules[256]; 
} __attribute__ ((__packed__)) myudp; 

myudp __attribute__ ((__packed__)) udpdata ; 

char arr[400] ; 

int main() {    
    memset (&udpdata , 0 ,sizeof(udpdata)); 
    udpdata.ip = 'a' ; 
    udpdata.udp = 13 ; 
    udpdata.rules[0].myname = "lalla\0" ; 
    memcpy (&arr , &udpdata, sizeof(udpdata)); 
    printf("%c",arr[0]); 
    return 0; 
} 

, 우리는 어떻게 구조 transrules의 문자 배열을 인쇄합니까?

추신 : 예,이 코드는 오류가 발생합니다. char 님!

정의 된 배열의 유형이 char이므로 arr [1]이 (가) memcpy() 인 정수 값을 허용하는 이유는 무엇입니까?

+0

게시자가 게시 한 코드가 무엇인지 구체적으로 언급 한 경우 도움이 될 수 있습니다. 세 가지 개별 문제가 있지만 그 중 어떤 것도 직접 언급하지는 않습니다. –

답변

3

memcpy 메모리를 할당하지 않습니다. memcpy 호출에서 변수 arr (char arr[400])이 정의되면 대상 메모리 arr이 할당되었습니다.

충분한 공간을 할당하지 않은 경우 문제가 있습니다. arrsizeof(updata) 바이트를 복사합니다. 이는 아마 1 + 4 + 7 * 256 = 1797입니다 (sizeof(int)에 따라 달라질 수 있으며 __packed__이 플랫폼에서 사용되지 않는 바이트를 실제로 제외하는지 여부에 따라 달라질 수 있습니다). arr이 정말로 필요하다면 (아마도 그렇지 않을 수도 있습니다.) 적어도 sizeof(updata) 크기로 만드십시오. char arr[sizeof(updata)]으로 정의하는 것이 좋습니다.

구조체의 레이아웃이 외부 형식으로 정의 된 경우 int (플랫폼에 따라 2 또는 4 바이트) 대신 고정 크기 유형을 사용해야하며 다른 크기 일 수는 있지만 가능성은 낮습니다 그들을 만나기).

구조의 레이아웃이 일부 외부 바이너리 형식으로 정의되고이 형식으로 1797 바이트를 인쇄하려면 fwrite을 사용하십시오.

fwrite(updata, sizeof(updata), 1, stdout); 

하면, 데이터의 인간 표현이 적절한 형식 사양을 printf을 사용합니다.

printf("ip='%c' udp=%d\n", updata.ip, updata.ip); 
for (i = 0; i < sizeof(updata.rules)/sizeof(updata.rules[0]); i++) { 
    puts(updata.rules[i].myname); 
} 

이름에도 불구하고 실제로는 char이 바이트 유형입니다. C의 문자에는 별도의 유형이 없습니다. 'a'과 같은 문자 상수는 사실 정수 값입니다 (거의 모든 시스템에서 97, ASCII). 바이트를 문자로 해석하게하는 것은 putchar 또는 printf("%c", …)으로 쓰는 것과 같습니다.

포인터 (예 : char*)을 정수와 혼합 할 때 컴파일러에서 오류를 알리는 메시지가 표시되지 않으면 경고 수준을 높입니다. GCC를 사용하려면 적어도 gcc -O -Wall을 사용하십시오.


실제로 코드를 컴파일 후, 메인 오류가 (당신은 당신의 질문에 컴파일러에서 오류 메시지를 복사 - 붙여 넣기해야) :

udpdata.rules[0].myname = "lalla\0" ; 

udpdata.rules[0].myname 바이트의 배열입니다. C의 배열에 할당 할 수 없습니다. 요소를 하나씩 복사해야합니다. 이것은 char의 배열이고 문자열을 복사하려는 경우 strcpy을 사용하여 문자열의 모든 바이트를 복사 할 수 있습니다. 일반적으로 바이트 묶음의 경우 memcpy을 사용합니다.

strcpy(udpdata.rules[0].myname, "lalla"); 

는 모든 규모의 검증을 수행하지 않습니다 strcpy 때문에 ( "lalla\0"는 모든 문자열 리터럴이 C.¹에 제로 종료됩니다 "lalla"에 해당합니다), 당신은 확인해야하는 최종 NULL 문자를 포함한 문자열 ()는 대상에 할당 한 메모리에 적합합니다. 최대 크기를 지정하려면 strncat 또는 strlcpy과 같은 다른 기능을 사용할 수 있습니다.

¹ "lalla"이 제로 종료되지 않는 경우가 하나뿐입니다 (예외적 인 경우 만 해당). 예 : 5 바이트 배열을 초기화 할 때. char bytes[5] = "lalla". 배열 크기가 6 이상이거나 지정되지 않은 경우 0 바이트가 종료됩니다.

+0

+1 명확한 설명 잘라 내기 :) – user1471

1
 
// this is really bad 
udpdata.rules[0].myname = "lalla\0" ; 

// do this instead. You want the literal string in your field. 
memcpy(udpdata.rules[0].myname, "lalla\0", 6); 

.... 

// This is wrong. arr is already a pointer. 
memcpy (&arr , &udpdata, sizeof(udpdata)); 

// do this instead 
mempcy (arr, &udpdata, sizeof(udpdate)); 

에 관한 인쇄, 나는 그들이 4 바이트 인 경우 컴퓨터에 있지만 얼마나 큰 int 치의 모르는 다음에 모든 것을 변환 할 이유를 잘 모르겠어요

printf("%.7s", &arr[1+4]);

내용을 인쇄하려면 char 배열을 사용하십시오. 구조체를 사용하고 루프에는 을 사용하십시오. 어쨌든 C 배열을 읽고 싶을 수도 있습니다.

1

코드와 관련하여 구조체 배열에서 문자 배열을 어떻게 인쇄합니까?

/* incorrect -> udpdata.rules[0].myname = "lalla\0" ; */ 
strcpy(udpdata.rules[0].myname,"lalla") ; 
printf("%s\n",udpdata.rules[0].myname); 

정의 배열 도착 [1] 여전히 방어 적이기 갖는 정수 값을 받아들이 않는 이유 char 형이므로?

memcpy는 기본 데이터 유형이 복사 대상이 될 수있는 항목을 모르거나 신경 쓰지 않습니다. void 포인터를 가져 와서 하나 이상의 바이트 값을 하나 이상의 다른 바이트에 복사합니다.

void * memcpy (void * destination, const void * source, size_t num);