首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C联合定义

C联合定义
EN

Stack Overflow用户
提问于 2015-12-21 15:49:46
回答 2查看 166关注 0票数 0

在一个结构中,我需要一些空间,我可以放进一些东西。这个空间必须能够收集所有数据类型,所以我想定义一个联合。空间限制为n个字节(无符号字符)。

如何定义我的联合,以便它能够包含char、int、float等等?

我要这样做吗?

代码语言:javascript
复制
#define SIZE (128)
union {
        unsigned char uchar[SIZE];
        char schar[SIZE];
        unsigned int uint[SIZE/sizeof(unsigned int)];
        int sint[SIZE/sizeof(int)];
        float flt[SIZE/sizeof(float)];
        double dbl[SIZE/sizeof(double)];
}memory;

或者是否有可能只定义无符号字符数组的大小,然后自动定义int数组的大小?如果SIZE不能被4整除,会发生什么呢?

编辑:(与评论相关)

我想要构建类似于时间事件处理程序的东西。这意味着,我有一个包含一系列事件的结构。每个事件都有一个执行时间和一个相关的函数(作为指针存储)。当事件处理程序的计时器计数器与事件执行时间匹配时,我将调用相关函数。在我所知道的函数中,预期会使用wich参数,因此不需要保存标记值。问题是,事件是在函数中创建的,而且由于我不希望事件是静态的(以节省内存),所以我在事件处理程序中添加了一些内存(循环缓冲区),所有函数都可以在其中放入一些数据。每个事件都有一个变量,其中包含指向(第一个)数据的指针。数据的类型只是nativ数据类型,没有自己的结构。

这是我目前的代码:

启动时将调用startSystemClock()

executeSystemEvent()将由计时器1的中断服务例程通过设置sysEventHandler.execute=TRUE调用,while(1)-loop将检查此标志,然后调用executeSystemEvent()

代码语言:javascript
复制
// typedefs requird for timed events
typedef union __attribute__ ((packed)){
    int *i;     // pointer, where data is stored
    int value;  // if there is a pointer assigned, value differs from zero
}systemEventData_u;

typedef union __attribute__ ((packed)){
    int value;  // if there is a pointer assigned, value differs from zero
    void (*voidFct_noData)();
    void (*voidFct_data)(systemEventData_u);
}systemEventFct_u;

typedef struct{
    int time;
    unsigned int id;
    systemEventFct_u fct;
    systemEventData_u data;
}systemEvent_t;

#define SYSTEM_EVENT_HANDLER_BUFFER_SIZE    (10)
#define SYSTEM_EVENT_HANDLER_MEMORY_SIZE    (10)
typedef struct{
    unsigned int actualCnt;
    unsigned int nextEventCnt;
    unsigned char execute;
    systemEvent_t events[SYSTEM_EVENT_HANDLER_BUFFER_SIZE];
    systemEvent_t* write;
    // create some persistent memory usable by all functions
    int* memWrite;
    union __attribute__ ((packed)){
        unsigned char uchar[0];
        char schar[0];
        unsigned int uint[0];
        int sint[SYSTEM_EVENT_HANDLER_MEMORY_SIZE];
        float flt[0];
        double dbl[0];
    }memory;
}systemEventHandler_t;

void startSystemClock(){
    // initialize event handler
    sysEventHandler.actualCnt=0;
    sysEventHandler.nextEventCnt=-1;
    sysEventHandler.execute=FALSE;
    sysEventHandler.write=sysEventHandler.events;
    sysEventHandler.memWrite=sysEventHandler.memory.sint;
    unsigned int i=SYSTEM_EVENT_HANDLER_BUFFER_SIZE;
    systemEvent_t *ptr=sysEventHandler.events;
    while(i--){
        ptr->fct.value=0;
        ptr->data.value=0;
        ptr->time=0;
        ptr++;
    }
    // initialize timer 1
    TMR1 = 0x00;
    T1CON =  T3_OFF | T3_IDLE_CON | T3_GATE_OFF | T1_PS_1_8 | T1_SOURCE_INT;
    IPC1SET = (INTERRUPT_PRIOR_TIMER1 << _IPC1_T1IP_POSITION) | (INTERRUPT_SUB_PRIOR_TIMER1 << _IPC1_T1IS_POSITION);
    IFS0CLR = (1 << _IFS0_T1IF_POSITION);
    IEC0SET = (1 << _IEC0_T1IE_POSITION);
    PR1 = PR_TIMER1;
    T1CONSET = (1 << _T1CON_ON_POSITION);
    print_text("timer1 started\n\r");
}

