首页 新闻 搜索 专区 学院

我在for循环语句给变量S赋值,但程序报错:使用了未赋值的局部变量“s”,希望老师们指导

0
悬赏园豆:5 [已解决问题] 解决于 2013-04-23 12:30
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace 数组的排序练习
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12            string[] names = { "梅西", "卡卡", "郑大世" };
13             string s;
14 //在for循环语句不是个s赋值了,怎么还是报错“局部变量S未赋值”
15             for (int i = 0; i < names.Length-2; )
16             {
17                  s=names[i]+"|";
18                  Console.Write(s);
19                  i++;
20             }
21             s=s+names[names.Length-1];
22             Console.WriteLine(s);
23 
24             Console.ReadKey();
25         }
26     }
27 }


程序报错:使用了未赋值的局部变量“s”(即代码中的红色s),可是我不是在for语句中,已经赋值初始化了吗?

希望各位老师们,指导学生,指点迷津

黑夜猫头鹰的主页 黑夜猫头鹰 | 初学一级 | 园豆:3
提问于:2013-04-21 17:16
< >
分享
最佳答案
0

前面很多人都已经正确指出了你的错误和解决方案,但是我看了你的评论,似乎对for循环的理解有误。你认为“编译器应当知道names.Length - 2 > 0",所以“编译器应当知道for循环是肯定执行的”,所以“编译器应当知道s一定会被赋值”。实际上for循环的语法是这样的:

for (初始化语句; 结束条件; 每次循环完成时执行的语句)
{
      循环主体
}

试想一个for语句可能是这样的:

for (int i = 0; Test(i); Go(i))
{
     //循环主体
}

其中Test(i)是一个非常复杂和耗时的方法。在这种情况下,编译器很难尝试去“检测Test(i)", 事实上这样做的意义也不大。

总结一下就是:for循环的结束条件表达式,编译器”总是认为“它是一个“运行时才能得到的值”,即使“你提供了一个总是为真的表达式”。这方面跟if-else和switch不同。编译器用很小的代价就可以知道if-else/switch分支是否总是会给s赋值:

string s;

if (Test(1))   //Test是某个返回bool的函数
{
     s = "1";
}
else
{
     s = "2";
}

//在此之后编译器能够很容易意识到s被赋值了,无论Test方法的实现是怎样的
//switch同理
收获园豆:2
水牛刀刀 | 大侠五级 |园豆:6350 | 2013-04-22 11:06

牛哥,我看了你的表达,我想问下,你是说:编译器是负责语法逻辑检测的,但是由于for循环语句【 for (int i = 0; i < names.Length-2; )】,编译器只对for循环语句进行语法检测,且对于这些循环体的变量赋值问题,一概默认为条件不成立(即使逻辑上是成立的,但是编译器为了提高效率,不进行多次循环逻辑判断,全部默认不成立),所以【s=names[i]+"|"】,虽然有赋值语句,但是程序认为for循环成立,对变量S的赋值初始化,根本没有执行,到了这句【s=s+names[names.Length-1]】,造成编译器认为我们使用了未初始化的变量s,进行赋值运算。

我的理解有错吗?希望指点,牛哥

黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-22 18:08

@黑夜猫头鹰: “一概默认为条件不成立”,更准确的说是“编译器认为有可能不成立”,即“s有可能未被赋值”。

水牛刀刀 | 园豆:6350 (大侠五级) | 2013-04-22 18:12
其他回答(7)
0

你的代码不能通过 VS 的编译,起码要赋空值。

geass.. | 园豆:1785 (小虾三级) | 2013-04-21 17:37

我知道将string s="";程序可以编译通过,但是我在for语句赋值也行啊,怎么就不可以呢?是我在知识点上有误区吗?我想知道为什么

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-21 17:55
1

我大概说下我的理解啊,主要的原因是 当你 不初始化 s的时候,s没有分配内存空间,然后s就不能作为一个值去使用

s=s+"zhi"; 或者 s+="zhi";都不可以,

而你这里的问题是 在程序买没有执行之前,是不能确定for循环里的内的东西用一定能执行,比如names.length==0的话

 

所以,声明变量时候一定要初始化,这是程序员的基础知识了,即使 string s = null;也可以。

收获园豆:1
SeeMore | 园豆:313 (菜鸟二级) | 2013-04-21 21:58

其实我也有这样想法:【在程序买没有执行之前,是不能确定for循环里的内的东西用一定能执行】

但是后来想想,程序在编译时是从上到下顺序编译的,

当编译器读取到【s=s+names[names.Length-1]】这句时,早就通过了for循环,知道肯定能通过for语句给变量s赋值,在需要使用变量s时,都对变量S进行赋值初始化了。

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-21 23:00

