Initialization differences between character and Integer pointers - c

This has no runtime error
int main()
{
char *p = "Hello";
}
This gives runtime error
int main()
{
int *p;
*p = 5;
}
I cant understand the reason why this is happening. Would appreciate any kind of help.

Your first example points pointer p to a literal string, so p is pointing to valid memory.
Your section declares the pointer p but does not point to to any memory address. Then the next statement *p = 5 dereferences p, which tries to store 5 at the memory address stored in pointer p. Since you have not pointed p to valid memory, your application crashes.

Your second snippet is undefined behaviour as the pointer is uninitialised.
Your first snippet could get you into trouble too: you ought to write const char *p = "Hello";. This is because the string text will be added to a table of string literals by the C runtime library. It's undefined behaviour to modify it. Using const helps enforce that.

The first program sets the value of the pointer, and is well-defined (so long as you don't attempt to modify the string).
The second program assigns a value through an uninitialized pointer (and therefore has undefined behaviour).
The following is a rough equivalent of the first program, but using int:
int main()
{
int val = 5;
int *p = &val;
}

Related

What is the difference between derefencing and assigning the address of a variable to pointer variable in C?

See the two codes below!
int main() {
int a = 12;
int *p;
*p = a;
}
and the this code,
int main() {
int a = 12;
int *p;
p = &a;
}
In the first piece of code dereferenced the pointer as this *p = a, and in the second piece of code, the address of variabe a is set to the pointer variable.
My question is what is the difference between both pieces of codes?
In your first piece of code:
int main() {
int a = 12;
int *p;
*p = a;
}
you have a serious case of undefined behaviour because, what you are trying to do is assign the value of a to the int variable that p currently points to. However, p has not been assigned an 'address', so it will have an arbitrary - and invalid - value! Some compilers may initialise p to zero (or NULL) but that is still an invalid address (on most systems).
Your second code snippet is 'sound' but, as it stands, doesn't actually achieve anything:
int main() {
int a = 12;
int *p;
p = &a;
}
Here, you are assigning a value (i.e. an address) to your pointer variable, p; in this case, p now points to the a variable (that is, it's value is the address of a).
So, if you appended code like this (to the end of your second snippet):
*p = 42;
and then printed out the value of a, you would see that its value has been changed from the initially-given 12 to 42.
Feel free to ask for further clarification and/or explanation.
Declaring *p and a is reserving some space in memory, for a pointer in first case, for what a is in the 2nd case (an int).
In these both cases, their values are not initialized if you don't put anything in it. That doesn't mean there is nothing in it, as that is not possible. It means their values are undetermined, kind of "random" ; the loader just put the code/data in memory when requested, and the space occupied by p, and the one occupied by a, are both whatever the memory had at the time of loading (could be also at time of compilation, but anyway, undetermined).
So you take a big risk in doing *p = a in the 1st case, since you ask the processeur to take the bytes "inside" a and store them wherever p points at. Could be within the bounds of your data segments, in the stack, somewhere it won't cause an immediate problem/crash, but the chances are, it's very likely that won't be ok!
This is why this issue is said to cause "Undefined Behavior" (UB).
When you initialized a pointer you can use *p to access at the value of pointer of the pointed variable and not the address of the pointed variable but it's not possible to affect value like that (with *p=a). Because you try to affect a value without adress of variable.
The second code is right use p = &a
The first one is bad:
int main() {
int a = 12;
int *p;
*p = a;
}
It means: put the value of variable a into location, pointed by pointer p. But what the p points? probably nothing (NULL) or any random address. In best case, it can make execution error like access violation or segmentation fault. In worst case, it can overwrite any existing value of totally unknown variable, resulting in problems, which are very hard to investigate.
The second one is OK.
int main() {
int a = 12;
int *p;
p = &a;
}
It means: get the pointer to (existing) variable a and assign it to pointer p. So, this will work OK.
What is the difference between dereferencing and assigning the address of a variable to pointer variable in C?
The latter is the premise for the first. They are separate steps to achieve the benefit of pointer dereferencing.
For the the explanation for where the difference between those are, we have to look what these guys are separately:
What is dereferencing the pointer?
First we need to look what a reference is. A reference is f.e. an identifier for an object. We could say "Variable a stands for the value of 12." - thus, a is a reference to the value of 12.
The identifier of an object is a reference for the value stored within.
The same goes for pointers. pointers are just like usual objects, they store a value inside, thus they refer to the stored values in them.
"Dereferencing" is when we "disable" this connection to the usual value within and use the identifier of p to access/refer to a different value than the value stored in p.
"Dereferencing a pointer" means simply, you use the pointer to access the value stored in another object, f.e. 12 in a instead through its own identifier of a.
To dereference the pointer the * dereference operator needs to precede the pointer variable, like *p.
What is assigning the address of a variable to a pointer?
We are achieving the things stated in "What is dereferencing a pointer?", by giving the pointer an address of another object as its value, in analogy like we assign a value to a usual variable.
But as opposed to usual object initializations/assignments, for this we need to use the & ampersand operator, preceding the variable, whose value the pointer shall point to and the * dereference operator, preceding the pointer, has to be omitted, like:
p = &a;
Therafter, The pointer "points" to the address the desired value is stored at.
Steps to dereferencing a pointer properly:
First thing to do is to declare a pointer, like:
int *p;
In this case, we declare a pointer variable of p which points to an object of type int.
Second step is to initialize the pointer with an address value of an object of type int:
int a = 12;
p = &a; //Here we assign the address of `a` to p, not the value of 12.
Note: If you want the address value of an object, like a usual variable, you need to use the unary operator of &, preceding the object.
If you have done these steps, you are finally be able to access the value of the object the pointer points to, by using the *operator, preceding the pointer object:
*p = a;
My question is what is the difference between both pieces of codes?
The difference is simply as that, that the first piece of code:
int main() {
int a = 12;
int *p;
*p = a;
}
is invalid for addressing an object by dereferencing a pointer. You cannot assign a value to the pointer´s dereference, if there isn´t made one reference before to which the pointer do refer to.
Thus, your assumption of:
In the first piece of code I dereferenced the pointer as this *p = a...
is incorrect.
You do not be able to dereference the pointer at all in the proper way with *p = a in this case, because the pointer p doesn´t has any reference, to which you are be able to dereference the pointer correctly to.
In fact, you are assigning the value of a with the statement of *p = a somewhere into the Nirwana of your memory.
Normally, the compiler shall never pass this through without an error.
If he does and you later want to use the value, which you think you´d assigned properly by using the pointer, like printf("%d",*p) you should get a Segmentation fault (core dumped).

C pointer difference Char Int [duplicate]

This question already has answers here:
warning: assignment makes integer from pointer without a cast
(5 answers)
Closed 6 years ago.
the code bellow works as it needs to work.
void TstPointer(int *Pointer)
{
*Pointer = 3;
}
int main()
{
int number = 1;
int *ptr = &number;
TstPointer(ptr);
printf("%d\n", number);
}
But when i switch types to char it doesnt work.
void TstPointer(char *Pointer)
{
*Pointer = "Hell1";
}
int main()
{
char *Hello = "Hello";
TstPointer(Hello);
printf("%s\n", Hello);
}
warning: assignment makes integer from pointer without a cast [-Wint-conversion]
*Pointer = "Hell1";
Pass the reference of Hello to your method (&Hello) as you do with int -
int *ptr = &number;
TstPointer(ptr);
While doing *Pointer = "Hell1"; your compiler warned you. You chose to ignore that which possibly invokes the undefined behavior.
In general , to copy to a pointer, use strcpy() but in that case, that will cause problem, as Pointer points to a string literal which you're not allowed to change.
You need to make sure that the memory is writable before trying to write into that memory location. Either use memory allocator function, or create an array and make the pointer point to the start of the array.
In your TstPointer method, when you do *Pointer = "Hell1";, you are generating the warning.
This is because, if Pointer is a char pointer, then *Pointer is a char variable. And you are assigning a string constant to a char variable which is wrong.
To solve this issue, I think you ought to use a double pointer in the function parameter as pass the address (of the pointer) in the main!
EDIT:
You are getting the warning because when you assign a string constant to a variable (char pointer or array, usually), that variable stores the address of the beginning of the string constant. Now, when the lvalue is not char pointer type, but is just a char variable, some implicit conversion takes place to assign (fit) the "address" into a normal char variable, which in turn gives the warning. But, we know char cannot accommodate a memory address, and thus will usually result in a segfault when printed!

Pointer and Memory from Stanford

I am reading article from Stanford CS library http://cslibrary.stanford.edu/102/
Bad Pointer Example
Code with the most common sort of pointer bug will look like the above correct code, but without the middle step where the pointers are assigned pointees. The bad code will compile fine, but at run-time, each dereference with a bad pointer will corrupt memory in some way. The program will crash sooner or later. It is up to the programmer to ensure that each pointer is assigned a pointee before it is used. The following example shows a simple example of the bad code and a drawing of how memory is likely to react...
void BadPointer() {
int* p; // allocate the pointer, but not the pointee
*p = 42; // this dereference is a serious runtime error
}
// What happens at runtime when the bad pointer is dereferenced...
But I remember that char* should be defined like this
char *const name_ptr = "Test";
In this way, if everyone think about if this char* is a bad define?
The line
char *const name_ptr = "Test";
is fine; you're initializing the pointer with the address of the string literal "Test", which is an array of char stored in such a way that the memory for it is allocated at program startup and held until the program terminates.
A quick digression on the const qualifier:
In C, declaration of the form
const T foo = expr;
or
T const foo = expr;
means that foo may not be written to; it's assigned the value of expr when it's created, and that value may not be changed for the rest of foo's lifetime1). With pointer variables, it gets a little more complicated:
const T *p = expr;
T const *p = expr;
both declare p as a non-const pointer to const data; IOW, you can change the value of p (p can point to different objects), but not the value of *p (you cannot change the value of what p points to).
T * const p = expr;
declares p as a const pointer to non-const data; you can change the value of what p points to (*p = ...), but you cannot change p to point to a different object.
const T * const p = expr;
T const * const p = expr;
both declare p as a const pointer to const data; you cannot change either the value of p or what p points to.
In C, string literals such as "Test" are stored as arrays of char, but attempting to modify the contents of a string literal is undefined behavior (depending on the platform, you may get an access violation). For safety's sake, it's usually a good idea to declare pointers to string literals as const char * or char const *, rather than char * const as in the example above.
As far as
void BadPointer() {
int* p; // allocate the pointer, but not the pointee
*p = 42; // this dereference is a serious runtime error
}
is concerned, p is an auto variable, which is not initialized to any particular value; it will contain a random bit string that may or may not correspond to a writable address. Because of this, the behavior of the statement *p = 42; is undefined - you may get an access violation, you may wind up overwriting something important and leave the program in a bad state, or it may appear to "work" with no issues (writing to some random memory area that is accessible and not important).
In general, it's impossible to tell whether a given pointer value is valid or invalid from the pointer value alone2). The one exception is the special pointer value NULL, which is a well-defined "nowhere" that's guaranteed to compare unequal to any valid pointer value. Pointer variables declared at file scope (outside of any function) or with the static qualifier are implicitly initialized to NULL. Non-static, block-scope pointer variables should always be explicitly initialized with either NULL or a valid address. This way you can easily check to see if the pointer has been assigned a valid value:
int *p = NULL;
...
if (p != NULL) // or simply if (p)
{
*p = 42;
}
else
{
// p was not assigned a valid memory location
}
1) Note that, in C, foo is not a compile-time constant; it's a regular run-time variable, you just cannot write to it. You cannot use it in a context that requires a compile-time constant.
2) If you're intimately familiar with your platform's memory model you can make some educated guesses, but even then it's not guaranteed.
In the second case:
char *const name_ptr = "Test";
You are creating a string literal that placed in read-only memory. Therefore you can have a legit pointer to it.
In the first case:
void BadPointer() {
int* p; // allocate the pointer, but not the pointee
*p = 42; // this dereference is a serious runtime error
}
you will get an Undefined Behavior (UB).
char *const name_ptr means that name_ptr is a constant pointer to a char (it is the pointer which is constant).
You probably mean const char * name_ptr = "Test"
(name_ptr is a pointer to a character that is constant)
The thing is that "Test" is a string, which is an array of chars, stored somewhere in (probably) constant memory. Since the memory is allocated, then that is fine to initialise the pointer to point at it.
int *p; is an uninitialised pointer. It has some undefined value which might or might not resolve to a sensible memory location - odds are that it won't but you never know. Saying *p = 42; will overwrite that arbitary memory location with 42, then all bets for your program are off.
In a case like this, it helps to remember that a pointer is nothing more than a normal variable that holds a value - the only "magic" part about it is that value represents a location in memory, and you can dereference that location to access what's stored there.
Imagine a bit of code like this:
void BadPrinter() {
int p;
printf("%d\n", p);
}
What would it print? Who knows? Maybe 0, maybe garbage, maybe the lyrics to "Come Sail Away" by Styx encoded as an integer.
Now we go back to your pointer code:
void BadPointer() {
int* p; // allocate the pointer, but not the pointee
*p = 42; // this dereference is a serious runtime error
}
p is uninitialized in the exact same way - it could contain anything. So when you do *p, you're asking the compiler to give you access to whatever memory is represented by the number contained in p.
So if p happens to contain 0, you're now trying to stuff the value 42 into the memory location 0x0: your program will probably crash. If p happens to contain a location in writable memory, your program will probably continue merrily along, since you will be allowed to store 42 at that location.
Now this case is a little different:
char *const name_ptr = "Test";
Here you're asking the compiler to allocate enough memory space to store the string "Test" and store the location of that memory in name_ptr. Going back to our first example, it would be analogous to:
void GoodPrinter() {
int p = 4;
printf("%d\n", p);
}

