2014-12-13 2 views
3

구조체를 사용하여 uint8_t 배열을 초기화 할 수 있습니까?구조체를 사용하여 C 배열 초기화

#define BIGGER_THAN_STRUCT 1024  

struct Device { 
    uint32_t address; 
    uint32_t id; 
}; 

const uint8_t bytes[BIGGER_THAN_STRUCT] = (struct Device) { 
    .address = 123, 
    .id = 456, 
}; 

내가 바이트 배열에 쓸 내용의 쉬운 오버레이보기를 얻을이 그것을하고 싶은 이유는 내가 무엇을 달성하고자하는

유사한 무언가이다. 간단히 말해서 구조에 의해 표시되는 정보에 필요한 첫 번째 바이트와의 쉬운 인터페이스가 필요합니다.

그게 불가능하면, 가장 가까운 것은 무엇인가? 내가 구조화 된 바이트의 가방과 함께 일해야 할 때

+4

첫 번째. 왜 그걸하고 싶니? –

+0

그래서 구조체 값을 배열에 넣기 만하면됩니까? – Nit

+1

이유가있는 게시물을 업데이트했습니다. 나는 더 큰 메모리 덩어리를 예약하지만 단순한 방법으로 구조체에 사용 된 부분을 초기화하고자하는 임베디드 시스템을 사용하고 있습니다. –

답변

0

이, 일반적으로 다음

static const uint8_t buffer[BIGGER_THAN_STRUCT] = { 
    0x7b, 0x00, 0x00, 0x00, 
    0xc8, 0x01, 0x00, 0x00 
}; 
+0

테스트하고 싶다면'memcpy (& device, buffer, sizeof (struct Device));'를 실행하고 값이 올바른지 프린트하십시오. –

0

그것을 할 것입니다, 나는 블록에 좀 더 높은 수준의 인터페이스를 제공하는 "보기"구조체/클래스를 생성 기억. 수동 포인터 산술은 일반적으로 너무 오류가 반복되기 쉽습니다. "메모리 뷰"구조를 만들고이를 단위 테스트하십시오.

struct memory_view { 
    uint32_t *addr; 
    uint32_t *id; 
}; 

void view_init(struct memory_view *view, void *buf, size_t bufsz) { 
    // TODO: validate buffer size using bufsz here 
    view->addr = (uint32_t*)buf; 
    view->id = (uint32_t*)(buf + sizeof(uint32_t)); 
} 

struct memory_view view; 
uint8_t buffer[LARGE_NUMBER]; 
view_init(&view, buffer, LARGE_NUMBER); 

*view->addr = 0xDEADBEEF; 
*view->id = 0xCAFEBABE; 

구조체가 초기화되어 일부 메모리 영역에있는 다른 하드웨어 레지스터에 액세스 할 때 비슷한 기술을 볼 수 있습니다. 또한 버퍼 포인터를 얻을 수

는 구조화하고 구조했다으로이 메모리 블록을 사용하려고 캐스팅. 할 수는 있지만, 메모리 정렬은 당신을 심하게 괴롭힐 수 있습니다. 이러한 코드는 컴파일러 및 시스템 아키텍처에 따라 작동하거나 작동하지 않을 수 있습니다.

+0

void view_init (struct memory_view * view, void * buf, size_t bufsz)를 선언하지만'view_init (& view, buffer)'를 호출하십시오. 무엇을 성취하려고합니까? –

+0

오타입니다. 아무것도 더. – ezaquarii

+0

그게 내가 지적한거야. –

0

난 당신이 어쩌면 사본이 당신이 필요로 정확히 무엇을 필요 b_sample로이없는 경우에도, 그런 일을하고 싶은 생각합니다.

#include <stdio.h> 
#include <stdint.h> 

typedef struct Device dev; 
struct Device { 
    uint32_t address; 
    uint32_t id; 
}; 

