printf的问题,不明白具体是什么原因,麻烦高手答疑解惑,谢谢

lokyu 2015-07-30 06:38:53
void main()
{
for (int i = 0 ; i < 10 ; i++)
{
int k;
// k++;
printf("%x\n",&k);
if (i == 0)
{
// k = 0;
k++;
}
else
{
k++;
}
printf("%d %x \n",k,&k);
}
getchar();
}

先说第一种情况:把k++打开,运行出错,原因是K没有初始化,这个能理解
问题是如果把k++屏蔽掉,感觉是和之前是一样的,但是运行就不报错了,不知道为什么,应该是printf的原因,不过具体是为什么就不清楚了
第二个问题:int k;应该是个局部变量,那么为什么k可以累加,并且地址相同?这样的话k在for里面定义和在for外面定义岂不是一样的?
感觉是printf的原因,但是不明白
请各位指点一下,谢谢
...全文
460 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lokyu 2015-08-08
  • 打赏
  • 举报
回复
虽然疑问没弄清楚 但是也谢谢各位 结贴
paschen 版主 2015-07-31
  • 打赏
  • 举报
回复
引用 2 楼 lokyu 的回复:
引用
第一个问题:你说:把k++打开,运行出错,原因是K没有初始化 这个是没有问题的。一个垃圾值(未初始化的局部变量),你读它根本没问题,输出他的地址也OK,只不过程序没意义。 一个局部变量一旦定义,在他的生存期内,他 的地址是不会变的。所以k地址不会变。 栈变量是系统分配的内存,你无法干预和改变。 问题是,k未初始化,他的值是垃圾值。你无法预测。所以你加加减减,输出什么的,都会看到是垃圾值。 还有,不要不定义放到循环里面,这样没错,但是不好。一个变量定义一次了,你使用完了又把它定义一遍,没理由这样做。 你可以放在for( int k ; ; ) 这里,或者for外面。
首先谢谢你的回答 你说局部变量在他的生存周期里地址不会变,那我想问一下这个int k;的周期是什么范围,我理解的就是一次for循环,下次循环k就是个全新的变量。 另外这里我主要想请大家帮忙解答的是printf的影响,很明显printf是对整个运行结果有影响的,这事我想问的重点。至于在哪定义就是其他的事了,不知道我有没有说清楚,再次感谢
没错,下一次循环k确实是一个全新的变量了,只是碰巧又分配在了相同的地址,而你又没有初始化k的值,他仍保留了原来的值
jiqiang01234 2015-07-31
  • 打赏
  • 举报
回复
与printf无关,是因为vc调试器会插入调试代码(检查变量是否已经初始化),导致k++的时候报错。用release就没有问题。 局部变量的周期就是一个作用域内,在本例中,就是一次for循环,也就是每次for循环,否有一个新的k产生。之所以新生成的局部变量还会每次累加,是因为局部变量的分配地址的问题。编译器很有可能将新生成的局部变量放置在同一个内存地址,所以新的一个循环中的k与上一次循环中的k,从语义上来说已经是不同的了,但是从实现上来说,却分配了同一个地址。所以多次循环操作的是同一个地址中的值,也就会出现可以累加的情况了。
jiqiang01234 2015-07-31
  • 打赏
  • 举报
回复
与printf无关,是因为vc调试器会插入调试代码(检查变量是否已经初始化),导致k++的时候报错。用release就没有问题。 局部变量的周期就是一个作用域内,在本例中,就是一次for循环,也就是每次for循环,否有一个新的k产生。之所以新生成的局部变量还会每次累加,是因为局部变量的分配()
lokyu 2015-07-31
  • 打赏
  • 举报
回复
另外变量k的值也不是我想问的重点,所以也没有必要讨论他的值是不是有意义
lokyu 2015-07-31
  • 打赏
  • 举报
回复
引用
第一个问题:你说:把k++打开,运行出错,原因是K没有初始化 这个是没有问题的。一个垃圾值(未初始化的局部变量),你读它根本没问题,输出他的地址也OK,只不过程序没意义。 一个局部变量一旦定义,在他的生存期内,他 的地址是不会变的。所以k地址不会变。 栈变量是系统分配的内存,你无法干预和改变。 问题是,k未初始化,他的值是垃圾值。你无法预测。所以你加加减减,输出什么的,都会看到是垃圾值。 还有,不要不定义放到循环里面,这样没错,但是不好。一个变量定义一次了,你使用完了又把它定义一遍,没理由这样做。 你可以放在for( int k ; ; ) 这里,或者for外面。
首先谢谢你的回答 你说局部变量在他的生存周期里地址不会变,那我想问一下这个int k;的周期是什么范围,我理解的就是一次for循环,下次循环k就是个全新的变量。 另外这里我主要想请大家帮忙解答的是printf的影响,很明显printf是对整个运行结果有影响的,这事我想问的重点。至于在哪定义就是其他的事了,不知道我有没有说清楚,再次感谢
lokyu 2015-07-31
  • 打赏
  • 举报
回复
引用 5 楼 jiqiang01234 的回复:
与printf无关,是因为vc调试器会插入调试代码(检查变量是否已经初始化),导致k++的时候报错。用release就没有问题。 局部变量的周期就是一个作用域内,在本例中,就是一次for循环,也就是每次for循环,否有一个新的k产生。之所以新生成的局部变量还会每次累加,是因为局部变量的分配地址的问题。编译器很有可能将新生成的局部变量放置在同一个内存地址,所以新的一个循环中的k与上一次循环中的k,从语义上来说已经是不同的了,但是从实现上来说,却分配了同一个地址。所以多次循环操作的是同一个地址中的值,也就会出现可以累加的情况了。
感谢你的回答 可是如果和printf没关系的话,为什么把k++放在printf之前和之后运行结果不一样呢?
赵4老师 2015-07-31
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
love1code 2015-07-30
  • 打赏
  • 举报
回复
第一个问题:你说:把k++打开,运行出错,原因是K没有初始化 这个是没有问题的。一个垃圾值(未初始化的局部变量),你读它根本没问题,输出他的地址也OK,只不过程序没意义。 一个局部变量一旦定义,在他的生存期内,他 的地址是不会变的。所以k地址不会变。 栈变量是系统分配的内存,你无法干预和改变。 问题是,k未初始化,他的值是垃圾值。你无法预测。所以你加加减减,输出什么的,都会看到是垃圾值。 还有,不要不定义放到循环里面,这样没错,但是不好。一个变量定义一次了,你使用完了又把它定义一遍,没理由这样做。 你可以放在for( int k ; ; ) 这里,或者for外面。

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