Strange (for me) behavior of pointers

I'm reading about pointers, but i'm confused about their nature. Here is what I mean.
int x = 4;
//Here I declare p as integer pointer
int *p;
// Here I assign memory address of x to pointer p
p = &x;
// The line below prints result 4 which is expected. If I miss asterisk before p I'll get memory address instead of data which that memory address holds.
printf("%d", *p)
Summarizing when asterisk is mising before pointer it "points" to memory address. If asterisk preceded pointer it "points" to actual data.
So far so good.
But why that segment of code works correctly ?
int someIntVariable = 10;
const int *p = &someIntVariable;
printf("%d", *p);
If I miss asterisk the compiler gives me an warning " warning: initialization makes integer from pointer without a cast"
I expected p (if the compiler allows me to use p without asterisk) to hold memory address of someIntVariable instead of it's "value";
What is happening here ?
In the declaration:
const int *p = &someIntVariable;
The asterisk is not the dereference operator. It simply states p is a pointer. That line has the same effect as
const int *p;
p = &someIntVariable;
Here you are declaring a pointer and assigning a value to the pointer in one step.
It is equivalent to the following code:
const int *p;
p = &someIntVariable;
Here the * is not used as a de-referencing operator. It is used in the context of pointer declaration.
The const int * is a datatype - i.e. pointer to a const int. p is the name of the variable. It is on the LHS.
When asterik is on the RHS it has a different meaning. It means dereference.
I belive you got the warning:initialization makes integer from pointer without a cast,
when you tried these way
int someIntVariable = 10;
const int p = &someIntVariable;
printf("%d", p);
What your trying to do is , Your assigning a address to a normal variable and your expecting it to work but that is not how the normal variables used thats why pointers came into act to do that job and your trying to replace a pointer with normal variable
I still did not find the real answer to it but Just check out these question that I asked I wonder what really the &a returns?