int main(void) { 
    //create an instance `sample.address=123` and `sample.id=456` 
    dev sample = (dev) { 123, 456 }; 
    //convert dev pointer to byte pointer, so you loop through bytes 
    uint8_t* b_sample = (uint8_t *)(&sample); 
    //buffer for copy 
    uint8_t* bytes[1024]; 

    int size = (int)(sizeof(dev)/sizeof(uint8_t)), i; 
    for(i = 0; i < size; i++) { 
     bytes[i] = b_sample[i]; 
     //see what values you copy 
     printf("%x ", bytes[i]); 
    } 

    return 0; 
} 

데모 : 당신이 uint16_t 세그먼트로 구조체를 나눌 경우 uint8_t byte[] 배열을 사용하는 대신이 모든 uint8_tuint16_t

0

http://codepad.org/wE8dbBV1

가 안전하게 교체 할 수 있습니다. 각 addrid에 대해 bitfield을 사용하는 구조체를 사용할 수도 있습니다. 더 편리 할 수도 있지만, 오프셋 정보를 유지하는 쉬운 방법을 제공합니다. addr/id 쌍.

구조체 유형 지정 초기화 자uint8_t byte 배열로 채우기 위해 직접 사용할 수있는 방법이 없다고 생각합니다. 가장 가까운 전체 초기화는 memcpy 일 것이라고 생각합니다. 나는 아래 예제에서 그것을 포함시켰다. 참고memcpy으로 uint8_t byte 배열을 작성하지 못하도록 아무것도 없지만, 당신은 정확하게 어떤 주어진 요소 중 하나 addr 또는 id에 주어진 바이트를 가리 키도록 uint8_t byte 배열 내에서 offset을 추적 할 수 있습니다. 이것은 비트 필드가 일을 좀 더 쉽게 만들어주는 곳입니다. 당신은 a1..4b1..4는 각각 각 addrid, 내 바이트 인으로 struct Device 인덱스와 uibitfield 인덱스 사이 일대일 상관 관계를 얻는다.

uint8_t 배열을 사용하는 버전이이 버전 아래에 표시됩니다. 여기

struct Device의 배열에서 테스트 데이터 짧은 예입니다

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

typedef struct      /* bitfield corresponding to struct Device */ 
{ 
    unsigned int a1 : 8, 
        a2 : 8, 
        a3 : 8, 
        a4 : 8; 

    unsigned int b1 : 8, 
        b2 : 8, 
        b3 : 8, 
        b4 : 8; 

} uibitfield; 

struct Device {      /* original struct Device */ 
    uint32_t addr; 
    uint32_t id; 
}; 

int main() { 

    /* test data in an array of struct Device */ 
    struct Device dev[] = { {0x4009f0, 0}, {0x4009f1, 1}, {0x4009f2, 2}, {0x4009f3, 3}, 
          {0x4009f4, 4}, {0x4009f5, 5}, {0x4009f6, 6}, {0x4009f7, 7}, 
          {0x4009f8, 8}, {0x4009f9, 9}, {0x4009fa, 10}, {0x4009fb, 11}, 
          {0x4009fc, 12}, {0x4009fd, 13}, {0x4009fe, 14}, {0x4009ff, 15}, 
          {0x400a00, 16}, {0x400a01, 17}, {0x400a02, 18}, {0x400a03, 19} }; 

    int it = 0;        /* general iterator */ 
    size_t sz = sizeof (dev)/sizeof (*dev); /* size of array */ 

    /* create validate and fill bitfield array */ 
    uibitfield *bytes = calloc (sz, sizeof (*bytes)); 
    if (!bytes) { 
     fprintf (stderr, "error: allocation failed.\n"); 
     return 1; 
    } 
    memcpy (bytes, dev, sz * sizeof (dev)); 

    /* print bytes in each addr & id in dev */ 
    for (it = 0; it < sz; it++) 
     printf ("\n addr[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n id[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", 
       it, (bytes + it)->a1, (bytes + it)->a2, (bytes + it)->a3, (bytes + it)->a4, 
       it, (bytes + it)->b1, (bytes + it)->b2, (bytes + it)->b3, (bytes + it)->b4); 

    printf ("\n"); 

    return 0; 
} 

출력 :

