user-0 提问: c如何在枚举和变量间建立key value 关系

回复:
user: user-1
content: 引用 7 楼 u012560967 的回复:[quote=引用 3 楼 u012560967 的回复:]  void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } } 写错了个地方。。。 另， 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。赵老师的意思就是，我写300多个case是可以的么？？[/quote] 就算你写30000个case，没准仍然比map效率高。

user: user-2
content: 引用 12 楼 u012560967 的回复:[quote=引用 9 楼 paschen 的回复:] [quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦，可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组，如何通过id（而非地址）进行赋值和访问呢？ 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。 谢谢，说的很对，这个帖子就是单纯的想对结构体成员赋值进行理解，只有用不同途径完成相同功能，理解的才能更深刻不是么？[/quote]  #define FIELD_OFFSET(type, field)    ((LONG)(LONG_PTR)&(((type *)0)->field))  type结构体类型名，field该结构体中的成员名字

user: user-0
content: 引用 9 楼 paschen 的回复:[quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦，可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组，如何通过id（而非地址）进行赋值和访问呢？ 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。 谢谢，说的很对，这个帖子就是单纯的想对结构体成员赋值进行理解，只有用不同途径完成相同功能，理解的才能更深刻不是么？

user: user-1
content: 不要低估编译器生成Release版switch语句时选择优化算法的智商。 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

user: user-1
content: 引用 7 楼 u012560967 的回复:[quote=引用 3 楼 u012560967 的回复:]  void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } } 写错了个地方。。。 另， 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。赵老师的意思就是，我写300多个case是可以的么？？[/quote] Why not !? char* TransOperType(int nOperType) {     switch (nOperType) {     case OPER_UNKNOWN:              return "UNKNOWN";     case OPER_PLAY:                 return "PLAY";     case OPER_RECORD:               return "RECORD";     case OPER_GETDIG:               return "GETDIG";     case OPER_ACCEPTCALL:           return "ACCEPTCALL";     case OPER_ANSWERCALL:           return "ANSWERCALL";     case OPER_MAKECALL:             return "MAKECALL";     case OPER_DROPCALL:             return "DROPCALL";     case OPER_SETBILLING:           return "SETBILLING";     case OPER_SENDMOREINFO:         return "SENDMOREINFO";     case OPER_DLCACHE:              return "DLCACHE";     case OPER_DLMEM:                return "DLMEM";     case OPER_STOPCH:               return "STOPCH";     case OPER_PUTEVT:               return "PUTEVT";     case OPER_SYSNOTIFY:            return "SYSNOTIFY";     case OPER_CST:                  return "CST";     case OPER_GETTRCOUNT:           return "GETTRCOUNT";     case OPER_XOIP_SETRESATTR:      return "OPER_XOIP_SETRESATTR";     case OPER_XOIP_GETRESATTR:      return "OPER_XOIP_GETRESATTR";     case OPER_XOIP_GETSSINFO:       return "OPER_XOIP_GETSSINFO";     case OPER_XOIP_STARTMEDIA:      return "OPER_XOIP_STARTMEDIA";     case OPER_XOIP_STOP:            return "OPER_XOIP_STOP";     case OPER_XOIP_SENDDIGITS:      return "OPER_XOIP_SENDDIGITS";     case OPER_XOIP_ENABLEEVENT:     return "OPER_XOIP_ENABLEEVENT";     case OPER_XOIP_DISABLEEVENT:    return "OPER_XOIP_DISABLEEVENT";     case OPER_XOIP_RECEIVEDIGITS:   return "OPER_XOIP_RECEIVEDIGITS";     case OPER_XOIP_SENDRFC2833:     return "OPER_XOIP_SENDRFC2833";     case OPER_SENDCPG:              return "OPER_SENDCPG";     case OPER_CALLPROCEEDING:       return "OPER_CALLPROCEEDING";     case OPER_CALLPROGRESS:         return "OPER_CALLPROGRESS";     case OPER_SETUPACK:             return "OPER_SETUPACK";     case OPER_SIP_SENDREINVITE:     return "OPER_SIP_SENDREINVITE";     case OPER_SIP_SENDREINVITEACK:  return "OPER_SIP_SENDREINVITEACK";     case OPER_SIP_SENDREGISTER:     return "OPER_SIP_SENDREGISTER";     case OPER_XOIP_SWITCH_VF:       return "OPER_XOIP_SWITCH_VF";     case OPER_SIP_SENDINFO:         return "OPER_SIP_SENDINFO";     case OPER_SIP_SENDINFOACK:      return "OPER_SIP_SENDINFOACK";     case OPER_NR_SCROUTE:           return "OPER_NR_SCROUTE";     case OPER_NR_SCUNROUTE:         return "OPER_NR_SCUNROUTE";     case OPER_SIP_SENDREGISTERACK:  return "OPER_SIP_SENDREGISTERACK";     case OPER_SIP_SENDTRYING:       return "OPER_SIP_SENDTRYING";     case OPER_DT_SETTSSIG:          return "OPER_DT_SETTSSIG";     case OPER_DT_GETTSSIG:          return "OPER_DT_GETTSSIG";     case OPER_SIP_SENDSUBSCRIBE:    return "OPER_SIP_SENDSUBSCRIBE";     case OPER_SIP_SENDNOTIFYACK:    return "OPER_SIP_SENDNOTIFYACK";     case OPER_GETCONFENERGY:        return "OPER_GETCONFENERGY";     case OPER_ESTCONF:              return "OPER_ESTCONF";     case OPER_ADDCONF:              return "OPER_ADDCONF";     case OPER_REMCONF:              return "OPER_REMCONF";     case OPER_DELCONF:              return "OPER_DELCONF";     case OPER_SETCDE:               return "OPER_SETCDE ";     case OPER_ESTCONF_EX:           return "OPER_ESTCONF_EX";     case OPER_ADDCONF_EX:           return "OPER_ADDCONF_EX";     case OPER_REMCONF_EX:           return "OPER_REMCONF_EX";     case OPER_SETCDE_EX:            return "OPER_SETCDE_EX";     case OPER_SETLMASKEX:           return "OPER_SETLMASKEX";     case OPER_SS7_SENDEXT:          return "OPER_SS7_SENDEXT";     case OPER_FXS_SEND:             return "OPER_FXS_SEND";     case OPER_FXS_RECV:             return "OPER_FXS_RECV";     case OPER_MO_SETHOOK:           return "OPER_MO_SETHOOK";     case OPER_MO_DIAL:              return "OPER_MO_DIAL";     case OPER_MS_GENRING:           return "OPER_MS_GENRING";     case OPER_MS_WTRING:            return "OPER_MS_WTRING";     case OPER_AG_SENDTONE:          return "OPER_AG_SENDTONE";     case OPER_RECVFSK:              return "OPER_RECVFSK";     case OPER_SENDFSK:              return "OPER_SENDFSK";     case OPER_SIP_RECVUPDATE:       return "OPER_SIP_RECVUPDATE";     case OPER_SIP_SENDUPDATE:       return "OPER_SIP_SENDUPDATE";     case OPER_SIP_RECVUPDATEACK:    return "OPER_SIP_RECVUPDATEACK";     case OPER_SIP_SENDUPDATEACK:    return "OPER_SIP_SENDUPDATEACK";     case OPER_SIP_RECVACK:          return "OPER_SIP_RECVACK";     case OPER_SIP_SENDACK:          return "OPER_SIP_SENDACK";     case OPER_SIP_RECVPRACK:        return "OPER_SIP_RECVPRACK";     case OPER_SIP_SENDPRACK:        return "OPER_SIP_SENDPRACK";     case OPER_SIP_SENDPRACKACK:     return "OPER_SIP_SENDPRACKACK";     case OPER_SIP_RECVPRACKACK:     return "OPER_SIP_RECVPRACKACK";     default: break;     }     return "UNKNOWN"; }