void executeSystemEvent(){
    asm("di");
    int time=sysEventHandler.actualCnt;
    asm("ei");
    unsigned int i=SYSTEM_EVENT_HANDLER_BUFFER_SIZE;
    unsigned int nextEventCnt=-1;
    systemEvent_t *ptr=sysEventHandler.events;
    while(i--){
        // do not investigate, if there is no function pointer
        // no function pointer means no event action
        if(ptr->fct.value){
            if(time>=ptr->time){
                // execute function
                if(ptr->data.value){
                    (*ptr->fct.voidFct_data)(ptr->data);
                }else{
                    (*ptr->fct.voidFct_noData)();
                }
                ptr->fct.value=0;
            }
        }
        ptr++;
    }
    // determine next event
    // iterate again through whole queue to take added events into account also
    i=SYSTEM_EVENT_HANDLER_BUFFER_SIZE;
    ptr=sysEventHandler.events;
    while(i--){
        if(ptr->fct.value){
            // get execution time to determine next one
            if(ptr->time<nextEventCnt){
                nextEventCnt=ptr->time;
            }
        }
        ptr++;
    }
    asm("di");
    sysEventHandler.nextEventCnt=nextEventCnt;
    sysEventHandler.execute=FALSE;
    asm("ei");
}

void addSystemEvent(systemEvent_t event){
    // check, if this event will be the first event to execute
    asm("di");
    // get event execution time
    event.time+=sysEventHandler.actualCnt;
    // check, if it will be the next one to execute
    if(sysEventHandler.nextEventCnt>event.time){
        sysEventHandler.nextEventCnt=event.time;
    }
    asm("ei");
    *sysEventHandler.write=event;
    if(++sysEventHandler.write>=sysEventHandler.events+SYSTEM_EVENT_HANDLER_BUFFER_SIZE){
        sysEventHandler.write=sysEventHandler.events;
    }
}

int * storeSystemEventData(int data){
    int *ptr=sysEventHandler.memWrite;
    *ptr=data;
    if(++sysEventHandler.memWrite>=sysEventHandler.memory.sint+SYSTEM_EVENT_HANDLER_MEMORY_SIZE){
        sysEventHandler.memWrite=sysEventHandler.memory.sint;
    }
    return ptr;
}

要添加一个事件,我在任何函数中写入:

代码语言:javascript
复制
systemEvent_t event;
event.fct.voidFct_data=&enablePinChangeInterrupt_wrapper;
event.data.i=storeSystemEventData((int)PUSHBUTTON_CN_BIT);
event.time=10;
addSystemEvent(event);

我知道,storeSystemEventData-function还没有完成。但对于我的第一个目的,我只需要int,所以它可以工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-21 15:57:22

除了最大的数组外,不需要指定数组大小。只是越界进入其他类型。

代码语言:javascript
复制
#include "stdio.h"

union memory {
    unsigned char uchar[128];
    char schar[0];
    unsigned int uint[0];
    int sint[0];
    float flt[0];
    double dbl[0];
} ;

int main (void)
{
    union memory my_mem;
    my_mem.schar[5] = 'A';
    my_mem.schar[6] = 'B';
    my_mem.schar[7] = 'C';
    my_mem.schar[8] = 'D';

    printf ("%d\n", my_mem.uint[1]);
    return 0;
}

C不提供任何一种方式的数组边界检查,所以如果您试图访问内存对象之外的内存,那就太倒霉了。

票数 3
EN

Stack Overflow用户

发布于 2015-12-21 16:00:27

如果大小不能被4整除,会发生什么?

我假设您会问关于4的可分性的问题(与任何其他数字相反),因为它是一个常见的sizeof(int)。当SIZE被任何一个sizeof所不可分割时,最终会得到一个完全适合于size的最大数组,也就是说,这个数字将被截断。例如,当SIZE为4时,将sizeof(int)设置为13将产生

代码语言:javascript
复制
int sint[3];

换句话说,大小将被“四舍五入”(截断)。如果您更喜欢舍入,请使用以下表达式:

代码语言:javascript
复制
unsigned int uint[(SIZE+sizeof(unsigned int)-1)/sizeof(unsigned int)];

但是,请注意,uint[]数组的大小可能超过uchar的大小。

是否有可能只定义无符号字符数组的大小,然后自动定义int数组的大小?

您可以将union替换为char数组,并将void*指针转换为int*float*等。这将导致一种不同的语法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34399500

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档