쓰기

2016-12-26 2 views
-3

-Theory C 메모리에 다른 종류 읽어쓰기

I는 다른 유형의 변수 S 세트가 있고 지금 S.의 크기와 메모리 어드레스 포인터 P의 좌표를, I S의 모든 값을 P로 지정하고 다시 읽으 려합니다.

이 문제는 수동으로 구조체와 비슷한 것을 구축하는 데 있습니다.

내가 그랬어 어쩐 :

우리가 여기서 문제는 내 할당하고 있습니다 것입니다

uint8_t* foo(int i, char c, char* s) { 
    uint8_t* r = malloc(sizeof(i) + sizeof(c) + sizeof(s)); 
    *r = i; 
    *(r+sizeof(i)) = c; 
    *(r+sizeof(i)+sizeof(c)) = s; 
    return r; 
} 

int main(void) { 
    uint8_t * a = foo(500, 'a', "hello"); 
    printf("%d, %c, %s\n", *a, *(a+sizeof(int)), (a+sizeof(int)+sizeof(char))); 
    return 0; 
} 

우리의 S 등의 난, 숯불 c 및 숯불 * s의하는 int가 있다고 가정하자 데이터를 첫 번째 바이트로만 읽은 다음 첫 번째 바이트 만 읽습니다.

년 - 질문 : 컴파일러를 어떻게 알 수

그 * r에에에 foo = 난; i를 * r의 다음 4 바이트에 할당 한 다음 주 읽기 *를 a로 4 바이트로 지정한 다음 c 및 s에 대해 동일한 작업을 수행합니까?

+0

'sizeof (s)'가 함수에 전달 된 문자열 데이터에 대해 아무 것도 말하지 않는다는 것을 알기를 바랍니다. 그것은 포인터의 크기입니다. –

+0

예, 나는 포인터를 포함하여 어떤 타입도 저장하는 것을 신경 쓰지 않는다 – Naheel

+0

'* (r + sizeof (i) + sizeof (c)) = s;'는 문자열을 복사하지도, 문자열 포인터를위한 공간도 없다 'uint8_t'에 있습니다. –

답변

1

당신은, 당신의 lvalues를 캐스팅해야 그들이 올바른 유형을 가질 수 있도록 :

int main(void) { 
    uint8_t *a = foo(500, 'a', "hello"); 
    printf("%d, %c, %s\n", *(int *)a, *(char *)(a + sizeof(int)), *(char **)(a + sizeof(int) + sizeof(char))); 
    return 0; 
} 

:

을 읽기 위해서는
uint8_t *foo(int i, char c, char *s) { 
    uint8_t *r = malloc(sizeof i + sizeof c + sizeof s); 
    *(int *)r = i; 
    *(char *)(r + sizeof i) = c; 
    *(char **)(r + sizeof i + sizeof c) = s; 
    return r; 
} 

, 적절한 형식으로 캐스팅 할 필요가있다 @chux가 주석에서 지적했듯이 이것은 실제로 정의되지 않은 동작입니다.

// Get the smallest multiple of _Alignof(type) >= off 
#define GET_ALIGNED_OFFSET(off, type) ((off + _Alignof(type) - 1)/_Alignof(type) * _Alignof(type)) 

uint8_t *foo(int i, char c, char *s) { 
    size_t offset1 = GET_ALIGNED_OFFSET(sizeof i, char); 
    size_t offset2 = GET_ALIGNED_OFFSET(offset1 + sizeof c, char *); 
    uint8_t *r = malloc(offset2 + sizeof s); 
    *(int *)r = i; 
    *(char *)(r + offset1) = c; 
    *(char **)(r + offset2) = s; 
    return r; 
} 

비록 물론 @ 데이비드 컬린의 대답은 공학적인 관점에서 최적의 솔루션 남아있다 : ​​이전과 같은 정신, 표준 호환 코드를 얻으려면 C11 _Alignof 연산자를 사용하는 것이 가능하다.

+0

'* (char **) (r + sizeof i + sizeof c) = s;'는 음식물 요구 사항으로 인해 실패 할 수 있습니다. – chux

+0

@chux : 네, 고마워요! ;) 나는 나의 대답을 업데이트했다. – md5

+0

@chux가 : BTW 나는 표준 char''의 정렬 요구 사항이 1이라고 말할하지 않기 때문에'정의되지 않은 동작은, 또한 두 번째 문'* (숯불 *) (R +를 sizeof i)를 생각한다 (그것은 "단지입니다 약점 "). – md5

2

저는 가능한 한 컴퓨터가 수학을하도록하고 싶습니다.

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

struct multi_type { 
    int i; 
    char c; 
    char *s; 
}; 

struct multi_type *foo(int i, char c, char *s) { 
    struct multi_type *result = malloc(sizeof(*result)); 
    if (result == NULL) { 
     return NULL; 
    } 
    result->i = i; 
    result->c = c; 
    result->s = s; 
    return result; 
} 

int main(void) { 
    struct multi_type *a = foo(500, 'a', "hello"); 
    if (a) { 
     printf("%d, %c, %s\n", a->i, a->c, a->s); 
     free(a); 
    } 
    return 0; 
} 

출력

500, a, hello 

이 코드는 유지 보수가 용이하다 :이 상황에서 나는 struct 사용할 수 있습니다. struct multi_type의 유형 중 하나가 변경되거나 유형을 추가해야하는 경우 변경할 코드가 적습니다.

+0

사실, 내 질문에 뒤에있는 점은 구조체가하는 일을하지만, 높은 자유와 그것은 당신이 수학을 직접하고 싶은 질문의 제목이나 본문에서 분명하지 않다 – Naheel

+0

수학 나 자신을 수행하여 비슷한 일을하는 것입니다. 질문의 제목과 본문을보다 명확하게 업데이트하는 것을 고려해야합니다. 그러나 내 대답은 수작업을 수동으로하고 싶지 않은 사람들에게 유용 할 것입니다. –

+0

이 대답은 '* (CHAR **)의 동작과는 달리 정의가 S (R +는 sizeof 난를 sizeof C를 +), 휴대용 올;'. – chux