initializing char pointers
Asked Answered
P

12

14

I have a char pointer which would be used to store a string. It is used later in the program.

I have declared and initialized like this:

char * p = NULL;

I am just wondering if this is good practice. I'm using gcc 4.3.3.

Prettypretty answered 2/11, 2009 at 10:19 Comment(5)
I guess, he's asking if he should initialize that "string" to NULL (or 0), to "" or not to initialize it at all.Polycythemia
Some caution is needed here, NULL is usually 0 but according to the standard it might be different: The macro NULL, defined in any of <clocale>, <cstddef>, <cstdio>, <cstdlib>, <cstring>, <ctime>, or <cwchar>, is an implementation-defined C++ null pointer constant in this International Standard. I would definitely stick to NULL, besides it is more "type-oriented" and more descriptive in source code than 0.Rolling
The int value 0, when converted to pointer type, always results in a null pointer. From the point of view of portability it makes no difference which you do, it doesn't matter whether or not NULL is just 0. That still leaves the "more descriptive" argument, on which opinions vary. The counter-claim amounts to that the NULL macro is a slightly leaky abstraction and misleading when misused (int i = NULL;)Culver
@RedGlyph: Different language; you're quoting C++ not C. C doesn't even have the <clocale> etc. headers.Cabot
preferred styles: in C: char * c = NULL; in C++: char * c = 0;Knowle
C
15

Yes, it's good idea. Google Code Style recommends:

  1. To initialize all your variables even if you don't need them right now.
  2. Initialize pointers by NULL, int's by 0 and float's by 0.0 -- just for better readability.

    int i = 0;
    double x = 0.0;
    char* c = NULL;
    
Coastland answered 2/11, 2009 at 10:27 Comment(6)
By the way, that's a C++ style guide. It doesn't tell us what (if anything) Google says about C.Culver
@onebyone: Even still, its good practice to initialize pointers to NULL and then set them to NULL after freeing them. It makes it easier to test them prior to dereferencing them, especially in complex code. This is true in C or C++.Sesame
@onebyone you are right, i'm c++ developer and saw c++ syntax in the question =) But O think the rule about NULL is a good practice for C too.Coastland
The first part - "prefer to always initialize" - is only acceptable in C 99 and C++, where the declarations can be made at any point in the code. In classic C89/90 this is a major anti-rule. Don't waste your code on such nonsense. The second part - "use type-specific initializers" - is an anti-rule in any context. It violates one of the most important rules of good programming: don't introduce any redundancies without a good reason. Floating-point values can be safely and successfully initialized by 0 (as opposed to 0.0).Multivalent
Using 0.0 does not improve readability and introduces redundant type-dependence between left-hand side and right-hand side of initialization. Using NULL for pointers might be permissible, but in all other cases it is a good practice to use a simple 0 to initialize everything that can be initialized with it. Apparently, Google Code Style is more arbitrary that I thought it would be.Multivalent
Yes and since it's a style guide, it's not necessarily universally accepted. I for one say (and i know of others having the same opinion) that i don't initialize things i don't need. I initialize them when appripriate - which might be just before a loop starts, for instance. Bugs will be found by placing proper assertions, not by having things initialized.Sapphira
F
5

You cannot store a string in a pointer.

Your definition of mgt_dev_name is good, but you need to point it somewhere with space for your string. Either malloc() that space or use a previously defined array of characters.

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 */
}
Finbar answered 2/11, 2009 at 10:24 Comment(1)
I don't know if this is what he was asking, but it's what I wanted to know. Specifically, how to initialize to NULL and later assign space for a string.Jenicejeniece
A
4

It is good practice to initialize all variables.

Aeriela answered 2/11, 2009 at 10:23 Comment(0)
F
3

If you're asking whether it's necessary, or whether it's a good idea to initialize the variable to NULL before you set it to something else later on: It's not necessary to initialize it to NULL, it won't make any difference for the functionality of your program.

Note that in programming, it's important to understand every line of code - why it's there and what exactly it's doing. Don't do things without knowing what they mean or without understanding why you're doing them.

Fourth answered 2/11, 2009 at 10:24 Comment(5)
Actually, he should initialize it to NULL. Technically, even pointing to memory that doesn't belong to your program makes it ill-formed, so by setting it to NULL, you avoid that. (And it's good coding practice)Deherrera
But it's more error-prone not to initialize variables, according to me.Polycythemia
@GMan - But if he's initializing the variable to some other value a few lines later, without doing anything with the variable in between, it's unnecessary.Fourth
Unnecessary for run-time behavior, but for making a well-formed program, it should be initialized.Deherrera
"even pointing to memory that doesn't belong to your program makes it ill-formed". No, it doesn't. The following code is valid C with defined behavior: char *c; c = "hello, world";. So is the following: char *c = malloc(13); free(c); /* c points to memory I don't own! */ c = NULL;Culver
P
3

Another option is to not define the variable until the place in your code where you have access to it's initial value. So rather then doing:

char *name = NULL;

...

name = initial_value;

I would change that to:

...

char *name = initial_value;

The compiler will then prevent you from referencing the variable in the part of the code where it has no value. Depending on the specifics of your code this may not always be possible (for example, the initial value is set in an inner scope but the variable has a different lifetime), moving the definition as late as possible in the code prevents errors.

