错误"不能出现在g ++中的常量表达式中"但不能出现在gcc中

1 c++ linux gcc g++

 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");
Run Code Online (Sandbox Code Playgroud)

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

知道为什么这个g ++失败了吗?

谢谢.

Jon*_*ely 5

offsetof宏要求成员指示符具有产生一个地址常量(C11 7.19/3):

offsetof(type, member-designator)
Run Code Online (Sandbox Code Playgroud)

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

static type t;
Run Code Online (Sandbox Code Playgroud)

然后表达式&(t.member-designator)求值为地址常量.(如果指定的成员是位字段,则行为未定义.)

在你的代码中,t.u_subreg[dr_index]不是常量,因为dr_index它不是常数.

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

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

offsetof(struct user, u_debugreg[0])
Run Code Online (Sandbox Code Playgroud)

然后你可以为它添加索引,T数组中的类型在哪里u_debugreg:

offsetof(struct user, u_debugreg[0]) + sizeof(T)*dr_index
Run Code Online (Sandbox Code Playgroud)

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