在一个结构中,我需要一些空间,我可以放入一些东西。这个空间必须能够收集所有数据类型,所以我想定义一个联合。空间限制为n个字节(unsigned char)。
我如何定义我的联合,以便它可以包含char,int,float等?
我有这样做吗?
#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;
或者是否有可能只定义unsigned char数组的大小,然后自动定义int数组的大小?如果SIZE
不能被4整除,会发生什么?
编辑:(与评论相关)
我想构建类似定时事件处理程序的东西。这意味着,我有一个包含事件数组的结构。每个事件都有一个执行时间和一个相关的函数(存储为指针)。当事件处理程序的计时器计数器与事件执行时间匹配时,我调用相关函数。在我将要知道的函数中,期望参数,所以我不需要保存标记值。问题是,事件是在一个功能中创建的,因为我不想让事件静态(为了节省内存),我在我的事件处理程序中添加了一些内存(环形缓冲区),其中所有函数都可以放入一些数据。每个事件都有一个包含指向(第一个)数据的指针的变量。数据类型只是nativ数据类型,没有自己的结构。
这是我目前的代码:
startSystemClock()
将在启动时调用
executeSystemEvent()
和sysEventHandler.execute=TRUE
- 循环检查此标志然后调用while(1)
来调用 executeSystemEvent()
// 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;
}
要添加事件,我会在任何函数中编写:
systemEvent_t event;
event.fct.voidFct_data=&enablePinChangeInterrupt_wrapper;
event.data.i=storeSystemEventData((int)PUSHBUTTON_CN_BIT);
event.time=10;
addSystemEvent(event);
我知道,storeSystemEventData
- 功能尚未完成。但是对于我的第一个目的,我只需要int,所以它有效。
答案 0 :(得分:3)
除最大值外,您无需指定数组大小。只是越界访问其他类型。
#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不提供任何方式的数组边界检查,所以如果你试图访问内存对象之外的内存,那你就不走运了。
答案 1 :(得分:2)
如果SIZE不能被4整除,会发生什么?
我假设您通过4(而不是任何其他数字)提出有关可分性的问题,因为它是一个常见的sizeof(int)
。当SIZE
不能被任何sizeof
不可分割时,最终会得到完全适合size
内部的最大数组,即该数字将被截断。例如,当SIZE
为4时,将13
设置为sizeof(int)
会产生
int sint[3];
换句话说,尺寸将是&#34;向下舍入&#34; (截)。如果您更喜欢四舍五入,请使用以下表达式:
unsigned int uint[(SIZE+sizeof(unsigned int)-1)/sizeof(unsigned int)];
但请注意,uint[]
数组的大小可能超过uchar
的大小。
是否有可能只定义unsigned char数组的大小,然后自动定义int数组的大小?
您可以将union
替换为char
个数组,并将void*
指针转换为int*
,float*
等。这将导致不同的语法。