c - 访问数组中存储的元素时出现奇怪的结果

标签 c arrays for-loop igraph

我初始化了数组rhs来存储函数rbf产生的数据,如下所示:

float rhs[m][n1+n2];
        for (i=0; i<m; i++){
         igraph_edge(&graph, i, &from, &to);
         igraph_neighbors(&graph, &v1, from, IGRAPH_ALL);
         igraph_neighbors(&graph, &v2, to, IGRAPH_ALL);
         n2 = igraph_vector_size(&v2);
         n1 = igraph_vector_size(&v1);
         for (j=0; j < n2 ; j++) {
              rhs[i][j] = rbf(to, (int) VECTOR(v2)[j]);
              printf("%d %d %f\n", to, (int) VECTOR(v2)[j], rhs[i][j]);
          }
         for (j=0; j < n1; j++) {
              rhs[i][j+n2] = rbf(from, (int) VECTOR(v1)[j]);
              printf("%d %d %d %d %f\n", from, (int) VECTOR(v1)[j], j, j+n2, rhs[i][j+n2]);
          }
printf("\n");
     }

输出:

2 1 0.367879
2 3 0.367879
2 4 0.018316
1 2 0 3 0.367879

3 2 0.367879
3 4 0.367879
2 1 0 2 0.367879
2 3 1 3 0.367879
2 4 2 4 0.018316 

4 2 0.018316
4 3 0.367879
4 5 0.367879
2 1 0 3 0.367879
2 3 1 4 0.367879 <-- ** here rhs[i = 2][( j+(n2=3) ) =  4] = 0.367879 **
2 4 2 5 0.018316 <-- ** here rhs[i = 2][( j+(n2=3) ) =  5] = 0.018316 **

4 2 0.018316
4 3 0.367879
4 5 0.367879
3 2 0 3 0.367879
3 4 1 4 0.367879

5 4 0.367879
4 2 0 1 0.018316
4 3 1 2 0.367879
4 5 2 3 0.367879

当我尝试访问这个数组时,如下所示,其中只有两个元素的顺序与存储时的顺序不同!我不知道为什么要互相替换!

for (i=0; i<m; i++){
         igraph_edge(&graph, i, &from, &to);
         igraph_neighbors(&graph, &v1, from, IGRAPH_ALL);
         igraph_neighbors(&graph, &v2, to, IGRAPH_ALL);
         n2 = igraph_vector_size(&v2);
         n1 = igraph_vector_size(&v1);
 for (j=0; j < (n1+n2) ; j++) {
    printf("%li %li %f", i, j, rhs[i][j]);
printf("\n");
  }  
printf("\n");    
}
printf("\n%f", rhs[2][5]);

输出:

    0 0 0.367879
    0 1 0.367879
    0 2 0.018316
    0 3 0.367879

    1 0 0.367879
    1 1 0.367879
    1 2 0.367879
    1 3 0.367879
    1 4 0.018316

    2 0 0.018316
    2 1 0.367879
    2 2 0.367879
    2 3 0.367879
    2 4 0.018316 <-- ** here is a strange element rhs[2][4] should equal 0.367879 **
    2 5 0.367879 <-- ** here is a strange element rhs[2][5] should equal 018316 **

    3 0 0.018316
    3 1 0.367879
    3 2 0.367879
    3 3 0.367879
    3 4 0.367879

    4 0 0.367879
    4 1 0.018316
    4 2 0.367879
    4 3 0.367879


    0.367879 <-- it is this one! should equal 0.018316 but it is replacing rhs[2][5] with rhs[2][4]

我想知道为什么在数组中访问元素时的顺序与存储这些元素时的顺序不同?到底是因为什么造成的结果呢?

添加:

文件toy由玩具数据组成,其格式为

1 2
2 3
2 4
3 4
4 5

如果您想编译它,这里是所有代码:

#include <igraph/igraph.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define sigma 1
    /* Declare and define the rbf function */

float rbf(int a, int b);
float rbf(int a, int b) {
               double inverse;
               double exp(double x;);
               double x;
               double result;

               inverse = ( 1/(sigma*sigma) );
               x = (- inverse * ( (a - b)*(a - b) ) );
               result = exp(x);
               return (result); 
 }

/* Define a function to print a vector in a file using the functions defined in igraph package */

void print_vector(igraph_vector_t *v, FILE *file) {
     long int i;
     for (i=0; i < igraph_vector_size(v); i++) {
        fprintf(file, "%li \n", (long int) VECTOR(*v)[i]);
      }
     fprintf(file,"\n");
  }

