the value of a pointer in a function [duplicate] - c

This question already has answers here:
Declare and initialize pointer concisely (i. e. pointer to int)
(4 answers)
Closed 3 years ago.
Hi I am learning about pointers in C and wondered what does the code below do?
Does the pointer *abc just points to some random stuff because it is not properly assigned with an address of a variable?
void func()
{
int *abc;
*abc = 5;
}

You cannot assigning a value to pointer with assigning memory, which leads to segmentation fault.
int *abc;
Above statement will just declare a pointer to integer, but it does not hold any address.
int *abc = (int *)malloc(sizeof(int));
*abc = 5;
If you want to assign a value directly, You need to initialize with some memory.
Only then you can assign directly

As you note, abc is not properly initialized, so we do not know what it points to. Before it can be reliably used, it must be assigned a value that is the address of properly reserved memory. You can assign it a value by assigning it the address of a defined object (as in int x; int *abc = &x;) or by requesting memory through a routine such as malloc (as in int *abc = malloc(sizeof *abc); and checking that the result is not NULL).
Note that it is not correct to say that it “points to random stuff.” In the terms of the C standard, its value is indeterminate. This means its value is not only unspecified, but that a program that uses it might behave as if abc has a different value each time it is used—it does not necessarily act as if abc has some single randomly determined value. It might also have a trap representation, which does not represent a value of pointer type, and using it would result in the behavior of the program not being defined by the C standard.

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 initialization differences