user: user-2
content: 引用 2 楼 paschen 的回复:建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数

user: user-0
content: 引用 3 楼 u012560967 的回复: void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } } 写错了个地方。。。 另， 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。赵老师的意思就是，我写300多个case是可以的么？？

user: user-0
content: void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr)/sizeof(M); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } }

user: user-1
content: swith case  这个世界上唯一不变的就是变化。请拥抱变化。

user: user-0
content: 引用 4 楼 u012560967 的回复:[quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系 谢谢，这样的确是我需要的，但是用偏移量会不会有危险，结构体在内存中的地址是不是因为内存对齐导致不连续，如果使用这样的方法，需要注意什么呢，需不需要对结构体成员位置进行调整呢？[/quote] sorry，忘问了一句，这样写的话，是不是每次需要变更结构体的时候，都需要变更对应的枚举吧。

user: user-0
content: 引用 2 楼 paschen 的回复:建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系 谢谢，这样的确是我需要的，但是用偏移量会不会有危险，结构体在内存中的地址是不是因为内存对齐导致不连续，如果使用这样的方法，需要注意什么呢，需不需要对结构体成员位置进行调整呢？

user: user-0
content: 引用 1 楼 user-3 的回复:如果结构体中的变量长度都相同，可以使用偏移量直接赋值 谢谢1楼的回答，用偏移量赋值的确是我期望的那样，但是由于结构体中成员类型有不同，所以需要用3楼的方法建立一个枚举或者数组记录对应成员位置，由于我之前用的Enum E {A,B,C,D,E,F,G,H,I,J,K...... }为协议中的ID值，所以需要建立一个 typedef struct Map {    int id;    int addr; }M; Enum E {A,B,C,D,E,F,G,H,I,J,K...... } Enum Ad {   ONE = 0,TWO = 4... }; M arr[1000] = { {A, ONE}, {B, TWO}, {C,THREE}... };  当我用的时候  void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } }

user: user-0
content: 引用 13 楼 paschen 的回复:[quote=引用 12 楼 u012560967 的回复:] [quote=引用 9 楼 paschen 的回复:] [quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦，可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组，如何通过id（而非地址）进行赋值和访问呢？ 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。 谢谢，说的很对，这个帖子就是单纯的想对结构体成员赋值进行理解，只有用不同途径完成相同功能，理解的才能更深刻不是么？[/quote]  #define FIELD_OFFSET(type, field)    ((LONG)(LONG_PTR)&(((type *)0)->field))  type结构体类型名，field该结构体中的成员名字[/quote] 不错不错，多谢指教了~也感谢1楼和一直都语重心长的赵老师~

user: user-2
content: 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系

user: user-3
content: 如果结构体中的变量长度都相同，可以使用偏移量直接赋值