-6

我有指针数组“item”,我需要动态地为其赋值,所有数组项都具有相同的值,这是第二个 for 循环中显示的最后一个值

int h = 0;
char* item[6];
char x[] = "sss";

for (h = 0; h < 6; h++)
{
    item[h] = (char*)malloc(sizeof(char*));
    sprintf(x, "%s (%d)", "item", h);
    item[h] = &x[0];
    printf("item= %s\r\n", item[h]);
}
for (h = 0; h < 6; h++)
{
    printf("item22222= %s\r\n", item[h]);
}

当我运行此代码时,我得到

item= item (0) 
item= item (1) 
item= item (2) 
item= item (3) 
item= item (4) 
item= item (5) 
item22222= item (5) 
item22222= item (5) 
item22222= item (5) 
item22222= item (5) 
item22222= item (5) 
item22222= item (5) 

为什么在第二个循环中重复相同的结果?我原以为它看起来类似于第一个循环 ( item (1), item (2), ...)。请帮助我在我的代码/逻辑中找到错误。

4

2 回答 2

1

您的代码不起作用,因为您犯了几个错误。

1)您没有为缓冲区分配足够的空间x

char x[]="sss";

这意味着将为x. 但是在你的sprintf你写一个更大的字符串到那个位置。你很幸运,它不仅仅是段错误(好吧它不适合我)。

2)您不会将字符串复制到新空间中;x相反,在每个循环中,您都会用新字符串覆盖相同的内存位(缓冲区)。由于每个都item[h]指向相同的字符串,因此它们都会在第二个循环中为您提供相同的结果。

稍微打破第二点(并假设您x最初做得足够大,通过在初始化期间放入更多的 sssssssssss ):

storage buffer x contains    item[h] points to    so when I print it I get
sssssssssssssssss                 nothing
item = item (0)              storage buffer x       item = item(0)
item = item (1)              storage buffer x       item = item(1)
item = item (2)              storage buffer x       item = item(2)
item = item (3)              storage buffer x       item = item(3)
item = item (4)              storage buffer x       item = item(4)
item = item (5)              storage buffer x       item = item(5)

当我再次绕过循环时,item[h] 仍然指向 x,它仍然包含

item = item (5)

要使其正常工作,您需要为要存储的每个字符串分配空间(不仅仅是指向它的指针......):

#include<stdio.h>
#include<stdlib.h>

int main(void){
  int h = 0;
  char* item[6];
  char *x; 

  for (h = 0; h < 6; h++)
  {
    item[h] = (char*)malloc(sizeof(char*));
    x = (char*)malloc(50); // big enough
    sprintf(x, "%s (%d)", "item", h);
    item[h] = x;
    printf("item= %s\r\n", item[h]);
  }

  for (h = 0; h < 6; h++)
  {
    printf("item22222= %s\r\n", item[h]);
  }

}

输出:

item= item (0)
item= item (1)
item= item (2)
item= item (3)
item= item (4)
item= item (5)
item22222= item (0)
item22222= item (1)
item22222= item (2)
item22222= item (3)
item22222= item (4)
item22222= item (5)

当然,您将很难释放像这样分配的内存......但是在一个小程序中,您可以让操作系统在退出时完成清理工作。

编辑由于操作似乎malloc引起了麻烦,这里有一种使程序工作的方法。它涉及“预分配”所使用的内存,而不是动态地这样做。当然,这不适用于大量数据,但是除非并且直到您发现为什么即使是非常小的数据也会出现问题,否则malloc运行更大的程序几乎是不走运的。所以这只是为了指导。

回想一下,您正试图将文本写入“项目”数组。如果我们将其设为 2D 数组char,并预先分配数据,那么我们就完成了。技巧: 的地址item[h][0]可以找到为&item[h][0]item[h]

这是代码:

#include <stdio.h>

int main(void){
  int h = 0;
  char item[6][50]; // array of 6 strings of up to 50 characters

  for (h = 0; h < 6; h++)
    {
      sprintf(item[h], "%s (%d)", "item", h);
      printf("item= %s\r\n", item[h]);
    }

  for (h = 0; h < 6; h++)
    {
      printf("item22222= %s\r\n", item[h]);
    }

  }

我希望你有更多的运气......它给了我和以前一样的输出。

另一个编辑

由于潜在的问题(malloc失败)仍然存在,我们可以尝试对其进行故障排除。请尝试运行此程序,看看会发生什么:

#include <stdio.h>
#include <stdlib.h>
int main(void){
  char* c;
  int ii;
  for(ii=1;ii<=50;ii++) {
    c = malloc(ii);
    printf("with ii = %d, c is %p\n", ii, c);
    if(c!=NULL) free(c);
    c = malloc(sizeof(int) * ii);
    printf("allocating in chunks of 'sizeof(int)': c is now %p\n", c);
    if (c!=NULL) free(c);
  }
}

我们应该看看是否/何时malloc成功或失败(它似乎在您的原始片段中工作......所以现在我们需要找出它何时/为什么会中断......)

于 2013-06-18T22:25:15.533 回答
1

您正在分配一个新的大小内存块sizeof(char*)*10(假设您想要足够的空间容纳 10 个字符,而不是 10 个指针,应该是sizeof(char)*10),然后让item数组中的每个索引指向一个循环中的新内存块。一切都很好,直到您item用代码覆盖数组指向的位置item[h]=&x[0]。这使得项数组中的每个指针都指向相同的内存位置 ( x)。只需 sprintf 直接进入新内存即可。另外,因为您正在处理字符串,所以请确保 null 终止。此外,您需要确保在大小为 10 的缓冲区中写入的字符不超过 9 个。此外,除非需要使用 c 字符串,否则请采纳 chris 的建议并使用 std::string。

int h = 0;
char* item[6];

for (h = 0; h < 6; h++)
{
  item[h] = (char*)calloc(20,sizeof(char));
  sprintf(item[h], "item (%d)", h);
  printf("item= %s\n", item[h]);
}
for (h = 0; h < 6; h++)
{
  printf("item2= %s\n", item[h]);
}
于 2013-06-18T22:14:26.427 回答