user-0 提问: c语言static 问题

回复:
user: user-1
content: 可以参考一下这个博文http://blog.csdn.net/libing403/article/details/72934198

user: user-1
content: 了解一下c语言存储类别，可以去看看这个资料http://blog.csdn.net/libing403/article/details/72934528

user: user-2
content: 引用 12 楼 lin5161678 的回复:引用 11 楼 xuhaoee 的回复:C标准规定，全局变量和静态变量都在编译时分配空间，并放在数据段中，且分配的空间是连续的！所以你的static变量才会在全局变量后面，你数组越界，不小心修改了static变量空间的数据，所以才会出现这样的问题！标准规定中 没说分配在数据段 也没说连续 不了解不要乱说 哈哈，兄台说的是，这肯定不是C的标准，而是某一版本编译器自己的行为，不同编译器可能处理不同，多谢提醒~

user: user-3
content: 引用 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]  根本就是对编译器的处理机制再讨论，具体的编译器不一样，结果也不一样。所以说是随机，是没有问题的。

user: user-4
content: V1[2]是一个长度为2的数组，在C语言里第一个元素是v1[0],第二个是v1[1], 你求和是写成了v[2]这是一个下标越界的情形，V1[2]的值是不确定的，可能与你其他变量的值相同，也可能是一个其他的随机值。如果v1数组的空间与static变量紧挨在一起，这时v1[2]的值可能就是static变量的值，总之v1[2]是不确定的，你把电脑关机，第二天开机再来build，运行这个程序，可能又是一个新的值。 static这里使用上没有什么问题，它是一个局部静态变量。

user: user-1
content: 引用 11 楼 xuhaoee 的回复:C标准规定，全局变量和静态变量都在编译时分配空间，并放在数据段中，且分配的空间是连续的！所以你的static变量才会在全局变量后面，你数组越界，不小心修改了static变量空间的数据，所以才会出现这样的问题！  在早期的编译器中（近代编译器如Clang/LLVM已经太复杂，不讨论），编译的数据段会分成几个部分：已初始化数据段、未初始化数据段、Heap和Stack，因此，变量是否初始化，这个程序的值都会不一致，这主要是因为编译器在编译时分配空间的顺序。同时，因为考虑不同优化算法的影响，也会对变量的分配顺序造成影响，即Debug和Release版本其变量分配顺序也有变化，所产生值也是不同的。注意我之前的回复，相同意义的代码，仅仅因为赋值位置或变量是否初始化，这个值都会发生变化即是如此。  这个问题从对错上没有讨论余地，正像楼上众位高手所云，这是个错误示例。基于此，如果从对错角度，这个问题不需要讨论，我所说的一切都可以无视，以免引起无谓的口水仗

user: user-1
content: 引用 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，利用数组越界访问其后的内容，以实现变长度数组。但这些都是老技巧，即必须对编译器足够了解。如清楚已初始化数据段和未初始化数据段如何分配等等。。。。

user: user-5
content: 其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

user: user-6
content: 引用 9 楼 tomsoft 的回复:[quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界，值是随机的，无讨论价值。  同样的编译器，这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界，其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则，数组越界在当代程序设计中是不允许的，但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题

user: user-6
content: 引用 11 楼 xuhaoee 的回复:C标准规定，全局变量和静态变量都在编译时分配空间，并放在数据段中，且分配的空间是连续的！所以你的static变量才会在全局变量后面，你数组越界，不小心修改了static变量空间的数据，所以才会出现这样的问题！标准规定中 没说分配在数据段 也没说连续 不了解不要乱说

user: user-2
content: C标准规定，全局变量和静态变量都在编译时分配空间，并放在数据段中，且分配的空间是连续的！所以你的static变量才会在全局变量后面，你数组越界，不小心修改了static变量空间的数据，所以才会出现这样的问题！

user: user-7
content: 月经

user: user-1
content: 引用 8 楼 jiftlixu 的回复:V2[2] 数组越界，值是随机的，无讨论价值。  同样的编译器，这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界，其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则，数组越界在当代程序设计中是不允许的，但从编译器进行学术性讨论还是蛮有趣的。

user: user-3
content: V2[2] 数组越界，值是随机的，无讨论价值。

user: user-1
content: 这个结果取决于编译器编译的结果，相同代码，修改如下： #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 因此，正如楼上所说，这样越界使用是非常危险的，其结果是由编译器决定的。

user: user-8
content: http://blog.csdn.net/destory27/article/details/54954821

user: user-9
content: v1[2]都越界了，讨论值没有意义

user: user-10
content: 数组是从0开始计数的

user: user-11
content: 静态变量也是存储在全局区，而不是栈上，但你这是未定义行为，不一定所有编译环境都这样

user: user-12
content: 1[2]属于越界访问，不建议使用,虽然你恰好得到了V4的值，但这和顺序有关，结果未定义