C: array of pointers pointing to the same value

时间:2016-04-12 00:36:41

标签: c arrays string pointers dereference

I'm writing an IP forwarding program, and I need to splice the following routing table into a char* array

  128.15.0.0    255.255.0.0    177.14.23.1
  137.34.0.0    255.255.0.0    206.15.7.2
  137.34.128.0  255.255.192.0  138.27.4.3
  137.34.0.0    255.255.224.0  139.34.12.4
  201.17.34.0   255.255.255.0  192.56.4.5
  27.19.54.0    255.255.255.0  137.7.5.6
  0.0.0.0       0.0.0.0        142.45.9.7

I have initialized an array of pointers to char* like so char *routing[128][128];, then I loop through each line, build a char temp[128] array which then get's assigned to routing as shown below.

In other words, each pointer in the routing array will point to an IP address.

char *routing[128][128];
char line[128], temp[128];
int i = 0, j = 0, token_count = 0, line_count = 0;
while(fgets(line, sizeof(line), routing_table) != NULL){
  // printf("%s\n", line);
  token_count = 0;
  for (i = 0; i < strlen(line); i++){
    if (line[i] != ' ' && token_count == 2){
      for (j = 0; j < 128; j++){
        if (line[i+j] == ' ')
          break;
        temp[j] = line[i+j];
      }
      i += j;
      routing[line_count][token_count] = temp; //ASSIGNMENT OCCURS HERE
      token_count++;
    }
    else if (line[i] != ' ' && token_count == 1){
      for (j = 0; j < 128; j++){
        if (line[i+j] == ' ')
          break;
        temp[j] = line[i+j];
      }
      i += j;
      routing[line_count][token_count] = temp;
      token_count++;
    }
    else if (line[i] != ' ' && token_count == 0){
      for (j = 0; j < 128; j++){
        if (line[i+j] == ' ')
          break;
        temp[j] = line[i+j];
      }
      i += j;
      routing[line_count][token_count] = temp;
      token_count++;
    }
  }
  line_count++;
}

The problem is that every time an assignment happens, it updates the entire array. So when I print out the array at the end, I get the last element repeated.

142.45.9.7

142.45.9.7

142.45.9.7

...

142.45.9.7

142.45.9.7

I figured I needed to dereference temp but that threw a warning and didn't even fix it.

What do I have wrong syntactically? Why are all pointers pointing to the same char string?

3 个答案:

答案 0 :(得分:2)

接近结尾,就在你增加token_count的地方之前,你就有这条线:

routing[line_count][token_count] = temp;

这就是你的问题。 temp是一个包含128个字符的数组 - 我们称之为C中的字符串,如果某处有一个空终结符。您依次将每个IP地址字符串复制到其中,然后对于每个IP地址字符串,将temp的地址分配给您的一个大二维指针数组中的一个插槽。所有这些指针,但它们都指向相同的实际缓冲区。

因此,在循环结束时,它们都指向您复制到temp的最后一个字符串。这不是你想要的,如果temp是函数中的本地,那么你真的遇到了麻烦。

你想要的是一个二维数组的实际char数组(每个16个字符就足以用于点缀四边形和一个空终止符) - 但是我在C上有点生疏并且不会冒险导致你误入歧途关于如何声明 - 或者你需要为现有二维数组中的每个字符串分配新内存。在许多C实现中,你会这样做:

routing[line_count][token_count] = strdup(temp);

strdup()是一个方便的函数,为你给它的字符串分配足够的内存,将字符串复制到该内存中,并返回指向它的指针。但它不是标准的一部分,所以在所有情况下都不能指望它。如果你正在为一个编译器编写它并且它就在那里,那么你们都已经设置好了(通常就是这种情况)。但是,如果您对可移植性有任何疑虑,here's a portable way to do the same thing

是否可移植,您现在正在分配内存,当您完成路由表时,您需要通过在您获得的每个指针上调用free(routing[i][j])来释放分配的内存从strdup()(或从其他一些更便携的功能)返回。

为此,你应该在分配任何东西之前调用它:

memset(routing, 0, sizeof(char) * 128 * 128);

...其中128和128是数组的两个维度(我将它放在我用于循环和声明的#defined常量中,如果我真的必须在C中执行此操作,并没有动态分配整个混乱)。如果你首先将整个事物设置为零,那么那里的每个指针都以NULL开头。然后当你遍历它以释放内存时,你可以循环遍历每个“行”释放每个指针,直到你点击NULL,然后停止。

答案 1 :(得分:2)

考虑另一种方法,它总是容易出错,解析命令行输出的ip地址,如ifconfig,route,ip等,为什么不用编程方式获取路由表信息呢?例如,在Linux上,RTNETLINK是操纵路由表的标准方法:

http://man7.org/linux/man-pages/man7/rtnetlink.7.html

它为您提供定义良好的结构中的所有信息。

在Windows上,您可以使用Win32 API执行相同的操作:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa365953(v=vs.85).aspx

答案 2 :(得分:0)

routing[line_count][token_count] = temp; //ASSIGNMENT OCCURS HERE

每次迭代时temp数组的内容可能不同。

temp数组的地址在整个程序执行过程中保持不变。

因此,您显然为routing数组中的每个条目分配了相同的值。