2014-01-07 78 views
1

我有一个宏需要能够接受任意整数或指针类型并将它们转换为unsigned long long。这样做的自然方法就是投射,而且工作正常,但是默认的GCC警告会产生“从指针投射到不同大小的整数”,我想避免这种情况。自然的方式,以避免该警告是中间投,作为(unsigned long long)(uintptr_t)x,但是,这并不在我的情况下工作,因为:替代(无符号long long)强制转换无警告

  1. 它将截断,不适合在uintptr_t整数输入。
  2. 它会中断符号输入的正确转换,例如, -1可能会变成0xffffffff而不是0xffffffffffffffff

如果我有一个表达式(也许是做别致的使用?:运营商的),可以从整数类型区分指针,我可以把它分成两种情况,并首先应用(uintptr_t)塑像为指针输入,而不是整数。任何想法都可以运作?

+2

(真的很可怕,只为了疯狂):'_Generic'每种整数类型都有大小写。 –

+0

@StephenCanon:公平地说,通过应用执行整数升级的操作,可以使这一点变得更加可怕,但这对于应用于指针也是安全的,从而排除了所有比“int”更低级别的操作。 '1?x:0'应该可以工作。 –

+1

甚至更​​好:应用'1?x:(uintmax_t)0',为'_Generic'的目的强制任何整数类型为'uintmax_t',同时保持指针类型不变。不幸的是,这仍然需要C11的支持,这并不普遍。 –

回答

1

这似乎是它应该工作:

sizeof (1?(x):(unsigned long long)0) < sizeof (unsigned long long) 
    ? (uintptr_t)(x) 
    : (unsigned long long)(x) 

案例:

  1. x具有任何整数类型。然后1?(x):(unsigned long long)0的类型为unsigned long long,因此取第二个分支,直接转换为unsigned long long
  2. x具有指针类型,指针类型小于unsigned long long。然后1?(x):(unsigned long long)0有原始的指针类型,并采取第一个分支,通过uintptr_t
  3. x有指针类型和指针类型是相同的大小(或更大,但我会假设不会发生)为unsigned long long。然后第二个分支被采取,但是没有任何警告要发出。

我不清楚GCC是否可以避免针对死码(不会被采用的分支)发出警告,但如果没有,也许__builtin_choose_expr是一个解决方案。