在 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 个位置的指针。
所以,总结一下:我的主要问题是:
- 为什么我有““s”:初始化需要用大括号括起来的初始化列表”? (调试器重复了两次)。这不是应该初始化字符串的方式(使用花括号“{}”)。字符串是用“”初始化的,我错了吗?
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
免责声明:这只是整个算法的一部分,但由于遇到了很多错误,我决定分而治之,因此,我从以下代码开始。 (以下代码的目标:创建一个除以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 个位置的指针。
所以,总结一下:我的主要问题是:
- 为什么我有““s”:初始化需要用大括号括起来的初始化列表”? (调试器重复了两次)。这不是应该初始化字符串的方式(使用花括号“{}”)。字符串是用“”初始化的,我错了吗?
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