在 C 中,为什么我有“"s": 初始化需要用大括号括起来的初始化列表”?

in C, why do I have " "s": initialization requires a brace-enclosed initializer list"?

免责声明:这只是整个算法的一部分,但由于遇到了很多错误,我决定分而治之,因此,我从以下代码开始。 (以下代码的目标:创建一个除以10的余数(n%10)的字符串。目前还没有反转,我还没有做,因为我想先检查一下这段代码)。

(我在 visual studio 环境中使用 C 语言工作)。

我必须实现像 atoi 这样的函数(从字符串到数字),但我想做相反的事情(从数字到字符串)。但我有一个问题:

调试器指出在 malloc 的行中,我应该先初始化字符串(初始化需要用大括号括起来的初始化列表),

但我已经做到了,我已经将字符串初始化为一个常量(在第二行,我写了“这是测试种子”)(因为我需要使用一个字符串,所以我初始化了,然后我 malloc 它来写入 (unsigned int n) 的值。

我的程序应该是这样工作的:

(1) 函数取一个unsigned int常量(n),

(2) 函数创建数组的“原型”(以零结尾的字符串),

(3) 然后,我创建了一个没有检查条件的 for 循环,因为我将它添加到循环体内,

(4) 现在,基本思想是:每一步,循环使用 i 分配 1 个 sizeof(char)(所以 1 个位置)来存储 n/10 的第 i 个余数分配。 n 每一步取不同的值( n/=10; // 所以 n 假设除法的值)。如果 n/10 等于零,这意味着我已经到达循环的末尾,因为每个余数都在字符串中)。因此,我放了一个 break 语句,以便在 for 循环之外。

最后,该函数应该 return 指向字符串第 0 个位置的指针。

所以,总结一下:我的主要问题是:

 char* convert(unsigned int n) {
   char s[] = "this is the test seed";
     for (unsigned int i = 0; ; i++) {
         if (i == 0) {
             char s[] = malloc (1 * sizeof(char));
         }
         if (i != 0) {
             char s[] = malloc(i * sizeof(char));
         }
         if ((n / 10) == 0) {
             break;
        }
        s[i] = n % 10;
        n /= 10;
    }

    return s;
}

char s[] 是一个数组,因此需要一个大括号括起来的初始化列表(或字符串文字)。在 C 标准中,请参阅第 6.7.8 节(6.7.8.14 是字符类型数组的文字字符串的附加特例)。 char s[] = malloc(...); 既不是大括号括起来的初始化列表也不是文字字符串,编译器正确地将其报告为错误。

原因是char s[] = ...;声明了一个数组,这意味着编译器需要在编译时知道数组的长度。

也许您想要 char *s = malloc(...),因为标量(例如,指针)可以用赋值语句初始化(参见第 6.7.8.11 节)。

与您的实际问题无关,您编写的代码存在缺陷,因为您返回的是本地数组的值(第一个 s)。为避免编码时出现内存问题,请避免混合使用堆栈分配的内存、静态分配的字符串(例如:文字字符串)和 malloc 内存。如果将它们混合在一起,您将永远不知道可以对内存做什么或不能做什么(例如,您将不确定是否需要释放内存)。

一个完整的工作示例:

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

char *convert(unsigned n) {
    // Count digits of n (including edge-case when n=0).
    int len = 0;
    for (unsigned m=n; len == 0 || m; m /= 10) {
        ++len;
    }
    // Allocate and null-terminate the string.
    char *s = malloc(len+1);
    if (!s) return s;
    s[len] = '[=10=]';
    // Assign digits to our memory, lowest on the right.
    while (len > 0) {
        s[--len] = '0' + n % 10;
        n /= 10;
    }
    return s;
}

int main(int argc, char **argv) {
    unsigned examples[] = {0, 1, 3, 9, 10, 100, 123, 1000000, 44465656, UINT_MAX};
    for (int i = 0; i < sizeof(examples) / sizeof(*examples); ++i) {
        char *s = convert(examples[i]);
        if (!s) {
            return 2;
        }
        printf("example %d: %u -> %s\n", i, examples[i], s);
        free(s);
    }
    return 0;
}

它可以像这样 运行(注意非常有用的 -fsanitize 选项,这些选项非常宝贵,特别是如果您开始使用 C 编程)。

$ gcc -fsanitize=address -fsanitize=leak -fsanitize=undefined -o convert -Wall convert.c && ./convert
example 0: 0 -> 0
example 1: 1 -> 1
example 2: 3 -> 3
example 3: 9 -> 9
example 4: 10 -> 10
example 5: 100 -> 100
example 6: 123 -> 123
example 7: 1000000 -> 1000000
example 8: 44465656 -> 44465656
example 9: 4294967295 -> 4294967295