C++ 面试题 :如何用编译错误取代运行时断言( assert)

110 views
Skip to first unread message

Roc Zhang

unread,
Aug 27, 2009, 6:04:15 AM8/27/09
to TopLanguage
见到一道C++面试题,半天没思路,请大家帮助一下有什么好的办法?


问如何把下面的assert 换掉,让在编译的时候,编译器提示错误。

void Convert( int source, char value[4])
{
assert( sizeof(int) == sizeof( value);

*(int*)value = source;
}

Xihe Yu

unread,
Aug 27, 2009, 6:13:04 AM8/27/09
to pon...@googlegroups.com
static_assert

Best Regards!

-
KrzyCube | 方块


2009/8/27 Roc Zhang <zhyg...@gmail.com>

Shuo Chen

unread,
Aug 27, 2009, 6:17:33 AM8/27/09
to TopLanguage
char size_should_be_the_same[sizeof(int) == sizeof(value) ? 1 : -1];

Dave Swen

unread,
Aug 27, 2009, 6:20:22 AM8/27/09
to pon...@googlegroups.com

template<size_t x> Foo;
template<>Foo<0>{};

Foo<sizeof(int)-sizeof(value)> bar;

Xihe Yu wrote:
> static_assert
>
> Best Regards!
>
> -
> KrzyCube | 方块
>
>

> 2009/8/27 Roc Zhang <zhyg...@gmail.com <mailto:zhyg...@gmail.com>>

Dave Swen

unread,
Aug 27, 2009, 6:22:19 AM8/27/09
to pon...@googlegroups.com
感觉你这个总是失败吧?
[]里的值要求编译时确定,而三元操作符的结果是运行时决定的

Shuo Chen

unread,
Aug 27, 2009, 6:30:35 AM8/27/09
to TopLanguage
你试过吗?
这是从C语言里就有的技巧,我们用了很久了。

Dave Swen

unread,
Aug 27, 2009, 6:38:55 AM8/27/09
to pon...@googlegroups.com
所以说感觉。。。。。然后就真试了一下,确实可以。。。。

dave@gentoo-on-x200s ~/devel/test $ g++ test.cc
test.cc: In function ‘int main(int, char**)’:
test.cc:5: error: size of array ‘size_should_be_the_same’ is negative

Fei Yan

unread,
Aug 27, 2009, 8:21:39 AM8/27/09
to pon...@googlegroups.com
这个方法在《Imperfect C++》第一章里边讲述的很清楚,确实很优雅实用;印象中大概还有一些更炫一点的

模板的方法,打印出来的一大堆信息很容易让人不知所谓

如果允许引入Boost,static_assert也是个不错的选择,还有很多不同的场景可用:
http://www.boost.org/doc/libs/1_39_0/doc/html/boost_staticassert.html

2009/8/27 Dave Swen <dave...@gmail.com>

唐正华

unread,
Aug 27, 2009, 1:06:29 PM8/27/09
to pon...@googlegroups.com
学习并使用了C++这么久,见到如此讨论,还是感觉很新鲜,C++的魅力或许就在于此吧
--~--~---------~--~----~------------~-------~--~----~
历史上的今天:http://dzshare.cn
新蛋校园代理:代下单全国免运费,直享团购价。(https://sites.google.com/site/isharedsite/newegg-quan
--~--~---------~--~----~------------~-------~--~----~


2009/8/27 Fei Yan <skyscr...@gmail.com>

Zhiming G

unread,
Aug 27, 2009, 1:48:50 PM8/27/09
to pon...@googlegroups.com
如果遇上有问题的编译器, 可以这么写(c/c++)

#define static_assert(x) do switch (0) { \
case ((int)x): {char _sa[-!(x)];} \
} while (0)


static_assert(sizeof(int)=sizeof(v)); // pass
static_assert(1.0f) // pass

int a = 4;
static_assert(a==sizeof(int)); // error



2009/8/27 Dave Swen <dave...@gmail.com>

Zhiming G

unread,
Aug 27, 2009, 2:50:10 PM8/27/09
to pon...@googlegroups.com
语法里面还有很多必须是常量或者必须是整数的地方呀, 比如这个~

#define static_assert(x)do{typedef enum __a{__b=-!(x)}__c[__b];}while(0)

2009/8/28 Zhiming G <gao...@gmail.com>

qing yin

unread,
Aug 27, 2009, 9:55:09 AM8/27/09
to pon...@googlegroups.com
sizeof就是编译期计算吧,那么【】中的就是个常量表达式咯,也在编译期计算了
在 09-8-27,Dave Swen<dave...@gmail.com> 写道:

Lai Jiangshan

unread,
Aug 27, 2009, 10:21:04 PM8/27/09
to pon...@googlegroups.com
编译时断言真的有很多技巧, 呵呵, 从上面看到一些我不知道的...

但为什么我觉得楼主的问题在责任在assert(), assert()本身应该做到这一点.

如果assert()做不到, 应该改一下assert() 的实现, 而不是换掉那一行

#define assert(x) \
{\
if (compiletime_const(x))\
static_assert(x);\
else\
runtime_assert(x);\
} while (0)

PS: 我只知道怎样在gcc实现compile_time_const(), 其他编译器完全不知道...

Ian Yang

unread,
Aug 27, 2009, 10:26:11 PM8/27/09
to pon...@googlegroups.com
瞄了一眼boost static assert, 要实现个跨平台的,适应不同平台的宏来实现这个功能还真是麻烦啊
-------
Sincerely, Ian Yang




2009/8/27 qing yin <qing1...@gmail.com>

bronco

unread,
Aug 27, 2009, 10:43:56 PM8/27/09
to pon...@googlegroups.com
loki里大量使用此手法;

rockeet

unread,
Aug 28, 2009, 1:45:15 AM8/28/09
to TopLanguage
char for_static_assert[1/(sizeof(int)==sizeof(value)];

Chunyuan Ge

unread,
Aug 28, 2009, 2:50:48 AM8/28/09
to pon...@googlegroups.com
en LOki里面有个这样的类似的实现:
#define LOKI_STATIC_CHECK(expr, msg) \
{ Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }

2009/8/28 bronco <renfe...@gmail.com>
loki里大量使用此手法;

Roc Zhang

unread,
Aug 28, 2009, 9:56:48 AM8/28/09
to pon...@googlegroups.com, hhy...@gmail.com, qing1...@gmail.com, renfe...@gmail.com, roc...@gmail.com, krzy...@gmail.com, eag...@gmail.com
2009/8/28 Chunyuan Ge <hhy...@gmail.com>:

大体上分两类: 一类是利用C++ 里面编译常量: 比如数组下表不能为0, 枚举为整形;
第二类: 利用模板特化,编译自己根据条件展开。
对于 Loki::CompileTimeError 实现,不知道,看看再说。


受教了,谢谢大家,用了C++五年惭愧啊。看样子还得好好看几本书。

wanng fenng

unread,
Aug 28, 2009, 11:13:31 PM8/28/09
to pon...@googlegroups.com

大体上分两类: 一类是利用C++ 里面编译常量: 比如数组下表不能为0, 枚举为整形;
第二类: 利用模板特化,编译自己根据条件展开。
对于 Loki::CompileTimeError 实现,不知道,看看再说。
我觉得模板偏特比较好一点,因为某些编译器(gcc)接受零数组;
见过这种写法
struct xx
{
 ......
 int s[0];
};
使用的时候直接把s转换到struct xx,从而标记下一个struct xx
 

zhang xuecheng

unread,
Aug 29, 2009, 3:46:37 AM8/29/09
to pon...@googlegroups.com
失败的话就是:
char size_should_be_the_same[0? 1 : -1];
编译时可以确定的

2009/8/27 Dave Swen <dave...@gmail.com>



--
   best regards,
   zhang xuecheng
   http://veryzhang.cn

四不象

unread,
Aug 31, 2009, 11:52:32 AM8/31/09
to pon...@googlegroups.com
编译器优化的关系

Lambda

unread,
Aug 31, 2009, 8:53:01 PM8/31/09
to TopLanguage
我有一个问题,为什么要这么做?
而且我感觉,并不是所有的assert都可以这样替换吧?

Ian Yang

unread,
Aug 31, 2009, 9:16:35 PM8/31/09
to pon...@googlegroups.com
编译时当时只能断言编译时的不变量

-------
Sincerely, Ian Yang




2009/9/1 Lambda <steph...@gmail.com>

xpol

unread,
Sep 1, 2009, 9:45:25 PM9/1/09
to TopLanguage
BOOST_STATIC_ASSERT (http://www.boost.org/doc/libs/1_40_0/doc/html/
boost_staticassert.html)
如果有一天C++0X成为现实,可以直接用关键字:static_assert

On Aug 27, 6:04 pm, Roc Zhang <zhyg6...@gmail.com> wrote:

Chika .

unread,
Sep 26, 2009, 5:58:25 PM9/26/09
to pon...@googlegroups.com

使用预处理器定义断言,是不是可以在编译阶段处理断言

Robin Lu

unread,
Sep 27, 2009, 8:03:12 AM9/27/09
to pon...@googlegroups.com
可以看看 Modern C++ Design: Generic Programming and Design Patterns Applied 
序言里就有一个简单的解答。

Robin Lu


2009/9/27 Chika . <tangyu...@gmail.com>

使用预处理器定义断言,是不是可以在编译阶段处理断言


王兵兵

unread,
Oct 12, 2009, 3:19:50 AM10/12/09
to pon...@googlegroups.com
用模板!


2009/9/27 Robin Lu <iamaw...@gmail.com>
Reply all
Reply to author
Forward
0 new messages