我看到过人们的代码像这样:
char *str = NULL;
我也看过这个问题,
char *str;
我想知道,初始化字符串的正确方式是什么?以及何时应该使用带有和不带有NULL的字符串初始化?
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 */
str2
(指向字符串字面量)未被修改,而str3
在堆栈上分配(或者在其他地方分配,这取决于代码放置的位置),该字面量仅用于初始化。 - Matteo Italiastr3
是一个数组,不是指针!该文字串用于初始化,它被复制到缓冲区(即str3
)中,编译器会自动调整数组大小以容纳该字符串。例如,在此处查看:http://msdn.microsoft.com/en-us/library/7w7xccx8%28VS.80%29.aspx。 - Matteo Italiastr3
的类型为 char[]
,一旦使用字符串字面值初始化为 char[38]
,它就变成了完整的类型。这种类型是可修改的左值。您没有修改字符串字面值,而是修改了一个具有与字符串字面值相同类型和内容的左值。 - dreamlax这是一个关于C语言变量的一般性问题,不仅限于char指针。
在声明变量时立即进行初始化被认为是最佳实践。例如:
char *str = NULL;
使用空值是一件好事。这样你就不会有未知值的变量。例如,如果你在代码中稍后执行以下操作:
if(str != NULL)
doBar(str);
会发生什么?str处于未知状态(几乎肯定不是NULL)
请注意,静态变量将自动初始化为零/ NULL。从问题中不清楚您是否在询问局部变量还是静态变量。
全局变量由编译器初始化为默认值,但局部变量必须初始化。
这完全取决于你将如何使用它。在下面的情况下,不初始化变量更有意义:
int count;
while ((count = function()) > 0)
{
}
因为如果你传递给free()一个NULL值,它不会执行任何操作,所以你可以像这样简化你的程序:
char *str = NULL;
if ( somethingorother() )
{
str = malloc ( 100 );
if ( NULL == str )
goto error;
}
...
error:
cleanup();
free ( str );
未初始化的指针应被视为未定义,因此为避免使用未定义值而导致错误,最好始终使用
char *str = NULL;
同样也因为
char *str;
这只是一个未分配的指针,指向某个地方,如果您忘记分配它,使用时会导致大多数问题,您仍然需要分配它(或复制另一个指针)。
这意味着您可以选择:
NULL
(这是一种经验法则)不要在声明时将所有指针变量都初始化为NULL,以防万一。
如果您尝试使用未初始化的指针变量,编译器会发出警告,除非您通过地址将其传递给函数(通常这样做是为了给它赋值)。
将指针初始化为NULL并不等同于将其初始化为一个合理的值,将其初始化为NULL只会禁用编译器告诉您未将其初始化为合理值的能力。
仅在声明时将指针初始化为NULL,如果您不这样做会收到编译器警告,或者您正在通过地址将它们传递给期望它们为NULL的函数。
如果您无法在同一屏幕中看到指针变量的声明和第一次赋值的位置,则说明您的函数太大了。
static const char str[] = "str";
或者
static char str[] = "str";
你的第一个片段是带初始化的变量定义;第二个片段是不带初始化的变量定义。
正确初始化字符串的方法是在定义时提供一个初始化器。将其初始化为NULL或其他内容取决于您想要做什么。
还要注意您所谓的“字符串”。在C语言中没有这样的类型:通常在C语言上下文中,“字符串”意味着“[某些数量的]字符数组”。在上面的代码片段中,您有指向char的指针。
假设您有一个程序,它想要在argv [1]中获取用户名并将其复制到字符串“name”中。当您定义name
变量时,可以将其保持未初始化状态,或将其初始化为NULL(如果它是指向char的指针),或使用默认名称进行初始化。
int main(int argc, char **argv) {
char name_uninit[100];
char *name_ptr = NULL;
char name_default[100] = "anonymous";
if (argc > 1) {
strcpy(name_uninit, argv[1]); /* beware buffer overflow */
name_ptr = argv[1];
strcpy(name_default, argv[1]); /* beware buffer overflow */
}
/* ... */
/* name_uninit may be unusable (and untestable) if there were no command line parameters */
/* name_ptr may be NULL, but you can test for NULL */
/* name_default is a definite name */
}