@黑夜猫头鹰:

1、我也认为是编译器不会识别for内部赋值语句,就像if……else……中赋值一样。

2、编译器也并不一定从上到下,会有编译优化

3、编译器编译的时候也不会去执行你的代码,只是进行类型安全检查,访问权限之类的检查和其他。

支持(1) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-04-21 23:28
0

你至少得初始化啊,都没有分配内存空间,怎么去对变量进行操作

不负春光,努力生长 | 园豆:1382 (小虾三级) | 2013-04-21 22:24

这一句,不是【 s=names[i]+"|"】不是赋值初始化了吗?

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-21 22:52

@黑夜猫头鹰: 变量定义的时候就要分配内存的

支持(0) 反对(0) 不负春光,努力生长 | 园豆:1382 (小虾三级) | 2013-04-21 23:02

@飘雪无痕007: 我只听过”变量在使用前要赋值初始化“,没有这”定义是就要分配内存地址“???

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace ConsoleApplication4
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12             string a;
13             string b = Console.ReadLine();
14             a = b;
15             Console.WriteLine(a);
16         }
17     }
18 }

照你的说法,呢么怎么变量a又可以运行呢??

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-21 23:17
0

for循环里面的语句会不会执行编译器是不知道的,这个s是一个运行时变量,而编译器检查的时候并不会认为你的s有值,因此是不能做右值被别的表达式使用的。

因此在遇到这种不一定会执行的语句的时候编译器其实是认不出s的值的。所以要在声明的时候初始化,即

string s = string.Empty;

这样是最好的方法。

收获园豆:2
飞鸟_Asuka | 园豆:251 (菜鸟二级) | 2013-04-21 23:19

其实我也有这样想法:【在程序买没有执行之前,是不能确定for循环里的内的东西用一定能执行】

但是后来想想,程序在编译时是从上到下顺序编译的,

当编译器读取到【s=s+names[names.Length-1]】这句时,早就通过了for循环,知道肯定能通过for语句给变量s赋值,在需要使用变量s时,都对变量S进行赋值初始化了。

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-21 23:22

@黑夜猫头鹰: 都说了,编译器是无法判断你的for语句能否跑完的。

支持(0) 反对(0) 飞鸟_Asuka | 园豆:251 (菜鸟二级) | 2013-04-21 23:41

@飞鸟_Asuka: 我想问下,我这里有个概念不是很懂

[这个s是一个运行时变量,而编译器检查的时候并不会认为你的s有值,因此是不能做右值被别的表达式使用的],右值是什么?

1 编译器检测时,程序不是运行了吗?

2“s是运行时变量”,请问有“非运行时变量”吗?

以上的问题导致我对这句【这种不一定会执行的语句的时候编译器其实是认不出s的值的】不解?

以为我是观点是{当编译器读取到【s=s+names[names.Length-1]】这句时,早就通过了for循环,知道肯定能通过for语句给变量s赋值

希望你能,指点我,感谢你

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-22 09:22

@黑夜猫头鹰: 编译器不会运行你的程序,它只会做一些语法上的检查。但是你这里把s用于赋给一个变量,而编译器检测到你的s只有声明没有值,因此认为这个语句不符合语法于是报错。编译器并不会跑你的程序来确定for循环会不会运行

支持(0) 反对(0) 飞鸟_Asuka | 园豆:251 (菜鸟二级) | 2013-04-22 10:50
0

定义成静态变量,每次跳出循环s为空的缘故

伏草惟存 | 园豆:1420 (小虾三级) | 2013-04-22 08:45
0

string s ;程序默认不给分配内存地址  所以会报错

胖子哥哥 | 园豆:341 (菜鸟二级) | 2013-04-22 08:45
0

计算机怎么知道一定会走for循环呢? 你如何保证for循环一定会执行呢?

string s; 修改为
 string s="";
chenping2008 | 园豆:9836 (大侠五级) | 2013-04-22 08:57

其实我也有这样想法:【在程序买没有执行之前,是不能确定for循环里的内的东西用一定能执行】

但是后来想想,程序在编译时是从上到下顺序编译的,

当编译器读取到【s=s+names[names.Length-1]】这句时,早就通过了for循环,因为【string[] names = { "梅西", "卡卡", "郑大世" }】,则编译器通过判断,肯定能通过for语句给变量s赋值,在需要使用变量s时,都对变量S进行赋值初始化了

支持(0) 反对(0) 黑夜猫头鹰 | 园豆:3 (初学一级) | 2013-04-22 09:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册