Is char pointer address initialization necessary in C?

百般思念 提交于 2021-02-07 20:21:05

问题


I'm learning C programming in a self-taught fashion. I know that numeric pointer addresses must always be initialized, either statically or dynamically.

However, I haven't read about the compulsory need of initializing char pointer addresses yet.

For example, would this code be correct, or is a pointer address initialization needed?

char *p_message;
*p_message = "Pointer";

回答1:


I'm not entirely sure what you mean by "numeric pointer" as opposed to "char pointer". In C, a char is an integer type, so it is an arithmetic type. In any case, initialization is not required for a pointer, regardless of whether or not it's a pointer to char.

Your code has the mistake of using *p_message instead of p_message to set the value of the pointer:

*p_message = "Pointer"          // Error!

This wrong because given that p_message is a pointer to char, *p_message should be a char, not an entire string. But as far as the need for initializing a char pointer when first declared, it's not a requirement. So this would be fine:

char *p_message;
p_message = "Pointer";

I'm guessing part of your confusion comes from the fact that this would not be legal:

char *p_message;
*p_message = 'A';

But then, that has nothing to do with whether or not the pointer was initialized correctly. Even as an initialization, this would fail:

char *p_message = 'A'; 

It is wrong for the same reason that int *a = 5; is wrong. So why is that wrong? Why does this work:

char *p_message;
p_message = "Pointer";

but this fail?

char *p_message;
*p_message = 'A';

It's because there is no memory allocated for the 'A'. When you have p_message = "Pointer", you are assigning p_message the address of the first character 'P' of the string literal "Pointer". String literals live in a different memory segment, they are considered immutable, and the memory for them doesn't need to be specifically allocated on the stack or the heap.

But chars, like ints, need to be allocated either on the stack or the heap. Either you need to declare a char variable so that there is memory on the stack:

char myChar;
char *pChar;
pChar = &myChar;
*pChar = 'A';

Or you need to allocate memory dynamically on the heap:

char* pChar;
pChar = malloc (1); // or pChar = malloc (sizeof (char)), but sizeof(char) is always 1
*pChar = 'A';

So in one sense char pointers are different from int or double pointers, in that they can be used to point to string literals, for which you don't have to allocate memory on the stack (statically) or heap (dynamically). I think this might have been your actual question, having to do with memory allocation rather than initialization.

If you are really asking about initialization and not memory allocation: A pointer variable is no different from any other variable with regard to initialization. Just as an uninitialized int variable will have some garbage value before it is initialized, a pointer too will have some garbage value before it is initialized. As you know, you can declare a variable:

double someVal;    // no initialization, will contain garbage value

and later in the code have an assignment that sets its value:

someVal = 3.14;

Similarly, with a pointer variable, you can have something like this:

int ary [] = { 1, 2, 3, 4, 5 };
int *ptr;          // no initialization, will contain garbage value
ptr = ary;

Here, ptr is not initialized to anything, but is later assigned the address of the first element of the array.

Some might say that it's always good to initialize pointers, at least to NULL, because you could inadvertently try to dereference the pointer before it gets assigned any actual (non-garbage) value, and dereferencing a garbage address might cause your program to crash, or worse, might corrupt memory. But that's not all that different from the caution to always initialize, say, int variables to zero when you declare them. If your code is mistakenly using a variable before setting its value as intended, I'm not sure it matters all that much whether that value is zero, NULL, or garbage.


Edit. OP asks in a comment: You say that "String literals live in a different memory segment, they are considered immutable, and the memory for them doesn't need to be specifically allocated on the stack or the heap", so how does allocation occur?

That's just how the language works. In C, a string literal is an element of the language. The C11 standard specifies in §6.4.5 that when the compiler translates the source code into machine language, it should transform any sequence of characters in double quotes to a static array of char (or wchar_t if they are wide characters) and append a NUL character as the last element of the array. This array is then considered immutable. The standard says: If the program attempts to modify such an array, the behavior is undefined.

So basically, when you have a statement like:

char *p_message = "Pointer";

the standard requires that the double-quoted sequence of characters "Pointer" be implemented as a static, immutable, NUL-terminated array of char somewhere in memory. Typically implementations place such string literals in a read-only area of memory such as the text block (along with program instructions). But this is not required. The exact way in which a given implementation handles memory allocation for this array / NUL terminated sequence of char / string literal is up to the particular compiler. However, because this array exists somewhere in memory, you can have a pointer to it, so the above statement does work legally.

An analogy with function pointers might be useful. Just as the code for a function exists somewhere in memory as a sequence of instructions, and you can have a function pointer that points to that code, but you cannot change the function code itself, so also the string literal exists in memory as a sequence of char and you can have a char pointer that points to that string, but you cannot change the string literal itself.

The C standard specifies this behavior only for string literals, not for character constants like 'A' or integer constants like 5. Setting aside memory to hold such constants / non-string literals is the programmer's responsibility. So when the compiler comes across statements like:

char *charPtr = 'A';    // illegal!
int *intPtr = 5;        // illegal!

the compiler does not know what to do with them. The programmer has not set aside such memory on the stack or the heap to hold those values. Unlike with string literals, the compiler is not going to set aside any memory for them either. So these statements are illegal.

Hopefully this is clearer. If not, please comment again and I'll try to clarify some more.




回答2:


Initialisation is not needed, regardless of what type the pointer points to. The only requirement is that you must not attempt to use an uninitialised pointer (that has never been assigned to) for anything.

However, for aesthetic and maintenance reasons, one should always initialise where possible (even if that's just to NULL).




回答3:


First of all, char is a numeric type, so the distinction in your question doesn't make sense. As written, your example code does not even compile:

char *p_message;
*p_message = "Pointer";

The second line is a constraint violation, since the left-hand side has arithmetic type and the right-hand side has pointer type (actually, originally array type, but it decays to pointer type in this context). If you had written:

char *p_message;
p_message = "Pointer";

then the code is perfectly valid: it makes p_message point to the string literal. However, this may or may not be what you want. If on the other hand you had written:

char *p_message;
*p_message = 'P';

or

char *p_message;
strcpy(p_message, "Pointer");

then the code would be invoking undefined behavior by either (first example) applying the * operator to an invalid pointer, or (second example) passing an invalid pointer to a standard library function which expects a valid pointer to an object able to store the correct number of characters.




回答4:


not needed, but is still recommended for a clean coding style. Also the code you posted is completely wrong and won't work, but you know that and only wrote that as a quick example, right?



来源:https://stackoverflow.com/questions/18560060/is-char-pointer-address-initialization-necessary-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!