自我总结:(之前查过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. java中@value的环境配置

    @value 在现阶段我想大家对注解都不陌生,@value的用法就是在后台获取配置文件的信息,从而方便修改一些固定的配置.不明白的可以百度@value的详解. 配置@value有以下几个步骤. 1.首 ...

  2. 2016年11月19日 星期六 --出埃及记 Exodus 20:10

    2016年11月19日 星期六 --出埃及记 Exodus 20:10 but the seventh day is a Sabbath to the LORD your God. On it you ...

  3. java-cmd-命令行编译和运行java文件

    一.使用的工具 1.javac 2.java 二.命令 项目目录只这样的 D:/project/src/com/example/Child.java D:/project/src/com/exampl ...

  4. SqlSever基础 cast 将getdate返回的时间转换成字符串

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

  5. C# 多线程之一:信号量Semaphore

    通过使用一个计数器对共享资源进行访问控制,Semaphore构造器需要提供初始化的计数器(信号量)大小以及最大的计数器大小 访问共享资源时,程序首先申请一个向Semaphore申请一个许可证,Sema ...

  6. 我的android学习经历21

    怎样在代码文件中修改控件的高低 有些时候使用setHight()或者setWidth()不管用就需要使用别的方法,下面有一种方法 你使用的布局.LayoutParams lp = new 你使用的布局 ...

  7. BZOJ 2229 最小割

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2229 题意:给定一个带权无向图.若干询问,每个询问回答有多少点对(s,t)满足s和t的最 ...

  8. BZOJ 1855 股票交易(单调队列优化DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票 ...

  9. 关于STM32库中 __IO 修饰符(volatile修饰符,反复无常的意思)

    STM32例子代码中会有像这样的代码 static __IO uint32_t TimingDelay;  这里边的__IO修饰符不好理解,单从字面可以看出是为IO相关,查其标准库可以得知这个__IO ...

  10. JAVA运算符和优先级

    1.算术运算符: ++ 和 -- 既可以出现在操作数的左边,也可以出现在右边,但结果是不同,如: ①int a=5: int b=a++: #先把a赋给b,a再自增 ②int a=5: int b=+ ...