int main(void)
{
     igraph_t graph; 
     igraph_bool_t false;
     int ret, n1, n2;
     igraph_vector_t v1, v2;
     long int i, j, k, n, m ;
     igraph_integer_t from, to;
     igraph_adjlist_t adjlist;
     FILE *file;

     /* read the graph from a file using igraph package */
     file = fopen("toy", "r");
          if(!file){
                     return 1;
           }
     igraph_read_graph_edgelist(&graph, file, 
                   0, false);
           fclose(file);
            //return 2;

  /* initialize two vectors to store v1, v2 to store vertices */
     igraph_vector_init(&v1, (igraph_vcount(&graph)) );
     igraph_vector_init(&v2, (igraph_vcount(&graph)) );

    n = igraph_vcount(&graph); /* number of vertices in the graph */
    m = igraph_ecount(&graph); /* number of edges in the graph */


float rhs[m][n1+n2];
    for (i=0; i<m; i++){
                 igraph_edge(&graph, i, &from, &to);
                 igraph_neighbors(&graph, &v1, from, IGRAPH_ALL);
                 igraph_neighbors(&graph, &v2, to, IGRAPH_ALL);
                 n2 = igraph_vector_size(&v2);
                 n1 = igraph_vector_size(&v1);


                 for (j=0; j < n2 ; j++) {
                     rhs[i][j] = rbf(to, (int) VECTOR(v2)[j]);
                     printf("%d %d %f\n", to, (int) VECTOR(v2)[j], rhs[i][j]);
                 }
                 for (j=0; j < n1; j++) {
                     rhs[i][j+n2] = rbf(from, (int) VECTOR(v1)[j]);
                     printf("%d %d %li %li %f\n", from, (int) VECTOR(v1)[j], j, j+n2, rhs[i][j+n2]);
                 }
printf("\n");
         }

  for (i=0; i<m; i++){
                 igraph_edge(&graph, i, &from, &to);
                 igraph_neighbors(&graph, &v1, from, IGRAPH_ALL);
                 igraph_neighbors(&graph, &v2, to, IGRAPH_ALL);
                 n2 = igraph_vector_size(&v2);
                 n1 = igraph_vector_size(&v1);
                 for (j=0; j < (n1+n2) ; j++) {
                        printf("%f", rhs[i][j]);
                  }  
                 printf("\n");

     }
}

最佳答案

n1n2rhs[m][n1+n2] 行之前未初始化。您的程序的所有行为可能/都是未定义的行为。

int ret, n1, n2;
... code that does not touches n1 nor n2 ...
float rhs[m][n1+n2];

变量n1n2使用前未初始化。它们用于声明可变长度数组VLA。编译器在 float rhs[m][n1 + n2] 行为 VLA 分配内存。 。由于变量未初始化,因此变量的值具有所谓的“不确定”值(读作:任何值)。编译器为 rhs 分配未知(对于程序员)数量的 float 。大批。 n1n2可能为负,在这种情况下会发生未定义的行为。您应该改用动态分配。

也不建议将 VLA 用于大数组(或根本使用它们)。您无法检测到故障。你不知道它是否会失败以及何时失败。它们不太可移植,并且在 C 中是可选的。不要使用 VLA,尽可能使用动态分配。

float **rhs = malloc(sizeof(rhs[0]) * m);
if (rhs == NULL) { /* handle error; */ }
for (i = ...) {
    .. later...
    rhs[i] = malloc(sizeof(rhs[i][0]) * (n1 + n2));
    if (rhs[i] == NULL) { /* handle error */ }
}
.. later ..
for (i = ... ){ 
    free(rhs[i]);
}
free(rhs);

注释:

  • 使用size_t类型来表示对象的大小和数组中元素的数量。 for (size_t i = 0; i < ... ; i++)是一个流行的习语。
  • Linux kernel coding style是 C 文件中很好的风格指南。
  • 来自 Linux 内核编码风格:“局部变量的数量 [...] 不应超过 5-10,否则你会做错什么”。
  • 始终尝试在启用所有(理智)警告的情况下进行编译。尝试修复所有警告。
  • igraph_bool_t false; “false”是stdbool.h中定义的宏。 。我建议重命名变量名称,以防您稍后想要包含 stdbool.h .

关于c - 访问数组中存储的元素时出现奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56003688/

相关文章:

c - GDB调试中的问题

Python数组中范围的最大总和

javascript - 按与另一个值相关的值的升序对对象数组进行排序

javascript - 将数组转换为嵌套对象 javascript

python - 我将如何迭代 Pandas 系列并将其与单个 float 进行比较?

c - 以十六进制和八进制打印一个带符号的 64 位整数

c - WM_SYSCOLORCHANGE 消息的含义

c - 简单字符设备驱动程序/模块 - Linux RedHat 8 (2.4.18) 在 ./module_unload 后出现 VM 段错误

Java程序跳过for循环

javascript - 延迟 for 循环不断返回相同的值