That said, this is only allowed starting with the c99 standard (it's also valid C++). To enable c99 features in gcc, you'll need to either do:

gcc -std=gnu99

or if you don't want gcc extensions to the standard:

gcc -std=c99
Presentation answered 3/11, 2009 at 4:44 Comment(0)
M
3

No, it is not a good practice, if I understood your context correctly.

If your code actually depends on the mgt_dev_name having the initial value of a null-pointer, then, of course, including the initializer into the declaration is a very good idea. I.e. if you'd have to do this anyway

char *mgt_dev_name;

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

then it is always a better idea to use initialization instead of assignment

char *mgt_dev_name = NULL;

However, initialization is only good when you can initialize your object with a meaningful useful value. A value that you will actually need. In general case, this is only possible in languages that allow declarations at any point in the code, C99 and C++ being good examples of such languages. By the time you need your object, you usually already know the appropriate initializer for that object, and so can easily come up with an elegant declaration with a good initializer.

In C89/90 on the other hand, declarations can only be placed at the beginning of the block. At that point, in general case, you won't have meaningful initializers for all of your objects. Should you just initialize them with something, anything (like 0 or NULL) just to have them initialized? No!!! Never do meaningless things in your code. It will not improve anything, regardless of what various "style guides" might tell you. In reality, meaningless initialization might actually cover bugs in your code, making it the harder to discover and fix them.

Note, that even in C89/90 it is always beneficial to strive for better locality of declarations. I.e. a well-known good practice guideline states: always make your variables as local as they can be. Don't pile up all your local object declarations at the very beginning of the function, but rather move them to the beginning of the smallest block that envelopes the entire lifetime of the object as tightly as possible. Sometimes it might even be a good idea to introduce a fictive, otherwise unnecessary block just to improve the locality of declarations. Following this practice will help you to provide good useful initializers to your objects in many (if not most) cases. But some objects will remain uninitialized in C89/90 just because you won't have a good initializer for them at the point of declaration. Don't try to initialize them with "something" just for the sake of having them initialized. This will achieve absolutely nothing good, and might actually have negative consequences.

Note that some modern development tools (like MS Visual Studio 2005, for example) will catch run-time access to uninitialized variables in debug version of the code. I.e these tools can help you to detect situations when you access a variable before it had a chance to acquire a meaningful value, indicating a bug in the code. But performing unconditional premature initialization of your variables you essentially kill that capability of the tool and sweep these bugs under the carpet.

Multivalent answered 3/11, 2009 at 5:9 Comment(0)
P
2

This topic has already been discussed here:

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

It refers to C++, but it might be useful for you, too.

Polycythemia answered 2/11, 2009 at 10:25 Comment(0)
S
0

There are several good answers to this question, one of them has been accepted. I'm going to answer anyway in order to expand on practicalities.

Yes, it is good practice to initialize pointers to NULL, as well as set pointers to NULL after they are no longer needed (i.e. freed).

In either case, its very practical to be able to test a pointer prior to dereferencing it. Lets say you have a structure that looks like this:

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

You then write an application that spawns several threads, all of which operate on a single allocated foo structure (safely) through the use of mutual exclusion.

Thread A gets a lock on foo, increments counter and checks for a value in ch. It does not find one, so it does not allocate (or modify) context. Instead, it stores a value in ch so that thread B can do this work instead.

Thread B Sees that counter has been incremented, notes a value in ch but isn't sure if thread A has done anything with context. If context was initialized as NULL, thread B no longer has to care what thread A did, it knows context is safe to dereference (if not NULL) or allocate (if NULL) without leaking.

Thread B does its business, thread A reads its context, frees it, then re-initializes it to NULL.

The same reasoning applies to global variables, without the use of threads. Its good to be able to test them in various functions prior to dereferencing them (or attempting to allocate them thus causing a leak and undefined behavior in your program).

When it gets silly is when the scope of the pointer does not go beyond a single function. If you have a single function and can't keep track of the pointers within it, usually this means the function should be re-factored. However, there is nothing wrong with initializing a pointer in a single function, if only to keep uniform habits.

The only time I've ever seen an 'ugly' case of relying on an initialized pointer (before and after use) is in something like this:

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

Not only is dereferencing a type punned pointer frowned upon on strict platforms, the above code makes free() even more dangerous, because callers will have some delusion of safety. You can't rely on a practice 'wholesale' unless you are sure every operation is in agreement.

Probably a lot more information than you actually wanted.

Sesame answered 2/11, 2009 at 13:41 Comment(0)
K
0

Preferred styles:

in C: char * c = NULL;

in C++: char * c = 0;

Knowle answered 4/11, 2009 at 1:55 Comment(0)
F
0

My rationale is that if you don't initialize with NULL, and then forget to initialize altogether, the kinds of bugs you will get in your code when dereferencing are much more difficult to trace due to the potential garbage held in memory at that point. On the other hand, if you do initialize to NULL, most of the time you will only get a segmentation fault, which is better, considering the alternative.

Freemon answered 9/6, 2010 at 15:35 Comment(0)
S
0

Initializing variables even when you don't need them initialized right away is a good practice. Usually, we initialize pointers to NULL, int to 0 and floats to 0.0 as a convention.

int* ptr = NULL;
int i = 0;
float r = 0.0;
Sabina answered 3/1, 2016 at 19:29 Comment(0)
C
0

It is always good to initialize pointer variables in C++ as shown below:

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

Because initializing as above will help in condition like below since nullptr is convertible to bool, else your code will end up throwing some compilation warnings or undefined behaviour:

if(iPtr){
   //then do something.
}

if(cPtr){
  //then do something.
}
Carnivorous answered 3/5, 2019 at 10:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.