初始化char指针

时间:2009-11-02 10:19:27

标签: c pointers char-pointer

我有一个char指针,用于存储字符串。它稍后会在程序中使用。

我已声明并初始化为:

char * p = NULL;

我只是想知道这是不是很好的做法。我正在使用gcc 4.3.3。

12 个答案:

答案 0 :(得分:13)

是的,这是个好主意。 Google Code Style建议:

  1. 即使您现在不需要它们,也要初始化所有变量。
  2. NULLint的指针初始化为0,将float的指针初始化为0.0 - 只是为了更好的可读性。

    int i = 0;
    double x = 0.0;
    char* c = NULL;
    

答案 1 :(得分:4)

最好初始化所有变量。

答案 2 :(得分:4)

您不能将字符串存储在指针中。

您对mgt_dev_name的定义很好,但您需要将其指向某个字符串的空间。 malloc()该空格或使用先前定义的字符数组。

char *mgt_dev_name = NULL;
char data[4200];

/* ... */

mgt_dev_name = data; /* use array */

/* ... */

mgt_dev_name = malloc(4200);
if (mgt_dev_name != NULL) {
    /* use malloc'd space */
    free(mgt_dev_name);
} else {
    /* error: not enough memory */
}

答案 3 :(得分:3)

如果您在询问是否有必要,或者在将变量设置为其他内容之前将变量初始化为NULL是否是个好主意:没有必要将其初始化为NULL ,它对你的程序的功能没有任何影响。

请注意,在编程中,理解每一行代码都很重要 - 为什么它在那里以及它究竟在做什么。不知道他们的意思或不理解你为什么这么做而不做事。

答案 4 :(得分:3)

另一种选择是在代码中您可以访问其初始值的位置之前不定义变量。而不是那样做:

char *name = NULL;

...

name = initial_value;

我会改为:

...

char *name = initial_value;

然后,编译器将阻止您引用代码中没有值的部分中的变量。根据您的代码的具体情况,这可能并不总是可能的(例如,初始值在内部范围中设置,但变量具有不同的生命周期),在代码中尽可能晚地移动定义可以防止错误。

也就是说,这只允许从c99标准开始(它也是有效的C ++)。要在gcc中启用c99功能,您需要执行以下操作:

gcc -std=gnu99

或者如果您不希望gcc扩展到标准:

gcc -std=c99

答案 5 :(得分:3)

不,如果我正确理解你的背景,这不是一个好习惯。

如果你的代码实际上依赖于具有空指针初始值的mgt_dev_name,那么当然,将初始化程序包含在声明中是一个非常好的主意。即如果你不得不这样做

char *mgt_dev_name;

/* ... and soon after */
mgt_dev_name = NULL;

然后使用初始化而不是赋值

总是更好的主意
char *mgt_dev_name = NULL;

但是,只有在使用有意义的 有用的值初始化对象时,初始化才有用。您实际需要的值。在一般情况下,这只能在允许在代码中的任何一点声明的语言中实现,C99和C ++是这些语言的好例子。当你需要你的对象时,你通常已经知道该对象的适当的初始化器,因此可以很容易地得到一个带有良好初始化器的优雅声明。

另一方面,在C89 / 90中,声明只能放在块的开头。此时,在一般情况下,您将无法为所有对象创建有意义的初始值设定项。您是否应该使用某些内容(例如0NULL)初始化它们,只是为了让它们初始化?没有!!!永远不要在代码中做无意义的事情。无论各种“风格指南”告诉你什么,它都不会改进任何东西。实际上,无意义的初始化实际上可能会覆盖代码中的错误,使得发现和修复它们变得更加困难。

请注意,即使在C89 / 90中,争取更好的声明局部性总是有益的。即众所周知的良好实践指南指出:始终将变量尽可能地放在本地。不要在函数的最开头堆积所有本地对象声明,而是将它们移动到最小块的开头,该块尽可能紧密地包围对象的整个生命周期。有时,为了改善声明的局部性,引入一个虚构的,否则不必要的块甚至可能是个好主意。遵循此练习将帮助您在许多(如果不是大多数)情况下为您的对象提供有用的初始化程序。但是有些对象在C89 / 90中仍然没有初始化,因为在声明时你不会有一个好的初始化器。不要试图用“东西”初始化它们只是为了让它们初始化。这绝对没有任何好处,实际上可能会产生负面影响。

