c语言static 问题

LATCHES 2017-05-15 05:06:03
#include <stdio.h>
int v0=3;
int v1[2]={1,2};
int v2;

int main()
{
v2=3;
static int v4 =7;
int v3=3;
int sum=0;
sum=v0+v1[1]+v1[2]+v2+v3+v4;
printf("%d\n",sum);

return 0;
}



结果为25
自己尝试了下看了下v1[1]和v4的地址是连着的,所以才会出现v1[2]等于7的情况,但不记得static有这个用法,求解

...全文
627 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2017-06-09
  • 打赏
  • 举报
回复
可以参考一下这个博文http://blog.csdn.net/libing403/article/details/72934198
「已注销」 2017-06-09
  • 打赏
  • 举报
回复
了解一下c语言存储类别,可以去看看这个资料http://blog.csdn.net/libing403/article/details/72934528
xuhaoee 2017-05-25
  • 打赏
  • 举报
回复
引用 12 楼 lin5161678 的回复:
引用 11 楼 xuhaoee 的回复:
C标准规定,全局变量和静态变量都在编译时分配空间,并放在数据段中,且分配的空间是连续的!所以你的static变量才会在全局变量后面,你数组越界,不小心修改了static变量空间的数据,所以才会出现这样的问题!
标准规定中 没说分配在数据段 也没说连续 不了解不要乱说
哈哈,兄台说的是,这肯定不是C的标准,而是某一版本编译器自己的行为,不同编译器可能处理不同,多谢提醒~
可爱的小莱 2017-05-25
  • 打赏
  • 举报
