今天我和海合会有一次奇怪的邂逅。请考虑以下代码:
float len[ELEM+1];
len[1]=1.0; len[2]=2.0; len[3]=3.0; //length
nod[1][1] = 1;
nod[1][2] = 2;
nod[2][1] = 2;
nod[2][2] = 3;
nod[3][1] = 3;
nod[3][2] = 4; //CONNECTIVITY
for(i=1;i<nnod;i++)
for(j=1;j<nfree;j++)
/* blah blah.........*/
还有一个变化:
float len[ELEM+1];
len[1]=1.0; len[2]=2.0; len[3]=3.0; //length
nod[1][1] = 1;
nod[1][2] = 2;
nod[2][1] = 2;
nod[2][2] = 3;
nod[3][1] = 3;
nod[3][2] = 4; //CONNECTIVITY
长度[1]=1.0;长度[2]=2.0;
for(i=1;i<=nnod;i++)
for(j=1;j<=nfree;j++)
/* blah blah.........*/
唯一的区别是用粗体突出显示。问题是:
当随后打印长度时,第一个代码将len[1]和len[2]打印为0.0000(并在表达式中使用),而第二个代码将打印并使用这些变量的正确值。
怎么了?我完全糊涂了。
注意:len在其他地方没有被修改。
最佳答案
您需要向我们展示nod
的定义。很有可能(基于数组从1开始,而不是从0开始)重写内存。
例如,如果nod定义为:
int nod[3][2];
可能的数组下标是
0-2
和0-1
,而不是1-3
和1-2
:nod[0][0] nod[1][0] nod[2][0]
nod[0][1] nod[1][1] nod[2][1]
如果是这样的话,你的记忆几乎肯定是写得太多了,在这种情况下,所有的赌注都被取消了。你可能会破坏任何其他数据。
如果
len
紧跟在nod
之后放在内存中,则此内存溢出将解释其更改的原因。下图将(试图)说明这一点。假设您的nod
定义是:int nod[3][2];
但您尝试设置
nod[1-3][1-2]
而不是nod[0-2][0-1]
: +-----------+
+0000 | nod[0][0] |
+-----------+
+0004 | nod[0][1] |
+-----------+
+0008 | nod[1][0] |
+-----------+
+000c | nod[1][1] |
+-----------+
+0010 | nod[2][0] |
+-----------+
+0014 | nod[2][1] |
+-----------+
+0018 | len[0] | and nod[3][0], should you be foolish enough to try :-)
+-----------+
+001c | len[1] | and nod[3][1] *
+-----------+
+0020 | len[2] | and nod[3][2] *
+-----------+
C/C++不会检查溢出的规则数组边界。所以,如果你试图设置
nod[3][something-or-other]
,你会发现自己遇到了与问题描述非常相似的麻烦。您正在使用的位模式(3和4)分别相当于IEEE754单精度4.2x10-45和5.6x10-45,因此它们在打印时肯定会给出
0.0000
(因为您似乎没有使用会给出更精确值的格式字符串)。测试这个理论的一个好方法是在设置相关的
len
变量之前和之后立即输出nod
变量,比如:printf ("before: len1 = %f, len2 = %f\n", len[1], len[2]);
nod[3][1] = 3;
nod[3][2] = 4;
printf ("after : len1 = %f, len2 = %f\n", len[1], len[2]);
关于变量如何在内存中布局的实际细节可能与上述不同,但理论仍然适用。
两个可能的解决方案,如果这是问题的话。
使用零基数组作为C/C++的意图;或者
为它们定义足够的空间来处理您的异常使用,例如
int nod[4][3]
。关于c++ - 数组值自动更改为0,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1284277/