自我总结:(之前查过goto和switch的资料但是一直没有搞懂,直到今天看到这个讨论才懂了)

1   int a;    是个描述,而不是个命令,只是说明我需要空间,编译器会保证在相应的作用域之中这个变量的空间是被分配了(只要改一下堆栈指针就好)。

2   大部分编译期实现会选择在函数开始把所有局部变量的空间都分配好。

3   声明还可以是一个类的对象,那么这时候这个声明的语句就很可能是一个命令了:调用相应的构造函数。这种情况下,编译器就会告诉你跳过了该做的事情,不能这么写了。

之前我的错误理解和这个形容是一样的:

vczh(作者) 回复 yksgj
你觉得编译器产生的代码,有可能真的是运行到int ival;这一行,就给你的stack立刻涨多4个字节,运行到}就立刻退回去吗?

原问题:http://www.zhihu.com/question/23051685

请教switch内部的变量定义问题?

 #include <iostream>
using namespace std; int main()
{
bool b = false; switch (false)
{
case true:
int ival;
break; case false:
ival = ;
cout << ival << endl;
} return ;
}

这段c++代码应该直接执行switch语句中的 case false,这样的话ival应该没有被定义,为什么程序能被编译通过,并顺利执行?(编译器gcc4.7)
这边的ival应该是局部变量,应该运行时在栈上分配空间啊,那么应该不存在在编译时已经分配好空间的问题了吧?

回答:

---------------------------------------------------------------------------

vczh专业造轮子 http://www.gaclib.net

不能跳过的不是变量的定义,而是初始化。你把int ival改成int ival=0;或者string ival,你就可以看到效果。

这个我明白,如果string ival的话,必须用花括号括起来才行。可是变量不是应该先定义才能使用吗,为什么这边可以直接跳过定义?
昨天 19:16   

vczh(作者) 回复 yksgj
“定义”不做任何事情,当然可以跳过。只有你初始化了,编译器才会给你产生代码,所以不能跳过。switch的case和goto是一个道理。
昨天 19:17   1 赞

yksgj 回复 vczh(作者)
那是不是在编译阶段,实际上已经为ival分配了存储空间?可是在这边ival不是局部变量吗
昨天 19:21   

vczh(作者) 回复 yksgj
你觉得编译器产生的代码,有可能真的是运行到int ival;这一行,就给你的stack立刻涨多4个字节,运行到}就立刻退回去吗?
昨天 19:22   

郑贤伟 回复 yksgj
这个在编译的时候,已经确定了的,系统会计算当前有多少个局部变量,然后统一开辟空间。
系统分配堆栈空间的时候,不是运行时才确定有多少空间需要分配的。
昨天 19:22   

yksgj 回复 vczh(作者)
你的意思是编译器虽然没有给 ival分配空间,但是为它在栈山保留了空间,所以实际上等于定义了ival,是这个意思么?
昨天 19:26   

yksgj 回复 郑贤伟
所以等于在编译阶段还是定义了ival?
昨天 19:28   

vczh(作者) 回复 yksgj
是,其实所有变量的空间都是一进函数就分配好的了,区别只是有没有在那块东西上运行构造函数
昨天 19:28   

郑贤伟 回复 yksgj
是的
昨天 19:28   

yksgj 回复 vczh(作者)
明白了,谢谢轮子哥!
昨天 19:28   

yksgj 回复 郑贤伟
谢谢!
昨天 19:29   

看看汇编代码就知道怎么回事,ival在编译时确定地址为-4(%ebp),ebp作为stack frame
昨天 20:26   1 赞

durow 回复 郑贤伟
正解!
昨天 22:27   

这种情况是否说明:内置类型没有初始化可以使用,自定义的类类型必须初始化才能使用? @vczh@郑贤伟 谢谢
昨天 23:22   

vczh(作者) 回复 tor vec
你只要没有构造函数和析构函数,并且你的struct的成员也都没有,那就跟内置的类型一样
昨天 23:37   

tor vec 回复 vczh(作者)
谢谢,我刚刚按你说的试了,确实可以。(另外有成员也是可以的,我用的VS2010)大神怎么一直在线啊
昨天 23:40   

vczh(作者) 回复 tor vec
因为我喜欢宅在家里
 

----------------------------------------------------------------------------

pansz自由软件开发者

ival是局部变量,作用域是所在的大括号内。

所以第二个case仍然属于该变量的作用域。

另外,变量的定义不是语句,所以无需执行也是全范围有效。这里第一个case的语句虽然没有被执行,但它的变量定义仍然有效。

同vczh说的一样,能跳过的是变量初始化而不是变量定义。变量无论在何处定义都有效,switch只能跳过变量初始化,不能跳过变量定义。

----------------------------------------------------------------------------

刘城不要上zhihu了!

你的理解有一些误区,变量的声明和定义的作用是在静态域,与是否执行到没有关系。定义变量并不存在执行动作。

为什么这个容易误解呢,因为c语言switch语句设计的比较悲剧,每个case部分是没有独立的作用域的。要理解它,一种方法是把它当作goto来看。 比如这个程序就是:

 #include <iostream>