回复
引用 15 楼 tomsoft 的回复:
[quote=引用 13 楼 lin5161678 的回复:] [quote=引用 9 楼 tomsoft 的回复:] [quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界,值是随机的,无讨论价值。
同样的编译器,这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界,其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则,数组越界在当代程序设计中是不允许的,但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题 [/quote] 说的没错,Debug或Release版本或GCC下得-O0或-O2的运行结果会存在不同,这主要是因为不同状态下编译器优化的方式不同,造成全局变量的分配顺序不同,但是,如果是确定版本,这个值是唯一的,即您运行多少次是25还是25,因为其变量的分配位置已经固定 ---- 编译器的优化原则所确定,不可能因为您现在运行是25下次就变成了100,所以,我之前讲了,这个单纯从应用角度上是个错误的案例,但如果从编译器角度我们深入讨论这个问题还是蛮有趣的 ----- 我只希望我们从编译器优化角度探讨一下,这不是一件很有趣的事情吗? 在相同条件下这个值是固定的“ 都有可能导致结果不同说随机毫无问题”,所以您这句话我并不完全认同,从单纯应用没有错 另外,我之前也说过,对于我们这些老古董C/C++程序员,早先编程最喜欢玩的就是零长度数组,即指定数组的长度是0,利用数组越界访问其后的内容,以实现变长度数组。但这些都是老技巧,即必须对编译器足够了解。如清楚已初始化数据段和未初始化数据段如何分配等等。。。。[/quote] 根本就是对编译器的处理机制再讨论,具体的编译器不一样,结果也不一样。所以说是随机,是没有问题的。
  • 打赏
  • 举报
回复
V1[2]是一个长度为2的数组,在C语言里第一个元素是v1[0],第二个是v1[1], 你求和是写成了v[2]这是一个下标越界的情形,V1[2]的值是不确定的,可能与你其他变量的值相同,也可能是一个其他的随机值。如果v1数组的空间与static变量紧挨在一起,这时v1[2]的值可能就是static变量的值,总之v1[2]是不确定的,你把电脑关机,第二天开机再来build,运行这个程序,可能又是一个新的值。 static这里使用上没有什么问题,它是一个局部静态变量。
「已注销」 2017-05-20
  • 打赏
  • 举报
回复
引用 11 楼 xuhaoee 的回复:
C标准规定,全局变量和静态变量都在编译时分配空间,并放在数据段中,且分配的空间是连续的!所以你的static变量才会在全局变量后面,你数组越界,不小心修改了static变量空间的数据,所以才会出现这样的问题!
在早期的编译器中(近代编译器如Clang/LLVM已经太复杂,不讨论),编译的数据段会分成几个部分:已初始化数据段、未初始化数据段、Heap和Stack,因此,变量是否初始化,这个程序的值都会不一致,这主要是因为编译器在编译时分配空间的顺序。同时,因为考虑不同优化算法的影响,也会对变量的分配顺序造成影响,即Debug和Release版本其变量分配顺序也有变化,所产生值也是不同的。注意我之前的回复,相同意义的代码,仅仅因为赋值位置或变量是否初始化,这个值都会发生变化即是如此。 这个问题从对错上没有讨论余地,正像楼上众位高手所云,这是个错误示例。基于此,如果从对错角度,这个问题不需要讨论,我所说的一切都可以无视,以免引起无谓的口水仗
「已注销」 2017-05-20
  • 打赏
  • 举报
回复
引用 13 楼 lin5161678 的回复:
[quote=引用 9 楼 tomsoft 的回复:] [quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界,值是随机的,无讨论价值。
同样的编译器,这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界,其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则,数组越界在当代程序设计中是不允许的,但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题 [/quote] 说的没错,Debug或Release版本或GCC下得-O0或-O2的运行结果会存在不同,这主要是因为不同状态下编译器优化的方式不同,造成全局变量的分配顺序不同,但是,如果是确定版本,这个值是唯一的,即您运行多少次是25还是25,因为其变量的分配位置已经固定 ---- 编译器的优化原则所确定,不可能因为您现在运行是25下次就变成了100,所以,我之前讲了,这个单纯从应用角度上是个错误的案例,但如果从编译器角度我们深入讨论这个问题还是蛮有趣的 ----- 我只希望我们从编译器优化角度探讨一下,这不是一件很有趣的事情吗? 在相同条件下这个值是固定的“ 都有可能导致结果不同说随机毫无问题”,所以您这句话我并不完全认同,从单纯应用没有错 另外,我之前也说过,对于我们这些老古董C/C++程序员,早先编程最喜欢玩的就是零长度数组,即指定数组的长度是0,利用数组越界访问其后的内容,以实现变长度数组。但这些都是老技巧,即必须对编译器足够了解。如清楚已初始化数据段和未初始化数据段如何分配等等。。。。
赵4老师 2017-05-19
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节中都有值且都是可读写的,从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
lin5161678 2017-05-19
  • 打赏
  • 举报
回复
引用 9 楼 tomsoft 的回复:
[quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界,值是随机的,无讨论价值。
同样的编译器,这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界,其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则,数组越界在当代程序设计中是不允许的,但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题
lin5161678 2017-05-19
  • 打赏
  • 举报
回复
引用 11 楼 xuhaoee 的回复:
C标准规定,全局变量和静态变量都在编译时分配空间,并放在数据段中,且分配的空间是连续的!所以你的static变量才会在全局变量后面,你数组越界,不小心修改了static变量空间的数据,所以才会出现这样的问题!
标准规定中 没说分配在数据段 也没说连续 不了解不要乱说
xuhaoee 2017-05-19
  • 打赏
  • 举报
回复
C标准规定,全局变量和静态变量都在编译时分配空间,并放在数据段中,且分配的空间是连续的!所以你的static变量才会在全局变量后面,你数组越界,不小心修改了static变量空间的数据,所以才会出现这样的问题!
angel6709 2017-05-18
  • 打赏
  • 举报
回复
月经
「已注销」 2017-05-18
  • 打赏
  • 举报
回复
引用 8 楼 jiftlixu 的回复:
V2[2] 数组越界,值是随机的,无讨论价值。
同样的编译器,这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界,其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则,数组越界在当代程序设计中是不允许的,但从编译器进行学术性讨论还是蛮有趣的。
可爱的小莱 2017-05-18
  • 打赏
  • 举报
回复
V2[2] 数组越界,值是随机的,无讨论价值。
「已注销」 2017-05-17
  • 打赏
  • 举报
回复
这个结果取决于编译器编译的结果,相同代码,修改如下: #include "stdafx.h" #include <stdio.h> int v0 = 3; int v1[2] = { 1,2 }; int v2 = 3; int main() { // v2 = 3; static int v4 = 7; int v3 = 3; int sum = 0; sum = v0 + v1[1] + v1[2] + v2 + v3 + v4; printf("%d\n", sum); return 0; } 其结果为21。其原因主要是紧跟v1[]之后的变量。在当前情况下,v1[]之后可能是v2或v4,这取决于编译器的行为。如果没有赋值语句,其存放顺序与变量出现顺序一致,因此,v1之后紧跟v2,这样v1[2]即是v2。但是,如果在一开始就有v2 =3,编译器从效能角度上先分配已初始化数据段,即顺序是v0,v1,v4,v2这样,v1[2]实际是v4即7 因此,正如楼上所说,这样越界使用是非常危险的,其结果是由编译器决定的。
destory27 2017-05-17
  • 打赏
  • 举报
回复
http://blog.csdn.net/destory27/article/details/54954821
starytx 2017-05-16
  • 打赏
  • 举报
回复
v1[2]都越界了,讨论值没有意义
真相重于对错 2017-05-15
  • 打赏
  • 举报
回复
数组是从0开始计数的
paschen 2017-05-15
  • 打赏
  • 举报
回复
静态变量也是存储在全局区,而不是栈上,但你这是未定义行为,不一定所有编译环境都这样
AlbertS 2017-05-15
  • 打赏
  • 举报
回复
1[2]属于越界访问,不建议使用,虽然你恰好得到了V4的值,但这和顺序有关,结果未定义
加载更多回复(1)
1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C中可变参数函数实现 38 8. C程序内存中组成部分 41 9. C编程拾粹 42 10. C语言中实现数组的动态增长 44 11. C语言中的位运算 46 12. 浮点数的存储格式: 50 13. 位域 58 14. C语言函数二维数组传递方法 64 15. C语言复杂表达式的执行步骤 66 16. C语言字符串函数大全 68 17. C语言宏定义技巧 89 18. C语言实现动态数组 100 19. C语言笔试-运算符和表达式 104 20. C语言编程准则之稳定篇 107 21. C语言编程常见问题分析 108 22. C语言编程易犯毛病集合 112 23. C语言缺陷与陷阱(笔记) 119 24. C语言防止缓冲区溢出方法 126 25. C语言高效编程秘籍 128 26. C运算符优先级口诀 133 27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33. 二叉树的数据结构 167 34. 位运算应用口诀和实例 170 35. 内存对齐与ANSI C中struct内存布局 173 36. 冒泡和选择排序实现 180 37. 函数指针数组与返回数组指针的函数 186 38. 右左法则- 复杂指针解析 189 39. 回车和换行的区别 192 40. 堆和堆栈的区别 194 41. 堆和堆栈的区别 198 42. 如何写出专业的C头文件 202 43. 打造最快的Hash表 207 44. 指针与数组学习笔记 222 45. 数组不是指针 224 46. 标准C中字符串分割的方法 228 47. 汉诺塔源码 231 48. 洗牌算法 234 49. 深入理解C语言指针的奥秘 236 50. 游戏外挂的编写原理 254 51. 程序实例分析-为什么会陷入死循环 258 52. 空指针究竟指向了内存的哪个地方 260 53. 算术表达式的计算 265 54. 结构体对齐的具体含义 269 55. 连连看AI算法 274 56. 连连看寻路算法的思路 283 57. 重新认识:指向函数的指针 288 58. 链表的源码 291 59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 346 65. C指针讲解 352 66. 关于指向指针的指针 368 67. C/C++ 误区一:void main() 373 68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C和C++的区别是什么? 387 74. 无条件循环 388 75. 产生随机数的方法 389 76. 顺序表及其操作 390 77. 单链表的实现及其操作 391 78. 双向链表 395 79. 程序员数据结构笔记 399 80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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