数组条目在C中被覆盖

我想将整数数组转换为字符串数组。例如,如果arr[] = {1,2,3,4,5},我想以arr2[] = {"1","2","3","4","5"}结尾。此函数可以正常工作,直到退出for循环,在循环中所有数组条目都被最后一个条目的值覆盖。为什么会发生这种情况的任何想法?

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

#define SIZE 5
int main(){
    int nums[] = {1,5};
    char **strings = (char **)malloc(SIZE * sizeof(char*));

    for(int i = 0; i < SIZE; i++){
        char temp[20];
        sprintf(temp,"%d",nums[i]);
        strings[i] = temp;
        //prints correct values here
        printf("%s\n",strings[i]);
    }

    for(int i = 0; i < SIZE; i++){
        //prints wrong values here
        printf("%s\n",strings[i]);
    }

    free(strings);
    return 0;
}
wangshaozhuang 回答:数组条目在C中被覆盖

问题是strings[i] = temp;。这会将temp分配给strings[i],但是temp是局部变量,其作用域是循环块,并且在该块终止后无效。

您需要为每个字符串malloc存储以保存复制的值(完成后free)。 tmp也是不必要的,因为我们可以sprintf直接进入指针。

SIZE = 5,但是您的数组只有4个成员,因此我们具有访问权限。我宁愿将此范围限定为它表示的数据,而不是使其成为全局常量。我还假设此数组将处理任意数据,因为按原样,与在循环中使用i + 1相比,它没有任何优势。

malloc(12)足以容纳32位整数字符串(sizeof char始终为1,我们需要'-''\0'字符的空间)。正如this comment中指出的那样,您可以使用sizeof(int) * CHAR_BIT / 3 + 2CHAR_BIT标头中定义了limits.h的缓冲区计算正确的大小。

顺便说一句,no need强制转换为malloc,并且最好使用sizeof(*strings)来防止指针类型在重构期间发生变化。

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

int main() {
    int nums[] = {1,2,3,4};
    int nums_size = 4;
    char **strings = malloc(nums_size * sizeof(*strings));

    for (int i = 0; i < nums_size; i++) {
        strings[i] = malloc(12);
        sprintf(strings[i],"%d",nums[i]);
    }

    for (int i = 0; i < nums_size; i++) { 
        printf("%s\n",strings[i]);
        free(strings[i]);
    }

    free(strings);
    return 0;
}
,

始终让编译器为您计数。

首先,我在宏--root-mode=upward下定义了一个宏COUNTOF,该宏在数组对象中生成的数量(而不是 bytes 的数量);应该随处使用。

第二,strdup()库函数复制字符串缓冲区-计算长度,分配正确的字节数,然后将字符串复制到其中。比滚动自己的要容易得多。

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

#define COUNTOF(x)   ( sizeof(x) / sizeof((x)[0]) )

int main(){
    int nums[] = {1,4};
    char **strings = malloc(COUNTOF(nums) * sizeof(*strings));

    for(int i = 0; i < COUNTOF(nums); i++){
        char temp[40];  // bigger than any plausible int
        sprintf(temp,nums[i]);
        strings[i] = strdup(temp);   // HERE
        printf("%s\n",strings[i]);
    }

    for(int i = 0; i < COUNTOF(nums); i++){
        //now prints correct value here :-)
        printf("%s\n",strings[i]);
    }

    return 0;
}
,

实际上不需要在运行时执行此操作。如果您遇到一些“ X宏”技巧,则可以在编译时执行此操作。

#define INIT_LIST \
   X(1) \
   X(2) \
   X(3) \
   X(4) \

#define STR(n) #n

#include <stdio.h>

int main (void)
{
  #define X(n) n,int nums[] = {INIT_LIST};
  #undef X

  #define X(n) STR(n),const char* str[] = {INIT_LIST};
  #undef X

  for(size_t i=0; i<sizeof(nums)/sizeof(*nums); i++)
  {
    printf("%d %s\n",nums[i],str[i]);
  }
}

INIT_LIST必须将所有初始化程序都包含为整数。经过预处理后,以上内容将扩展为:

#include <stdio.h>

int main (void)
{
  int nums[] = {1,4};
  const char* str[] = {"1","2","3","4"};

  for(size_t i=0; i<sizeof(nums)/sizeof(*nums); i++)
  {
    printf("%d %s\n",str[i]);
  }
}

就性能而言,这自然比使用堆分配的任何解决方案在天文速度上都要快。缺点是X宏可能很难读取。

本文链接:https://www.f2er.com/3136061.html

大家都在问