在C中初始化字符串的正确方法

在C中初始化字符串的正确方法,c,string,char,C,String,Char,我认为人们的准则是: char *str = NULL; 我也看到了这一点 char *str; 我想知道,初始化字符串的正确方法是什么?什么时候应该初始化一个带/和w/out NULL的字符串?这是一个关于c变量的一般问题,而不仅仅是char ptr 在声明点初始化变量被认为是最佳实践。即 char *str = NULL; 这是一件好事。这样你就不会有未知值的变量。例如,如果以后在代码中 if(str != NULL) doBar(str); 将会发生什么。str处于未知(几乎肯定

我认为人们的准则是:

char *str = NULL;
我也看到了这一点

char *str;

我想知道,初始化字符串的正确方法是什么?什么时候应该初始化一个带/和w/out NULL的字符串?

这是一个关于c变量的一般问题,而不仅仅是char ptr

在声明点初始化变量被认为是最佳实践。即

char *str = NULL;
这是一件好事。这样你就不会有未知值的变量。例如,如果以后在代码中

if(str != NULL)
 doBar(str);
将会发生什么。str处于未知(几乎肯定不是NULL)状态


请注意,静态变量将被初始化为零/空。这个问题不清楚你是在问局部变量还是静态变量,你应该在使用它之前设置它。这是避免未定义行为必须遵循的唯一规则。无论您是在创建时初始化它,还是在使用它之前分配给它,都没有关系

就我个人而言,我更喜欢自己永远不要将变量设置为未知值,所以我通常会做第一个,除非它设置得非常接近(在几行之内)

事实上,对于C99,您不再需要在块的顶部声明局部变量,我通常会推迟创建它,直到需要时,在这一点上它也可以初始化

请注意,在某些情况下(例如,如果变量是静态存储持续时间,例如在文件级别声明,则在任何函数之外),变量都是默认值

局部变量没有这种保证。因此,如果您上面的第二个声明(
char*str;
)在一个函数中,它可能有垃圾,尝试使用它将调用上述可怕的未定义行为

C99标准的相关部分
6.7.8/10

如果没有显式初始化具有自动存储持续时间的对象,则其值是不确定的。如果没有显式初始化具有静态存储持续时间的对象,则:

  • 如果有指针类型,则初始化为空指针
  • 如果它有算术类型,则初始化为(正或无符号)零
  • 如果是聚合,则根据这些规则(递归地)初始化每个成员
  • 如果是联合,则根据这些规则(递归地)初始化第一个命名成员

编译器使用默认值初始化全局变量,但必须初始化局部变量。

应将单位化指针视为未定义指针,以避免使用未定义值产生错误,最好使用未定义值

char *str = NULL;
也因为

char *str;
这将只是一个未分配的指针,指向在使用时会导致问题的地方。如果您忘记分配它,您将需要分配它(或复制另一个指针)

这意味着您可以选择:

  • 如果您知道在声明后不久将分配它,您可以避免将其设置为
    NULL
    (这是一种经验法则)
  • 在任何其他情况下,如果你想确定,就去做吧。如果您在没有初始化的情况下尝试使用它,则会出现唯一真正的问题
我想知道,初始化字符串的正确方法是什么? 好的,因为第二个代码段定义了一个未初始化的字符串指针,所以我认为是第一个。:)

一般来说,如果您想安全起见,最好将所有指针初始化为
NULL
all指针;通过这种方式,很容易发现来自未初始化指针的问题,因为取消引用
NULL
指针将导致崩溃(实际上,就标准而言,这是未定义的行为,但在我见过的每台机器上都是崩溃)

但是,您不应将指向字符串的
NULL
指针与空字符串混淆:指向字符串的
NULL
指针意味着该指针不指向任何内容,而空字符串是一个“实”零长度字符串(即它只包含
NUL
字符)


您的第一个代码段是带有初始化的变量定义;第二个代码段是一个没有初始化的变量定义

初始化字符串的正确方法是在定义字符串时提供初始值设定项。将其初始化为NULL或其他值取决于您要对其执行的操作

还要注意你所说的“字符串”
C
没有这样的类型:在
C
上下文中,通常“string”表示“字符的数组”。上面的代码段中有指向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 */
}

这完全取决于你将如何使用它。在下文中,不初始化变量更有意义:

int count;
while ((count = function()) > 0)
{
}

你说的正确是指没有bug?嗯,这要视情况而定。但我可以推荐一些经验法则

首先,请注意C中的字符串与其他语言中的字符串不同

它们是指向字符块的指针。其结尾以0字节或空终止符终止。因此,字符串以null结尾

举个例子,如果你要做这样的事情:

char* str;  
gets(str);
char *str = NULL;

if ( somethingorother() )
{
    str = malloc ( 100 );

    if ( NULL == str )
        goto error;
}
或者以任何方式与str交互,那么它就是一个巨大的bug。原因是,正如我刚才所说,在C语言中,字符串不像其他语言那样是字符串。它们只是指针。char*str是指针的大小,并且始终为

因此,您需要做的是分配一些内存来保存字符串

/* 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] = "";
然而,有时您只需要一个指针。
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);
char* str = NULL;
strcmp(str, "Hello World");
static const char str[] = "str";
static char str[] = "str";
char *str = NULL;

if ( somethingorother() )
{
    str = malloc ( 100 );

    if ( NULL == str )
        goto error;
}
error:

cleanup();
free ( str );