$ ./bin/memview 

    addr[ 0]: 0xf0, 0x09, 0x40, 0x00 
    id[ 0]: 0x00, 0x00, 0x00, 0x00 

    addr[ 1]: 0xf1, 0x09, 0x40, 0x00 
    id[ 1]: 0x01, 0x00, 0x00, 0x00 

    addr[ 2]: 0xf2, 0x09, 0x40, 0x00 
    id[ 2]: 0x02, 0x00, 0x00, 0x00 

    addr[ 3]: 0xf3, 0x09, 0x40, 0x00 
    id[ 3]: 0x03, 0x00, 0x00, 0x00 

    addr[ 4]: 0xf4, 0x09, 0x40, 0x00 
    id[ 4]: 0x04, 0x00, 0x00, 0x00 

    (snip) 

참고 :이이었다 불분명 사용이 얼마나/struct Device을 채우고 stuct Device에있는 데이터에서 처음 들었던 부분을 얼마만큼 보았는지 알 수 있습니다. 따라서 이는 데이터보기의 예입니다.

당신은`uint8_t 배열을 사용하려는 경우, 필요한 변화가 최소화 :

/* using a uint8_t byte array */ 
    uint8_t *bytearr = calloc (sz * 4, sizeof (*bytearr)); 
    if (!bytearr) { 
     fprintf (stderr, "error: allocation failed.\n"); 
     return 1; 
    } 
    memcpy (bytearr, dev, sz * sizeof (dev)); 

    /* print bytes in each addr & id in dev using uint8_t array */ 
    for (it = 0; it < sz * 4; it+=8) 
     printf ("\n addr[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n id[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", 
       it, bytearr[it], bytearr[it+1], bytearr[it+2], bytearr[it+3], 
       it, bytearr[it+4], bytearr[it+5], bytearr[it+6], bytearr[it+7]); 

출력이 같은

하는 uint8_t 바이트 배열을 사용하여


0

이 작업 수행 대상 :

#define BIGGER_THAN_STRUCT 1024  

struct Device { 
    uint32_t address; 
    uint32_t id; 
}; 

struct DeviceAndData { 
    struct Device d; 
    char filler[BIGGER_THAN_STRUCT - sizeof(Device)]; 
}; 
const struct DeviceAndData bytes_pre = { .d = { .address = 123, .id = 456 } }; 
const uint8_t* bytes = (uint8_t*)&bytes_pre; 

트릭을 수행 하시겠습니까? : 데이터 유형을 오버레이 C에서

3

표준 방법을 사용하는 조합입니다 :

#include <stdio.h> 
    #include <stdint.h> 
    #define BIGGER_THAN_STRUCT 1024  

    struct Device { 
     uint32_t address; 
     uint32_t id; 
    }; 

    union Memory { 
      uint8_t bytes[BIGGER_THAN_STRUCT]; 
      struct Device devices[BIGGER_THAN_STRUCT/sizeof(struct Device)]; 
    }; 

    const union Memory memory = { 
      .devices = { 
        { .address = 123, .id = 30 }, 
        { .address = 111, .id = 89 } 
      } 
    }; 

    int main(void) 
    { 
      unsigned i; 

      for (i = 0; i < 16; i++) 
        printf("%d ", memory.bytes[i]); 

      putchar('\n'); 

      return 0; 
    } 

,

$ ./a 
123 0 0 0 30 0 0 0 111 0 0 0 89 0 0 0 
1

옆에 여기 hdantehttps://stackoverflow.com/a/27462808/694576에 의해 제안 된 (A union을 통해이 접근) 대신 시도해보십시오.

const uint8_t bytes[BIGGER_THAN_STRUCT] = (struct Device) { 
    .address = 123, 
    .id = 456, 
}; 

는 신속하고 더러운 수행

uint8_t bytes[BIGGER_THAN_STRUCT] = {0}; 
*((struct Device *) bytes) = ((struct Device) { 
    .address = 123, 
    .id = 456, 
}); 

이상 할 일 :

struct Device dev = { 
    .address = 123, 
    .id = 456, 
}; 

uint8_t bytes[BIGGER_THAN_STRUCT] = {0}; 

... 

size_t size_dev = sizeof dev; 
memcpy(bytes, &dev, size_dev); 

는 그 다음 size_dev - 1 번째 요소까지 배열 bytes을 검사합니다.