How to answer this interview test about constant pointers?

I had an interview in which they had asked me this question
#include<stdio.h>
int main ()
{
int* const p=NULL;
int const *q=NULL;
p++;
q++;
printf("%d\n",p);
printf("%d\n",q);
}
How will above program behave
a) p will increment 4 bytes;
and q will also increment 4 bytes;
b) p will be zero
q will point to memory 4 bytes ahead;
c) error will come in above program
I am not able to understand what is the difference between the statements
int* const p=NULL;
int const *q=NULL;
int* const p=NULL;
p is a constant-pointer to an integer. The pointer IS constant (the pointer value cannot be changed); the integer pointed to is not constant (the integer value can be modified).
So statement:
p++;
will fail to compile because trying to modify a constant value (the pointer).
and statement:
(*p)++;
will increment the integer value being pointed by pointer p (but because p is assigned NULL, it will be undefined behaviour)
int const *q=NULL;
q is a pointer to a constant-integer.The pointer is not constant (the pointer value can be changed); the integer pointed to IS constant (the integer value cannot be modified).
So statement:
q++;
will modify pointer q to point to memory 4 bytes ahead (assuming sizeof(int) is 4). (because q is assigned NULL, q will be 0x4 -- I assume NULL is zero (which is true in all current implementation), incrementing NULL pointer is actually undefined behaviour )
and statement:
(*q)++;
will fail to compile because trying to modify a constant value (the integer pointed to is a constant)
How will above program behave?
This is rather simple to answer: the program will not compile.
The postfix ++ requires a modifiable lvalue as its argument; p is not modifiable because it is const-qualified.
The const after the * means that the pointer is qualified; if the const appears before the * as it does in the declaration of q, it means that the object referred to by the pointer is qualified. You can decode the C declarator syntax using the clockwise/spiral rule.
If you remove p and all references to it from the program so that only the lines containing q remain, the answer is that the program exhibits undefined behavior: you cannot perform arithmetic on a null pointer (at least not if the result is not the null pointer).
http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
They specifically say there:
An interesting extra feature pops up
now. What does this mean?
char c; char *const cp = &c;
It's simple really; cp is a pointer to
a char, which is exactly what it would
be if the const weren't there. The
const means that cp is not to be
modified, although whatever it points
to can be—the pointer is constant, not
the thing that it points to. The other
way round is
const char *cp;
which means that now cp is an
ordinary, modifiable pointer, but the
thing that it points to must not be
modified. So, depending on what you
choose to do, both the pointer and the
thing it points to may be modifiable
or not; just choose the appropriate
declaration.
For answering this question and many more questions about const and pointers you have to understand something basic. I will explain it verbally first, and then with an example:
A pointer object can be declared as a const pointer or a pointer to a const object (or both):
A const pointer cannot be reassigned to point to a different object from the one it is initially assigned, but it can be used to modify the object that it points to (called the "pointee"). Reference variables are thus an alternate syntax for constpointers.
A pointer to a const object, on the other hand, can be reassigned to point to another object of the same type or of a convertible type, but it cannot be used to modify any object.
A const pointer to a const object can also be declared and can neither be used to modify the pointee nor be reassigned to point to another object.
Example:
void Foo( int * ptr,
int const * ptrToConst,
int * const constPtr,
int const * const constPtrToConst )
{
*ptr = 0; // OK: modifies the "pointee" data
ptr = 0; // OK: modifies the pointer
*ptrToConst = 0; // Error! Cannot modify the "pointee" data
ptrToConst = 0; // OK: modifies the pointer
*constPtr = 0; // OK: modifies the "pointee" data
constPtr = 0; // Error! Cannot modify the pointer
*constPtrToConst = 0; // Error! Cannot modify the "pointee" data
constPtrToConst = 0; // Error! Cannot modify the pointer
}
I have just put the code provided and ran it,
the
I then compiled it,and an error of read only pointer can not be modified and in our case incremented as below abort compilation
I want just only to give an example of where we can not use const pointers.
Another example from the network simulator ns3 that clarifies constant pointer usage. when we define error model that will examine arriving packets.
a function na
After IsCorrupt return true(in case of error), then the program can then drop or delete the packet from its data buffer.
bool IsCorrupt (Ptr<Packet> pkt);
Note that we do not pass a const pointer, thereby allowing the function to modify the packet if IsCorrupt() returns true.

Resources