I have a structure like this:
struct foo {
int x;
char y;
};And this is my code in main():
struct foo *p; //haven't initialized it/used malloc
p->x = 10; //gives a warning but not an error?
p->y = 'a';
printf("%d %c\n",p->x,p->y); //why does this give an actual output???
printf("%p %p %p\n",p,&(p->x),&(p->y));
//this returns d0, d0, d4, like it would for a properly allocated struct (removed the rest of the memory address for conciseness)So why does using an uninitialized or unallocated pointer to a struct make any sense?
(My compiler is gcc)
Edit: Thanks for all the responses, you guys are really helpful!
c - Difference between uninitialized and null pointer - Stack Overflow
How can I pass an un-initialized pointer as an argument to a function in C?
How is the destination that an uninitialized pointer in c points to determined? - Stack Overflow
Declaring a pointer without initializing
Videos
All automatic (non-static local) variables will by default be uninitialized with an indeterminate value (that can seem like random or garbage). It doesn't matter if the variable is a pointer or not.
Also, just reading the value of an uninitialized pointer isn't automatically UB (in C), but dereferencing an uninitialized pointer definitely is.
However, as mentioned in one comment, you need to use "%p" to print pointers (technically they need to be casted to void * as well). Mismatching printf format specifier and argument type do lead to UB.
You cannot assume any pointer will be zero-initialized after declaration - C standard does not imply anything at that point. Same goes with other types of values. This is why it is a good practice to set a value of a variable upon declaration, like:
int * t = NULL;
Some compilers do zero-initialize variables, but this is tool-specific feature.
Well, the difference is exactly that. Null pointer is initialized to null, and as such has defined meaning. You can check it for null, and dereferencing it will (on all platforms I know) cause a program to crash with meaningful diagnostics. You can also use null pointers in some specific hacks. Unitinialized pointers, on the other hand, are just random and should be avoided.
Take an uninitialized pointer:
int* ptr;//points to any location in memory
Take a null pointer:
int* ptr = NULL;//normally points to 0x0 (0)
Both would cause undefined behaviour if dereferenced. NULL is often defined as 0.
How can I initialize a pointer from a function using malloc()?
I'm trying to make an API for rendering HTML in a window using C. The usage will look somewhat like this:
parseHTMLFromString(element* root, char* html);
int main()
{
char* html = "<button>click on this <b>bold</b> text</button>"
element* root;
parseHTMLFromString(root, html);
}The problem is that when the *root variable is passed as an uninitialized pointer, any acess to it causes a segmentation fault (even if I am accessing it to initialize). I know that if I initialize root using malloc the error will go away, but I want to avoid forcing the user to do that for the API to work. if this is impossible, I'l just tell the user to initialize if in the API's documentation, but I would rather make it work like this.
I hope this question isn't too easy for this subs standards (some people here say they made OPERATING SYSTEMS!!!), but the reason I wanted to avoid StackOverflow is because most of the people answering C-related questions there are super toxic to relatively easy questions from new accounts, and my account is new because my old one got banned from the stupid site due to downvotes.
If this pointer is defined outside of all functions (or is static), it will be initialized to NULL before main() gets control.
If this pointer is created in the heap via malloc(sizeof(sometype*)), it will contain whatever happens to be at its location. It can be the data from the previously allocated and freed buffer of memory. Or it can be some old control information that malloc() and free() use to manage the lists of the free and allocated blocks. Or it can be garbage if the OS (if any) does not clear program's memory or if its system calls for memory allocation return uninitialized memory and so those can contain code/data from previously run programs or just some garbage that your RAM chips had when the system was powered on.
If this pointer is local to a function (and is not static), it will contain whatever has been at its place on the stack. Or if a CPU register is allocated to this pointer instead of a memory cell, it will contain whatever value the preceding instructions have left in this register.
So, it won't be totally random, but you rarely have full control here.
Uninitialized is undefined. Generally speaking, when the pointer is allocated the memory space is not cleared, so whatever the memory contained is now a pointer. It is random, but it is also efficient in the sense that the memory location is not being changed in the operation.
Hi,Walkbitterwyrm Lightwarg
is it okay to declare a pointer without initializing?
You can declare a pointer without initializing it.
But it is recommended using initializationint* ptr_i = NULL;
so that you can check if the variable has been initialized.
if (ptr_i != NULL)
{
//do something
}
Best regards,
Minxin Yu
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
It may be worth noting that variables that aren't given an explicit initial value may be default initialized.
Global variables and static local variables are default initialized to zero.
Non-static local variables are not default initialized. However, some compilers such as Visual Studio may give them a specific initial value in Debug builds to assist in the debugging process.
#include
int g1, *gp1; // default initialized to zero
int main()
#include
int g1, *gp1; // default initialized to zero
int main()
{
static int sn, *snp; // default initialized to zero
int n1, *np1; // not default initialized, contents indeterminate
printf("g1 = %d\tgp1 = %p\n", g1, gp1); // g1 = 0 gp1 = 00000000
printf("sn = %d\tsnp = %p\n", sn, snp); // sn = 0 snp = 00000000
//printf("n1 = %d\tnp1 = %p\n", n1, np1); // gives compiler errors
return 0;
}
This is a very specialized optimized case for Video Games (basically an embedded system). We used to use them for Load-In-Place data behavior in our Video Games to speed up loading (and avoid fragmentation).
Basically we would create console-side (Playstation) objects in a PC cooker. Then to reduce fragmentation overload, we would pack the data objects in a contiguous buffer with a single alloc. References to the data objects in this buffer would then be changed to subtract the base from pointers to offsets (unfix call -- we also had a virtual fix / unfix calls that took the buffer base and could convert between offsets and pointers).
When we loaded the data, it loaded in one large block. All data referenced by the root was off the root object. We could do an inplace "new" on the the root that would initialize the proper VF tables for the object and fixup all the attached blocks (by doing inplace new and then fixing up attached blocks respectively).
We needed the constructors called (in place new) to generate the proper VF-Tables in the objects. However, if the pointers were automatically cleared to NULL during the constructor, we would have lost the offset data and not been able to recreate the pointers between the objects within the contiguous block.
FWIW, this is a common technique in the Video Game world. This Gamasutra article (not written by me or my coworkers) explains in detail the similar thing they did at another company:
Also, this topic of discussion on SourceForge.
There have even been several GDC (Game Developer Conference) talks on the subject.
Searching on Google for "load-in-place" will give many other examples of people using this technique that basically requires uninitialized pointers.
NOTE: Currently, this is the only response that actually answers the question asked ("Is there a use for uninitialized pointers in C or C++?") by giving a specific use for pointers that must remain unitialized.
All the other responses are better answers for the original question referenced ("[C++] Why aren’t pointers initialized with NULL by default?") that caused the poster to ask this question.
First of all, initializing pointers (or any other variables) by default does not break compatibility with C. Both C and C++ state that a value of uninitialized variable is indeterminate; in practice, this means that it can hold any value (including a trap representation), but note that 0 belongs to the set of "any values"! So a conformant implementation can perfectly well initialize all pointers to 0. Your program, should it rely on that, would not be conformant, however.
Now as to why you may want your pointer to not be initialized: mainly when it is written to afterwards. For example:
void foo(int*& p) {
p = new int;
}
int* p; // why initialize? we overwrite it anyway
foo(p);
You can say that compiler should be able to optimize this away. Unfortunately, it cannot do so if the definition of foo is not available (e.g. global link-time optimizations are disabled; or they are enabled, but the function is in a DLL), since it doesn't know if foo will try to read from p (and then initialization would be needed), or if it would just write to it (and then initialization isn't needed). What more, there may be cases that are harder to analyze; for example:
bool try_parse_int(const char* s, int& n)
{
// if parsed successfully, assign result to n and return true
// if there was error parsing, don't touch n and return false
...
}
int n;
if (try_parse_int(s, n)) {
// use n here
...
} else {
// don't use n here
...
}
This one is much harder for the compiler to analyze even if it has full definitions of all functions.
Variable dummy has already been declared in the following statement:
struct node dummy;
which means that memory has been allocated to it. In other words, this means that it now has an address associated with it. Hence the pointer tail declared in following line:
struct node* tail = & dummy;
to store its address makes perfect sense.
"But here the variable "dummy" is only declared and not initialized."
The variable declaration introduces it into the scope. You are correct in deducing it's value is unspecified, but to take and use its address is well defined from the moment it comes into scope, right up until it goes out of scope.
To put more simply: your program is correct because you don't depend on the variables uninitialized value, but rather on its well defined address.