I am new to C and have some questions about the pointer.
Question 1 What`s differences b/w the following two? Which way is better to initialize a pointer and why?
int *p=NULL;
int *p;
#include <stdio.h>
void main()
{
char *s = "hello";
printf("%p\t%p",s);
//printf("%p\t%p",&s) it will give me unpredictable result every time
//printf("%p\t%p",(void *)&s) it will be fine
//Question3: why?
}
Question 2: I try to google what is %p doing. According to my reading, it is supposed to print the pointer. It that mean it print the address of the pointer?
Question 1, these are definitions of pointer p. One initializes the pointer to NULL, another leaves it uninitialized (if it is local variable in a function, and not global variable, global variables get initialized to 0 by default). Initializing with NULL can be good, or it can be bad, because compiler can warn you about use of uninitialized variables and help you find bugs. On the other hand compiler can't detect every possible use of uninitialized variable, so initializing to NULL is pretty much guaranteed to produce segmentation fault if used, which you can then catch and debug with a debugger very easily. Personally I'd go with always initializing when variable defined, with the correct value if possible (if initialization is too complex for single statement, add a helper function to get the value).
Question 2, %p prints the address value passed to printf. So printf("%p", pointer); gets passed value of variable pointer and it prints that, while printf("%p", &pointer); (note the extra & there) gets passed address of the variable pointer, and it prints that. Exact numeric format of %p is implementation defined, it might be printed just as a plain number.
Question 3 is about undefined behavior, because format string has more items than what you actually pass to printf. Short answer is, behavior is undefined, there is no "why". Longer answer is, run the application with machine code debugger and trace the execution in disassembly view to see what actually happens, to see why. Note that results may be different on different runs, and behavior may be different under debugger and running normally, because memory may have different byte values in different runs for various reasons.
1) The first is an initialization (to NULL in this case) the second is only a declaration of p as a pointer to int, no initial value is assigned to p in this case. You should always prefer an initialization to prevent undefined behavior.
2) You should cast to void* when using %p to print out a pointer (beware that you are using it too many times in your format specifier). The memory address to which p points is printed.
1)
int *p = NULL
defines and initializes a pointer 'p' to NULL. This is the correct way to initialize pointers in order to get "Seg Fault" if you forget to assign a valid address to this pointer later.
int *p
Only defines a pointer "p" with an unknown address. If you forget to assign a valid value to this pointer before using it, then some compilers will notify you about this mistakes while some others will not and you may access a non-valid address and get a run time error or undefined behaviour of the program.
2) "%p" is printing the address where the pointer is points. Since the pointer holds an address, then "%p" prints this address.
printf("%p\t%p",s);
So the first "%p" will print the address where the pointer "s" points which is the address which stores the string "hello". However, note that you are using twice "%p" but you providing only one pointer to print its address !!
Most compilers will not scream about this cause it is effect-less; however try to avoid it.
Answer1 :
int *p=NULL;
p is a pointer to a int variable initialized with NULL. Here NULL means pointer p is not pointing to any valid memory location.
int *p;
p is a pointer to a int variable. p in uninitialized. Reading uninitialized variables is Undefined Behavior. (one possibility if try to use is that it will throw a segmentation fault)
Answer2:
It prints content of pointer. I mean base address of string "hello"
The main difference is that in *p = NULL, NULL is a pre-defined and standard 'place' where the pointer points.
Reading from Wikipedia,
The macro NULL is defined as an implementation-defined null pointer constant,
which in C99 can be portably expressed as the integer value 0
converted implicitly or explicitly to the type void*.
This means that the 'memory cell' called p contains the MACRO value of NULL.
If you just write int *p, you are naming the memory cell with the name p but this cell is empty.

Why can't we assign int* x=12 or int* x= "12" when we can assign char* x= "hello"?

What is the correct way to use int* x?
Mention any related link if possible as I was unable to find one.
Because the literal "hello" evaluates to a pointer to constant memory initialised with the string "hello" (and a nul terminator), i.e. the value you get is of char* type.
If you want a pointer to number 12 then you'll need to store the value 12 somewhere, e.g. in another int, and then take a pointer to that:
int x_value = 12;
int* x = &x_value;
However in this case you're putting the 12 on the stack, and so that pointer will become invalid once you leave this function.
You can at a pinch abuse that mechanism to make yourself a pointer to 12; depending on endianness that would probably be
int* x = (int*)("\x0c\x00\x00");
Note that this is making assumptions about your host's endianness and size of int, and that you would not be able to modify that 12 either (but you can change x to point to something else), so this is a bad idea in general.
Because the compiler creates a static (constant) string "hello" and lets x point to that, where it doesn't create a static (constant) int.
A string literal creates an array object. This object has static storage duration (meaning it exists for the entire execution of the program), and is initialized with the characters in the string literal.
The value of a string literal is the value of the array. In most contexts, there is an implicit conversion from char[N] to char*, so you get a pointer to the initial (0th) element of the array. So this:
char *s = "hello";
initializes s to point to the initial 'h' in the implicitly created array object. A pointer can only point to an object; it does not point to a value. (Incidentally, that really should be const char *s, so you don't accidentally attempt to modify the string.)
String literals are a special case. An integer literal does not create an object; it merely yields a value. This:
int *ptr = 42; // INVALID
is invalid, because there is no implicit conversion of 42 from int* to int. This:
int *ptr = &42; // INVALID
is also invalid, because the & (address-of) operator can only be applied to an object (an "lvalue"), and there is no object for it to apply to.
There are several ways around this; which one you should use depends on what you're trying to do. You can allocate an object:
int *ptr = malloc(sizeof *ptr); // allocation an int object
if (ptr == NULL) { /* handle the error */ }
but a heap allocation can always fail, and you need to deallocate it when you're finished with it to avoid a memory leak. You can just declare an object:
int obj = 42;
int *ptr = &obj;
You just have to be careful with the object's lifetime. If obj is a local variable, you can end up with a dangling pointer. Or, in C99 and later, you can use a compound literal:
int *ptr = &(int){42};
(int){42} is a compound literal, which is similar in some ways to a string literal. In particular, it does create an object, and you can take that object's address.
But unlike with string literals, the lifetime of the (anonymous) object created by a compound literal depends on the context in which it appears. If it's inside a function definition, the lifetime is automatic, meaning that it ceases to exist when you leave the block containing it -- just like an ordinary local variable.
That answers the question in your title. The body of your question:
What is the correct way to use int* x?
is much more general, and it's not a question we can answer here. There are a multitude of ways to use pointers correctly -- and even more ways to use them incorrectly. Get a good book or tutorial on C and read the section that discusses pointers. Unfortunately there are also a lot of bad books and tutorials. Question 18.10 of the comp.lang.c FAQ is a good starting point. (Bad tutorials can often be identified by the casual use of void main(), and by the false assertion that arrays are really pointers.)
Q1. Why can't we assign int *x=12? You can provided that 12 is a valid memory address which holds an int. But with a modern OS specifying a hard memory address is completely wrong (perhaps except embedded code). The usage is typically like this
int y = 42; // simple var
int *x = &y; // address-of: x is pointer to y
*x = 12; // write a new value to y
This looks the same as what you asked, but it is not, because your original declaration assigns the value 12 to x the pointer itself, not to *x its target.
Q2. Why can't we assign int *x = "12"? Because you are trying to assign an incompatible type - a char pointer to int pointer. "12" is a string literal which is accessed via a pointer.
Q3. But we can assign char* x= "hello"
Putting Q1 and Q2 together, "hello" generates a pointer which is assigned to the correct type char*.
Here is how it is done properly:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *x;
x = malloc(sizeof(int));
*x = 8;
printf("%d \n", *x);
}

Need help to understand this main() function in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm learning C programming and do not quite understand the following program, need some help with the understanding.
Question 1: What do the two asterisks do preceding *argv in the main function parameters.
Question 2: Inside the main() function, why void is followed by an asterisk? What does it do?
Question 3: &retval has the "&", does the variable "retval" point to the memory address?
Thanks for help
/** Main */
int main(int argc, char **argv) {
pthread_t thread;
void* retval;
pthread_create(&thread, NULL, thread_proc, NULL);
printf("Hello from the main thread.\n");
pthread_join(thread, &retval);
printf("Done.\n");
return 0;
}
This issue is somewhat confusing when starting to learn C.
Here are the basic principles that might help you get started:
There are only a few basic types in C:
char: an integer value with the size of 1 byte.
short: an integer value with the size of 2 bytes.
long: an integer value with the size of 4 bytes.
long long: an integer value with the size of 8 bytes.
float: a non-integer value with the size of 4 bytes.
double: a non-integer value with the size of 8 bytes.
Note that the size of each type is generally defined by the compiler and not by the standard.
The integer types short, long and long long are usually followed by int.
It is not a must, however, and you can use them without the int.
Alternatively, you can just state int, but that might be interpreted differently by different compilers.
So to summarize this:
short is the same as short int but not necessarily the same as int.
long is the same as long int but not necessarily the same as int.
long long is the same as long long int but not necessarily the same as int.
On a given compiler, int is either short int or long int or long long int.
If you declare a variable of some type, then you can also declare another variable pointing to it.
For example:
int a;
int* b = &a;
So in essence, for each basic type, we also have a corresponding pointer type.
For example: short and short*.
There are two ways to "look at" variable b (that's what probably confuses most beginners):
You can consider b as a variable of type int*.
You can consider *b as a variable of type int.
Hence, some people would declare int* b, whereas others would declare int *b.
But the fact of the matter is that these two declarations are identical (the spaces are meaningless).
You can use either b as a pointer to an integer value, or *b as the actual pointed integer value.
You can get (read) the pointed value: int c = *b.
And you can set (write) the pointed value: *b = 5.
A pointer can point to any memory address, and not only to the address of some variable that you have previously declared. However, you must be careful when using pointers in order to get or set the value located at the pointed memory address.
For example:
int* a = (int*)0x8000000;
Here, we have variable a pointing to memory address 0x8000000.
If this memory address is not mapped within the memory space of your program, then any read or write operation using *a will most likely cause your program to crash, due to a memory access violation.
You can safely change the value of a, but you should be very careful changing the value of *a.
Type void* is exceptional in the fact that it doesn't have a corresponding "value type" which can be used (i.e., you cannot declare void a). This type is used only as a general pointer to a memory address, without specifying the type of data that resides in that address.
Answer one :
char **argv mean you have a two dimension array of char.
you can access it like this :
argv[0][2]
it give you a char.
But you can access like this :
argv[0]
who give you a char *
Here, the '*' told that it's a pointer.
So it's not a char directly in your memory, but a case which will contain an address to char.
The fact to have int *; or char *; or anything * mean that you probably have an array.
Answer 2:
The void * is simple.
You have a pointer to something you don't know yet what it will be.
So a void * pointer can take address of any type of value like a char, a int, r more sophisticate type like system time (here, thread pointer).
Answer 3:
The '&' mean : take the address of this field.
So if I have
int i = 5;
printf("%i", i);
printf("%i", &i);
the first print will show the value of int : here 5.
The second will show you the address of i, here something like 0x06528A7
the fact with '&' is that you can do this :
int *ptr;
int i = 5;
ptr = &i;
you can now send your 'int *ptr' or another function, to modify it.
It will be too in the main.
Cause while modifying 'ptr', you are modifying 'i' and not a copy.
Hope it helps you!
* in c is used to declare pointers. A pointer is a variable that holds the location of, literally the address-of, a variable stored in computer memory.
So in your question void* retval; declare a void pointer. A void pointer is a special type of pointer that can be pointed at objects of any data type!
char **argv
is a pointer to a pointer to char. Actually it is a variable that holds the address of a variable that is a pointer also
char** argv is equivalent to char **argv, and roughly means
A memory address value that when accessed, contains a memory address value which
when accessed contains a memory address value which contains the first char
C uses null terminated strings, so all that is needed to know the end of a string is the first memory address where it starts. The rest of the routines then search subsequent addresses looking for the null \0 character.
C also uses null terminated lists, so all that is needed to know the end of a list is the first memory address where the list starts (assuming you know the size of the list). In this case, the list is of size sizeof(*char), or in English "the size of a pointer to char". The rest of the list traversing routines then search subsequent indexes in the list (subsequent memory offsets) until it is terminated by the null character.
Try to read it right to left, and it reads "a pointer to a pointer to a char", or in easier terms "a list of strings".
* is a notation to mark pointer You should learn about pointers in c
1)By char** argv, argv is declared as a pointer to pointer to char
2) By void*, it means a variable that can hold address of any kind of variable.
3) as retval is a pointer, it can point to a memory location. and by &retval you are getting address of the variable named retval.
& is called the address of operator.

Confusion with pointers

I am trying to learn C. The reading I've been doing explains pointers as such:
/* declare */
int *i;
/* assign */
i = &something;
/* or assign like this */
*i = 5;
Which I understand to mean i = the address of the thing stored in something
Or
Put 5, or an internal representation of 5, into the address that *i points to.
However in practice I am seeing:
i = 5;
Should that not cause a mismatch of types?
Edit: Semi-colons. Ruby habits..
Well, yes, in your example setting an int pointer to 5 is a mismatch of types, but this is C, so there's nothing stopping you. This will probably cause faults. Some real hackery could be expecting some relevant data at the absolute address of 5, but you should never do that.
The English equivalents:
i = &something
Assign i equal to the address of something
*i =5
Assign what i is pointing to, to 5.
If you set i = 5 as you wrote in your question, i would contain the address 0x00000005, which probably points to garbage.
Hope this helps explain things:
int *i; /* declare 'i' as a pointer to an integer */
int something; /* declare an integer, and set it to 42 */
something = 42;
i = &something; /* now this contains the address of 'something' */
*i = 5; /* change the value, of the int that 'i' points to, to 5 */
/* Oh, and 'something' now contains 5 rather than 42 */
If you're seeing something along the lines of
int *i;
...
i = 5;
then somebody is attempting to assign the address 0x00000005 to i. This is allowed, although somewhat dangerous (N1256):
6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.55) If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
...
5 An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.56)
...
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.
56) The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.
Depending on the architecture and environment you're working in, 0x00000005 may not be a valid integer address (most architectures I'm familiar with require multibyte types to start with even addresses) and such a low address may not be directly accessible by your code (I don't do embedded work, so take that with a grain of salt).
I understand to mean i = the address of the thing stored in something
Actually i contains an address, which SHOULD be the address of a variable containing an int.
I said should because you can't be sure of that in C:
char x;
int *i;
i = (int *)&x;
if i is a pointer, than assign to it something different to a valid address accessible from you program, is an error an I think could lead to undefined behavior:
int *i;
i = 5;
*i; //undefined behavior..probably segfault
here's some examples:
int var;
int *ptr_to_var;
var = 5;
ptr_to_var = var;
printf("var %d ptr_to_var %d\n", var, *ptr_to_var); //both print 5
printf("value of ptr_to_var %p must be equal to pointed variable var %p \n" , ptr_to_var, &var);
I hope this helps.
This declares a variable name "myIntPointer" which has type "pointer to an int".
int *myIntPointer;
This takes the address of an int variable named "blammy" and stores it in the int pointer named "myIntPointer".
int blammy;
int *myIntPointer;
myIntPointer = &blammy;
This takes an integer value 5 and stores it in the space in memory that is addressed by the int variable named "blammy" by assigning the value through an int pointer named "myIntPointer".
int blammy;
int *myIntPointer;
myIntPointer = &blammy;
*myIntPointer = 5;
This sets the int pointer named "myIntPointer" to point to memory address 5.
int *myIntPointer;
myIntPointer = 5;
assignment of hard-coded addresses, is something that shouldn't be done (even in the embedded world, however there are some cases where it's suitable.)
when declaring a pointer, limit yourself to only assign a value to it with dynamiclly allocated memory(see malloc()) or with the & (the address) of a static (not temporary) variable. this will ensure rebust code, and less chance to get the famous segmentation fault.
good luck with learning c.

Resources