请注意,一些现代开发工具(例如MS Visual Studio 2005)将捕获代码调试版中对未初始化变量的运行时访问。即,这些工具可以帮助您在有可能获取有意义的值之前访问变量时检测情况,从而指示代码中的错误。但是,对变量进行无条件的过早初始化,基本上会破坏工具的这种能力,并将这些错误扫除在地毯下。

答案 6 :(得分:2)

此主题已在此处讨论过:

http://www.velocityreviews.com/forums/t282290-how-to-initialize-a-char.html

它指的是C ++,但它也可能对你有用。

答案 7 :(得分:0)

这个问题有几个很好的答案,其中一个已被接受。无论如何,我要回答是为了扩展实用性。

是的,最好将指针初始化为NULL,并在不再需要(即释放)后将指针设置为NULL。

在任何一种情况下,能够在解除引用之前测试指针是非常实用的。假设你有一个看起来像这样的结构:

struct foo {
    int counter;
    unsigned char ch;
    char *context;
};

然后编写一个生成多个线程的应用程序,所有这些线程都通过使用互斥来安全地运行在一个分配的foo结构上。

线程A获取对foo的锁定,递增计数器并检查ch中的值。它找不到一个,因此它不分配(或修改)上下文。相反,它在ch中存储一个值,以便线程B可以代替这样做。

线程B看到计数器已经递增,在ch中注明了一个值,但不确定线程​​A是否对上下文做了任何事情。如果上下文被初始化为NULL,则线程B不再需要关心线程A做了什么,它知道上下文可以安全地取消引用(如果不是NULL)或分配(如果为NULL)而不会泄漏。

线程B完成其业务,线程A读取其上下文,释放它,然后将其重新初始化为NULL。

同样的推理适用于全局变量,不使用线程。能够在解除引用它们之前在各种函数中测试它们(或尝试分配它们从而导致程序中的泄漏和未定义的行为)是很好的。

当它变得愚蠢时,指针的范围不会超出单个函数。如果你有一个函数而无法跟踪其中的指针,通常这意味着该函数应该重新计算。但是,如果只是为了保持统一的习惯,在单个函数中初始化指针没有任何问题。

我唯一一次看到依赖初始化指针(使用前后)的“丑陋”情况就是这样:

void my_free(void **p)
{
    if (*p != NULL) {
        free(*p);
        *p = NULL;
    }
}

在严格的平台上,不仅取消引用类型受惩罚的指针,上面的代码使得free()更加危险,因为调用者会有一些安全错觉。除非您确定每项操作都是一致的,否则您不能依赖于“批发”练习。

可能比您实际想要的信息多得多。

答案 8 :(得分:0)

首选款式:

C中的

char * c = NULL;

在C ++中:char * c = 0;

答案 9 :(得分:0)

我的理由是,如果你没有使用NULL进行初始化,然后忘记完全初始化,那么在解除引用时你将在代码中获得的错误类型由于潜在的垃圾而难以追踪在那一点记忆。另一方面,如果你做初始化为NULL,大部分时间你只会获得segmentation fault,这是更好的,考虑到替代方案。

答案 10 :(得分:0)

即使您不需要立即初始化变量也是一个很好的做法。通常,我们将指针初始化为NULL,将int初始化为0并将其作为约定浮动到0.0。

int* ptr = NULL;
int i = 0;
float r = 0.0;

答案 11 :(得分:0)

用C ++初始化指针变量总是好的,如下所示:

import _ from 'lodash'

declare module 'lodash' {
    type HasElements<T extends boolean> = T extends boolean ? { // distributive conditional, makes HasElements<boolean> == HasElements<true> | HasElements<false>
        "gurad-traits"?: {
            hasElements?: T
        }
    }: never
    interface LoDashStatic {
        isEmpty<T extends HasElements<boolean>>(value?: T): value is T & HasElements<false>;
        last<T> (array: List<T> & HasElements<true>): T;
        last<T> (array: (List<T> & HasElements<false> )| null | undefined): undefined;
}
}

function test<T>(array: T[] & _.HasElements<boolean>, defaultValue: T): T {
    if (!_.isEmpty(array)) {
        return _.last(array);
    }else {
        let u: T = _.last(array); /// err, returns undefined
        return defaultValue;
    }
}

test([1,2,3], 1); //HasElements does not influence the assignability of arrays

由于如上初始化将在以下情况下有所帮助,因为 nullptr 可转换为 bool ,否则您的代码最终将引发一些编译警告或未定义的行为:

int *iPtr = nullptr;
char *cPtr = nullptr;