using namespace std;
int main() {
bool b = false;
goto case_false;
case_true:
int ival;
goto switch_end;
case_false:
ival = ;
cout << ival << endl;
switch_end:
return ;
}

再说一下动态分配的事情,先说清楚分配不是有一条指令教int xxx,执行到这里的时候会分配空间,这个是个描述,而不是个命令,只是说明我需要空间,编译器会保证在相应的作用域之中这个变量的空间是被分配了。
大部分编译期实现会选择在函数开始把所有局部变量的空间都分配好(只要改一下堆栈指针就好)。

最后补充一下,你的声明还可以是一个类的对象,那么这时候这个声明的语句就很可能是一个命令了:调用相应的构造函数。这种情况下,编译器就会告诉你跳过了该做的事情,不能这么写了。

转:switch内部的变量定义问题(goto类似)的更多相关文章

  1. C++ Prime:switch内部的变量定义

    如果需要为某个case分支定义并初始化一个变量,我们应该把变量定义在块内,从而确保后面的所有case标签都在变量的作用域之外. case true: { // 正确,声明语句位于语句块内部 strin ...

  2. C# 多线程调用静态方法或者静态实例中的同一个方法-方法内部的变量是线程安全的

    C#  多线程调用静态方法或者静态实例中的同一个方法-方法内部的变量是线程安全的 using System;using System.Threading;using System.Threading. ...

  3. Switch选择语句能否作用在String【字符串】上,也就是能否这么写:Switch(一个字符串变量)?

    Switch选择语句能否作用在String[字符串]上,也就是能否这么写:Switch(一个字符串变量)? 解答:不可以,只能处理int,byte,short,char,(其实是只能处理int,其它三 ...

  4. 函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!闭包访问局部变量

    函数内部声明变量的时候,一定要使用var命令.如果不用的话,你实际上声明了一个全局变量! function f1(){ n=999; } f1(); alert(n); 子函数可以一层一层读取到父元素 ...

  5. shell-的bash内部命令变量介绍与shift等

    一:shell的bash内部命令变量介绍与shift等 1. bash内部变量     有些内部命令在目录列表时是看不见的,他们有shell本身提供,常用的内部命令有:echo,eval,exec,e ...

  6. 《Go学习笔记 . 雨痕》流程控制(if、switch、for range、goto、continue、break)

    Go 精简(合并)了流控制语句,虽然某些时候不够便捷,但够用. if...else... 条件表达式值必须是布尔类型,可省略括号,且左花括号不能另起一行. func main() { x := 3 i ...

  7. 2_C语言中的数据类型 (九)逻辑运算符与if语句、switch、条件运算符?、goto语句与标号

    1          条件分支语句 1.1       关系运算符 在C语言中0代表false,非0代表真 1.1.1          < 小于 1.1.2          <= 小于 ...

  8. Java中简单的操作(if语句、常用操作符、switch语句、变量赋值等)

    ---------------------if语句介绍--------------------------------------------------- class IfDemo { public ...

  9. python中修改函数内部的变量会发生什么

    最近写python遇到个函数内部变量使用外部变量的问题,现在总结下吧 #!/usr/bin/env python a = 100def su(): a = a + 1 print(a) s = su( ...

随机推荐

  1. 类型解释器——C专家编程读书笔记

    对于声明,应该按下面的步骤来进行解释: 1) 声明从它的名字开始读取,然后按照优先级顺序依次读取 2) 优先级顺序 a) 括号括起来的部分 b) 后缀操作符,()表示函数,[]表示数组 c) 前缀操作 ...

  2. A Mathematical Curiosity 分类: HDU 2015-06-25 21:27 11人阅读 评论(0) 收藏

    A Mathematical Curiosity Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...

  3. Unity中实现List类型的自定义GUI(ReorderableList)

    感谢韩同学提供的资源 Unity本身提供了float,int,vector3..等类型字段的gui接口,而对于集合类型一般要自己硬写. 官方提供了一个List的自定义GUI,但使用起来非常复杂 Uni ...

  4. dubbo源码之四——dubbo服务发布

    dubbo版本:2.5.4 服务发布是服务提供方向注册中心注册服务过程,以便服务消费者从注册中心查阅并调用服务. 服务发布方在spring的配置文件中配置如下: <bean id="d ...

  5. Python3基础 while配合random输出10个随机整数

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  6. SqlSever基础 union 联合查询,厉害的并集 重复项只显示一个 两个查询结果并在一起后排序

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  7. BZOJ 1266 上学路线route(最小割)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1266 题意:给出一个无向图,每条边有长度和代价.求出1到n的最短路.之后删掉一些边使得1 ...

  8. ios获取摄像头与相册图片

    iOS的一些设备上都安装了摄像头.现在绝大多数都有了. 在编程中,我们是用相应的东西来进行照相,录像等功能.   一.UIImagePickerController类 UIImagePickerCon ...

  9. 访问者模式,visitor

    定义: 表示作用于某对象结构中的各个元素的操作. 可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 前提: 适用于数据结构(Element)相对稳定的系统,这样visitor中的方法就是稳定 ...

  10. 一个ListBox的例子

    1.向ListBox中放入其他控件 XAML: <Window x:Class="ItemsControls.MainWindow" xmlns="http://s ...