C语言 在 C 中初始化字符串的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4083239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Proper way to initialize a string in C
提问by foobar01
I've seen people's code as:
我已经看到人们的代码为:
char *str = NULL;
and I've seen this is as well,
我也看到了,
char *str;
I'm wonder, what is the proper way of initializing a string? and when are you supposed to initialize a string w/ and w/out NULL?
我想知道,初始化字符串的正确方法是什么?你什么时候应该初始化一个带和不带 NULL 的字符串?
回答by paxdiablo
You're supposed to set it before using it. That's the only rule you haveto follow to avoid undefined behaviour. Whether you initialise it at creation time or assign to it just before using it is not relevant.
你应该在使用它之前设置它。这是您必须遵循的唯一规则,以避免未定义的行为。无论您是在创建时初始化它还是在使用它之前分配给它都无关紧要。
Personally speaking, I prefer to never have variables set to unknown values myself so I'll usually do the first one unless it's set in close proximity (within a few lines).
就个人而言,我更喜欢自己永远不要将变量设置为未知值,所以我通常会做第一个,除非它设置得很近(在几行内)。
In fact, with C99, where you don't have to declare locals at the tops of blocks any more, I'll generally defer creating it until it's needed, at which point it can be initialised as well.
事实上,在 C99 中,您不必再在块的顶部声明局部变量,我通常会推迟创建它,直到需要它,此时它也可以被初始化。
Note that variables are given default values under certain circumstances (for example, if they're static storage duration such as being declared at file level, outside any function).
请注意,变量在某些情况下会被赋予默认值(例如,如果它们是静态存储持续时间,例如在文件级别声明,在任何函数之外)。
Local variables do not have this guarantee. So, if your second declaration above (char *str;) is inside a function, it may have rubbish in it and attempting to use it will invoke the afore-mentioned, dreaded, undefined behaviour.
局部变量没有这个保证。所以,如果你上面的第二个声明 ( char *str;) 在一个函数内,它可能有垃圾,尝试使用它会调用上述的、可怕的、未定义的行为。
The relevant part of the C99 standard 6.7.8/10:
C99标准的相关部分6.7.8/10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
- if it has pointer type, it is initialized to a null pointer;
- if it has arithmetic type, it is initialized to (positive or unsigned) zero;
- if it is an aggregate, every member is initialized (recursively) according to these rules;
- if it is a union, the first named member is initialized (recursively) according to these rules.
如果没有显式初始化具有自动存储持续时间的对象,则其值是不确定的。如果没有显式初始化具有静态存储持续时间的对象,则:
- 如果是指针类型,则初始化为空指针;
- 如果它有算术类型,则初始化为(正或无符号)零;
- 如果是聚合,则根据这些规则(递归地)初始化每个成员;
- 如果是联合,则根据这些规则(递归地)初始化第一个命名成员。
回答by Matteo Italia
I'm wonder, what is the proper way of initializing a string?
我想知道,初始化字符串的正确方法是什么?
Well, since the second snippet defines an uninitializedpointer to string, I'd say the first one. :)
好吧,由于第二个代码段定义了一个未初始化的字符串指针,我会说第一个。:)
In general, if you want to play it safe, it's good to initialize to NULLall pointers; in this way, it's easy to spot problems derived from uninitialized pointers, since dereferencing a NULLpointer will yield a crash (actually, as far as the standard is concerned, it's undefined behavior, but on every machine I've seen it's a crash).
一般来说,如果你想安全一点,初始化为NULL所有指针是好的;通过这种方式,很容易发现源自未初始化指针的问题,因为取消引用NULL指针会导致崩溃(实际上,就标准而言,这是未定义的行为,但在我见过的每台机器上都是崩溃)。
However, you should not confuse a NULLpointer to string with an empty string: a NULLpointer to string means that that pointer points to nothing, while an empty string is a "real", zero-length string (i.e. it contains just a NULcharacter).
但是,您不应将NULL指向字符串的指针与空字符串混淆:指向字符串的NULL指针意味着该指针不指向任何内容,而空字符串是“真正的”零长度字符串(即它仅包含一个NUL字符)。
char * str=NULL; /* NULL pointer to string - there's no string, just a pointer */
const char * str2 = ""; /* Pointer to a constant empty string */
char str3[] = "random text to reach 15 characters ;)"; /* String allocated (presumably on the stack) that contains some text */
*str3 = 0; /* str3 is emptied by putting a NUL in first position */
回答by pm100
this is a general question about c variables not just char ptrs.
这是关于 c 变量的一般问题,而不仅仅是 char ptr。
It is considered best practice to initialize a variable at the point of declaration. ie
在声明点初始化变量被认为是最佳实践。IE
char *str = NULL;
is a Good Thing. THis way you never have variables with unknown values. For example if later in your code you do
是一件好事。这样你就永远不会有未知值的变量。例如,如果稍后在您的代码中执行
if(str != NULL)
doBar(str);
What will happen. str is in an unknown (and almost certainly not NULL) state
会发生什么。str 处于未知(几乎可以肯定不是 NULL)状态
Note that static variables will be initialized to zero / NULL for you. Its not clear from the question if you are asking about locals or statics
请注意,静态变量将为您初始化为零/NULL。如果您询问当地人或静态,则从问题中不清楚
回答by Max
Global variables are initialized with default values by a compiler, but local variables must be initialized.
全局变量由编译器用默认值初始化,但局部变量必须被初始化。
回答by Hyman
an unitialized pointer should be considered as undefined so to avoid generating errors by using an undefined value it's always better to use
一个未定义的指针应该被认为是未定义的,这样为了避免使用未定义的值产生错误,最好使用
char *str = NULL;
also because
也因为
char *str;
this will be just an unallocated pointer to somewhere that will mostly cause problems when used if you forget to allocate it, you will need to allocate it ANYWAY (or copy another pointer).
这将只是一个未分配的指针,指向某个地方,如果您忘记分配它,在使用时通常会导致问题,您无论如何都需要分配它(或复制另一个指针)。
This means that you can choose:
这意味着您可以选择:
- if you know that you will allocate it shortly after its declaration you can avoid setting it as
NULL(this is a sort of rule to thumb) - in any other case, if you want to be sure, just do it. The only real problem occurs if you try to use it without having initialized it.
- 如果您知道将在声明后不久分配它,则可以避免将其设置为
NULL(这是一种经验法则) - 在任何其他情况下,如果你想确定,就去做吧。如果您在未初始化的情况下尝试使用它,则会出现唯一真正的问题。
回答by user207421
It depends entirely on how you're going to use it. In the following, it makes more sense notto initialize the variable:
这完全取决于您将如何使用它。在下面,不初始化变量更有意义:
int count;
while ((count = function()) > 0)
{
}
回答by Martin Broadhurst
Don't initialise all your pointer variables to NULL on declaration "just in case".
不要在声明“以防万一”时将所有指针变量初始化为 NULL。
The compiler will warn you if you try to use a pointer variable that has not been initialised, except when you pass it by address to a function (and you usually do that in order togive it a value).
如果您尝试使用尚未初始化的指针变量,编译器会警告您,除非您通过地址将其传递给函数(并且您通常这样做是为了给它一个值)。
Initialising a pointer to NULL is not the same as initialising it to a sensiblevalue, and initialising it to NULL just disables the compiler's ability to tell you that you haven'tinitialised it to a sensible value.
将指针初始化为 NULL 与将其初始化为合理值不同,将其初始化为 NULL 只会禁用编译器告诉您尚未将其初始化为合理值的能力。
Only initialise pointers to NULL on declaration if you get a compiler warning if you don't, or you are passing them by address to a function that expects them to be NULL.
如果您没有收到编译器警告,或者您通过地址将它们传递给期望它们为 NULL 的函数,则仅在声明时初始化指向 NULL 的指针。
If you can't see both the declaration of a pointer variable and the point at which it is first given a value in the same screen-full, your function is too big.
如果在同一个全屏中看不到指针变量的声明和它第一次被赋值的点,那么你的函数太大了。
回答by Teme
static const char str[] = "str";
or
或者
static char str[] = "str";
回答by onemasse
Because free() doesn't do anything if you pass it a NULL value you can simplify your program like this:
因为 free() 不做任何事情,如果你给它传递一个 NULL 值,你可以像这样简化你的程序:
char *str = NULL;
if ( somethingorother() )
{
str = malloc ( 100 );
if ( NULL == str )
goto error;
}
...
...
error:
cleanup();
free ( str );
If for some reason somethingorother() returns 0, if you haven't initialized str you will free some random address anywhere possibly causing a failure.
如果由于某种原因 somethingorother() 返回 0,如果您尚未初始化 str ,您将在任何可能导致失败的地方释放一些随机地址。
I apologize for the use of goto, I know some finds it offensive. :)
我为使用 goto 表示歉意,我知道有些人觉得它令人反感。:)
回答by Matt
By proper you mean bug free? well, it depends on the situation. But there are some rules of thumb I can recommend.
正确的意思是没有错误?嗯,这取决于情况。但是我可以推荐一些经验法则。
Firstly, note that strings in C are not like strings in other languages.
首先,请注意 C 中的字符串与其他语言中的字符串不同。
They are pointers to a block of characters. The end of which is terminated with a 0 byte or NULL terminator. hence null terminated string.
它们是指向字符块的指针。其结尾以 0 字节或 NULL 终止符终止。因此空终止的字符串。
So for example, if you're going to do something like this:
例如,如果您要执行以下操作:
char* str;
gets(str);
or interact with str in any way, then it's a monumental bug. The reason is because as I have just said, in C strings are not strings like other languages. They are just pointers. char* str is the size of a pointer and will always be.
或以任何方式与 str 交互,那么这是一个巨大的错误。原因是因为正如我刚才所说的,在 C 中字符串不像其他语言那样是字符串。它们只是指针。char* str 是指针的大小,并且永远是。
Therefore, what you need to do is allocate some memory to hold a string.
因此,您需要做的是分配一些内存来保存字符串。
/* this allocates 100 characters for a string
(including the null), remember to free it with free() */
char* str = (char*)malloc(100);
str[0] = 0;
/* so does this, automatically freed when it goes out of scope */
char str[100] = "";
However, sometimes all you need is a pointer.
e.g.
但是,有时您只需要一个指针。
例如
/* This declares the string (not intialized) */
char* str;
/* use the string from earlier and assign the allocated/copied
buffer to our variable */
str = strdup(other_string);
In general, it really depends on how you expect to use the string pointer. My recommendation is to either use the fixed size array form if you're only going to be using it in the scope of that function and the string is relatively small. Or initialize it to NULL. Then you can explicitly test for NULL string which is useful when it's passed into a function.
通常,这实际上取决于您期望如何使用字符串指针。我的建议是,如果您只打算在该函数的范围内使用它并且字符串相对较小,则要么使用固定大小的数组形式。或将其初始化为 NULL。然后,您可以显式测试 NULL 字符串,这在将其传递给函数时很有用。
Beware that using the array form can also be a problem if you use a function that simply checks for NULL as to where the end of the string is. e.g. strcpy or strcat functions don't care how big your buffer is. Therefore consider using an alternative like BSD's strlcpy & strlcat. Or strcpy_s & strcat_s (windows).
请注意,如果您使用的函数只是检查 NULL 以了解字符串的结尾位置,那么使用数组形式也可能会出现问题。例如 strcpy 或 strcat 函数不关心你的缓冲区有多大。因此,请考虑使用 BSD 的 strlcpy 和 strlcat 等替代方案。或 strcpy_s & strcat_s (windows)。
Many functions expect you to pass in a proper address as well. So again, be aware that
许多函数也希望您传入正确的地址。再次提醒,
char* str = NULL;
strcmp(str, "Hello World");
will crash big time because strcmp doesn't like having NULL passed in.
会崩溃很长时间,因为 strcmp 不喜欢传入 NULL。
You have tagged this as C, but if anyone is using C++ and reads this question then switch to using std::string where possible and use the .c_str() member function on the string where you need to interact with an API that requires a standard null terminated c string.
您已将其标记为 C,但如果有人使用 C++ 并阅读此问题,则在可能的情况下切换到使用 std::string 并在需要与需要与 API 交互的字符串上使用 .c_str() 成员函数标准的空终止 c 字符串。

