正如您在C中所知,我们可以像这样初始化字符串变量:
char text[1024] =
"Hello "
"World";
但是,如果我有一个返回单词" World"?
的函数怎么办?char text[1024] =
"Hello "
World();
在我看来,在C中是不可能的。 请确认。
答案 0 :(得分:2)
你想要什么是不可能的。
分配运算符的L值需要是可修改的,而数组则不是。
来自C11标准:
<强> 6.5.16 / 2 强>
赋值运算符应具有可修改的左值作为其左操作数。
唯一的例外是在初始化期间使用文字作为R值:
char text[1024] = "Hello ""World";
来自C11标准:
<强> 6.7.9 / 14 强>
字符类型数组可以用字符串文字或UTF-8字符串初始化 文字,可选择括在括号中。字符串文字的连续字节(包括 如果有空间或数组的大小未知,则终止空字符)初始化 数组的元素。
答案 1 :(得分:1)
如果World()
总是返回“World”,则将其定义为宏:
#define World "World"
然后做:
char text[1024] =
"Hello "
World; //Without parentheses
修改强>
您希望执行的字符串连接是由C预处理器完成的。您实际上正在寻找两个字符串的运行时串联,这可以通过多种方式执行。最简单的一个是strcat
函数实现的,但初始化应该由函数显式执行:
char text[1024];
void init_text() {
strcpy(text, "Hello ");
strcat(text, World()); //World() defined somewhere else
}
替代使用sprintf
:
void init_text() {
sprintf(text, "Hello %s", World());
}
然后在main
函数中,在开头调用init_text()
:
int main() {
init_text();
...
}
答案 2 :(得分:0)
在标准C中,无法使用某些特定于运行时的行为来初始化某些内容。因此,标准的可移植方法是通过在main
的开头调用函数来初始化数据,作为answered by Claudix。
但是,如果您正在使用某些最新的GCC编译器(或Clang/LLVM),则在某些系统(包括Linux和可能的其他POSIX系统)上可能会使用某些constructor attribute on function。所以你要声明:
static void init_text(void) __attribute__((constructor));
并在Claudix's answer 中定义init_text
,而不必在main
中调用它:因为它具有constructor
属性,它会如果它出现在动态链接的插件或库中,则会在main
之前神奇地调用,或者在dlopen(3)期间调用。
更便携的技巧可能是让一个函数返回该文本,该函数将在第一次调用时初始化它。因此,不是使用text
,而是在任何地方调用get_my_text()
(可能将#define text get_my_text()
放入标题中,但出于可读性原因,我不建议这样做,因此请更换每次出现的text
1}} get_my_text()
...),并将其定义为:
const char*get_my_text() {
static char textbuf[1024];
if (textbuf[0]) {
// already initialized, so return it
return textbuf;
};
snprintf(textbuf, sizeof(textbuf), "Hello %s", World());
return textbuf;
}
请注意,这样的技巧在多线程程序中不可靠:两个线程可能同时运行get_my_text
,并且您有一个数据race。在多线程应用程序中使用例如pthread_once
您甚至可以在头文件中将get_my_text
定义为static inline
函数。
PS总是更喜欢snprintf(3)到sprintf
以避免buffer overflows。另请注意,在标准C ++中,任何static
或具有某些给定constructor的全局数据在 main
之前初始化 ...因此GCC函数属性的名称。