C++小问题3则

问题1

有网友问这样一个问题:

Is there any way to use QString as a parameter in switch case as shown below.

QString str;
switch(str)
{
     case "A":
     break;
     case "B":
     break;
}

潜意识告诉我这样肯定不行,可是证据呢?连自己都说服不了,难受。

只好翻翻C++标准了。还好,很容易就找到了(ISO C++ 6.4 节):

  • switch 语句中的“条件”,必须是
    • 整数或enum类型的变量,或
    • 可以隐式转换成整数或enum类型的变量

由于QString没有 operator int() 这类的成员函数,故不可以。

标准原文:

  • The value of a condition that is an initialized declaration in a switch statement is the value of the declared variable if it has integral or enumeration type, or of that variable implicitly converted to integral or enumeration type otherwise.

恩,那么case后面可以是“A”这种东西么?ISO C++ 6.4.2,对此有规定:

  • case 后面必须是整数常量

标准原文:

  • Any statement within the switch statement can be labeled with one or more case labels as follows:
    case constant-expression :
    where the constant-expression shall be an integral constant.

问题二

void main(){
     int a = a;
}
A compiler通过, linker不能通过.
B compiler不能通过
C 视乎具体compiler而定

咱们忽略 main 函数的这个不规范的写法,假定它的意图就是问 int a = a;这一句。

这个东西有没有问题?翻标准,恩 ISO C++ 3.3.2

没任何问题:

int x = 12;
{ int x = x; }

第二个x将使用它自己的值(尽管是不确定的值)进行初始化。与第一个x无关。

标准中还给出的其他的例子:

const int i = 2;
{ int i[i]; }

恩,和先前不同,块作用域内定义了一个两个整数元素的数组。

const int x = 12;
{ enum { x = x }; }

恩,对于枚举量,x的值初始化为12。也和先前不同。

标准原文(只贴出一段):

  • The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [ Example: 
    int x = 12;
    { int x = x; }
    Here the second x is initialized with its own (indeterminate) value. — end example ]

问题三

使用typeid实验结果是:

typeid(int()) != typeid(int)
typeid(int()) != typeid(i)   // int i

so...
int()是啥东西?

恩,int() 是什么东西呢?

当我们这样写时,应该就比较清楚了

int a();

是一个函数的声明,那么 int() 就是函数类型了。

只是,有个疑问,楼主既然用到typeid了,为何不使用 type_info::name() 来输出类型信息看看呢?

于是写个例子:

#include <stdio.h>
#include <typeinfo>
int main()
{
    printf("%s\n", typeid(int()).name());
    printf("%s\n", typeid(int).name());
    return 0;
}

用GCC编译运行(如果用的MSVC,生成的可读性很好的字符串)

FivE
i

啊,难怪,原来这个和名字改编几乎一样的东西,很难读懂。既然输出都输出了,试试读读看:

GCC4使用的 Itanium C++ ABI,于是找到这个网页:

F...E

函数

i

返回值为 int

v

参数为 void

恩,简单的函数还好办,如果复杂的类型还真麻烦。幸好,GCC提供有demangle的函数:

恩,改写如下:

#include <stdio.h>
#include <typeinfo>
#include <cxxabi.h>
int main()
{
    char * realname = abi::__cxa_demangle(typeid(int()).name(), 0, 0, 0);
    printf("%10s ==> %15s\n", typeid(int()).name(), realname);

    realname = abi::__cxa_demangle(typeid(int(*)()).name(), 0, 0, 0);
    printf("%10s ==> %15s\n", typeid(int(*)()).name(), realname);

    realname = abi::__cxa_demangle(typeid(int).name(), 0, 0, 0);
    printf("%10s ==> %15s\n", typeid(int).name(), realname);
    return 0;
}

结果:

      FivE ==>        int ()()
     PFivE ==>       int (*)()
         i ==>             int

参考


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值