错误“不能出现在g ++中的常量expression式中”,而不是gcc中

98 static inline int set_hw_br(pid_t tracee, dr7_t *pdr7, void *addr, int dr_index) 99 { 100 errno = 0; 101 printf("LINE = %d <pid> %d, dr_index= %d addr=%u \n",__LINE__, tracee, dr_index, addr); 102 //if (ptrace(PTRACE_POKEUSER, tracee, offsetof(struct user, u_debugreg[dr_index]), addr)) 103 if (ptrace(PTRACE_POKEUSER, tracee, offsetof(struct user, u_debugreg[dr_index]), addr)) 104 { 105 int ii = errno; 106 printf("MKH: 22 errno = %d\n", ii); 107 ptrace(PTRACE_DETACH, tracee, 0, 0); 108 return -1; 109 } 110 else 111 printf("PTRACE_POKEUSER passed...\n"); 

上面的代码(主代码的一部分)被成功地编译在GCC编译器中。 但是,通过G ++编译时,会error: 'dr_index' cannot appear in a constant-expression错误: error: 'dr_index' cannot appear in a constant-expression在第103行error: 'dr_index' cannot appear in a constant-expression中。set_hw_br从另一个函数中调用。

任何想法为什么这在g ++失败?

谢谢。

宏的offsetof要求成员指定 offsetof必须产生一个地址常量(C11 7.19 / 3):

 offsetof(type, member-designator) 

它从结构的开头(由type 指定 )扩展成一个整型常量表达式,该表达式的类型为size_t ,其值是以字节为单位的结构成员(由member-designator指定)。 类型和成员代号应该是给定的

 static type t; 

那么表达式&(t. -designator )计算结果就是一个地址常量。 (如果指定的成员是位字段,则行为是未定义的。)

在你的代码中, t.u_subreg[dr_index]不是一个常量,因为dr_index不是一个常量。

GCC用一个编译器实现offsetof ,所以在offsetof表达式中允许的取决于GCC的内在规则。 作为标准的扩展,GCC C前端允许一个非常量表达式作为输入,并产生一个非常量的结果。 C ++前端不允许它,给出错误告诉你dr_index不能在那里使用。

您可以将offsetof表达式更改为仅使用常量:

 offsetof(struct user, u_debugreg[0]) 

那么你可以添加索引,其中T是数组中的类型u_debugreg

 offsetof(struct user, u_debugreg[0]) + sizeof(T)*dr_index 

(这假定u_debugreg是一个实际的数组,而不是一个指针)。