This question already has answers here:
Difference between different ways of initializing pointers in c
(7 answers)
why is assigning values to int pointers different to that from char pointers?
(4 answers)
Closed 8 months ago.
What's the difference between 1 and 2?
int *p;
p = malloc(2 * sizeof(int));
int *p = malloc(2 * sizeof(int));
The way I first learned it is number 1, but I've seen someone do it number 2.
Is number 1 and 2 the same thing? I'm assuming it is, but
I'm confused because I don't understand why number 2 is
int *p = malloc(2 * sizeof(int));
not
int p = malloc(2 * sizeof(int));
The way he used it was for array. Later in the code, he used p to save some desired values.
Like this.
p[0] = i;
p[1] = j;
(1) and (2) are the same which are used to initialize pointer with memory allocation.
I think you're confused with the way to initialize pointer, not how to use malloc(). Take a look on some articles about "Initialize pointer" like this one.
int number = 88; // An int variable with a value
int * pNumber; // Declare a pointer variable called pNumber pointing to an int (or int pointer)
pNumber = &number; // Assign the address of the variable number to pointer pNumber
int * pAnother = &number; // Declare another int pointer and init to address of the variable number
int p = malloc(2 * sizeof(int));
This way is not correct to declare a pointer, in this case, p is just an integer variable, not a pointer that points to an integer variable.
What's the difference between 1 and 2?
1 and 2 do the same thing. The compiler should produce exactly the same code. They both declare a variable p of type int * and then initialize p with the pointer returned from malloc.
It's int *p = ... because int * is the type. The variable is p. It is declaring the variable p as the type int * and then assigning to p.
The difference is that 2 does it in a single statement. This is preferable because it ensures the variable is initialized, and it makes it easier to see that the variable is initialized. Uninitialized variables contain garbage and are a common source of errors. It's usually a good idea to initialize every variable immediately, even if it's to 0 or NULL.
You will often see code which declares and initializes variables separately; sometimes all the variables are declared at the top of each function. This is an old style from way back when C required you to declare all your variables at the start of a function. This is no longer an issue. You can declare variables as needed now.
Related
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.
I'm struggling to understand how pointers work.
The way I got it is that, when I declare a pointer to, say, int, I create both a variable that'll contain an address (that must be initialized to even operate on the int) and an int variable. Visually, I'd represent this this way (address;int). For example, if I declared
int* number;
I'd have "number" being the address variable and "*number" being the int variable.
Likewise, declaring something such as int** d should mean to create a pointer to (address;int). That'd be [address;(address;int)].
With this in mind, I was trying to modify the int value of **d by using an external function, incrementer_3, and this so called pass by reference, but I get an error on runtime. So, I was wondering what I'm missing.
#include <stdio.h>
void incrementer(int* a) {
(*a)++;
}
void incrementer_2(int** a) {
(**a)++;
}
void incrementer_3(int*** a) {
(***a)++;
}
int main() {
int b = 7;
incrementer(&b);
printf("%d\n", b);
int* c = (int*)malloc(sizeof(int));
*c = 4;
incrementer_2(&c);
printf("%d\n", *c);
int** d = (int**)malloc(sizeof(int*));
**d = 6;
incrementer_3(&d);
printf("%d\n", **d);
system("pause");
}
FYI the part when I increase b and c works fine.
On a side note, I was also wondering if it's possible to modify the value of *c by using the function "incrementer" and not "incrementer_2". In fact I was just thinking that I could have simply written from main
incrementer(&(*c));
or, in a simpler way
incrementer(c);
but none of them work on runtime.
You need to keep in mind that a pointer need not actually refer to anything, and even if it does refer to something that something need not be valid. Keeping track of those things is your job as a programmer.
By convention an invalid pointer will be given the value 0 (which is what NULL eventually comes to) but that is only convention, other values might be used in some circumstances.
So, with "int* number;" you have declared a pointer-to-int but because it is not initialized you have absolutely no idea what value it contains, dereferencing it at this point is undefined behavior - meaning that most anything could happen if you tried doing so, though in reality it will likely simply crash your program.
The problem with:
int** d = (int**)malloc(sizeof(int*));
**d = 6;
is that while d is initialized *d is not. You could do:
*d = malloc(sizeof(int));
or
*d = c;
but *d needs to be pointed at something before you can use **d.
int b
b is an int. We can refer to it by writing b.
b = 7;
Here we assign a number to b.
int* c
c is a pointer that should point to an int. We can refer to that int by writing *c.
c = (int*)malloc(sizeof(int));
We have found a piece of memory that can hold an int, and made a pointer that points to that piece, and assigned it to c. All is well.
*c = 4;
Here we assign a number to *c. See? *c behaves just like b. But that's only because we have initialised it with a valid pointer! Without that, *c = 4; would be invalid.
int** d
d is a pointer that should point to a thing of type int*, which we can refer to by writing *d. That int* thing, in turn, should point to an int, which we can refer to by writing **d.
d = (int**)malloc(sizeof(int*));
We have found a piece of memory that can hold an int*, and made a pointer that points to that piece, and assigned it to d. All is well. Now that int* we call *d, what does it point to?
Nothing. In order to point it to something, we could have found a piece of memory that can hold an int, and made a pointer that points to that piece, and assigned it to our *d, just as we have done earlier with c. See? *d behaves just like c. In order to use *c we had to initialise c with a valid pointer first. In order to use **d we need to initialise *d with a valid pointer first.
*d = (int*)malloc(sizeof(int));
The problem is that you allocate memory for the int* but you don't allocate any memory for the int or set the pointer of the int.
Should be:
int** d = (int**)malloc(sizeof(int*));
*d = (int*)malloc(sizeof(int));
**d=6;
The way I got it is that, when I declare a pointer to, say, int, I create both a variable that'll contain an address (that must be initialized to even operate on the int) and an int variable.
No, when you declare a pointer you create a variable that knows how to contain an address. When you use malloc() you allocate memory. malloc() returns an address that you may assign to your pointer.
P.S. - incrementer(c) should work just fine
This question already has answers here:
How do pointer-to-pointers work in C? (and when might you use them?)
(14 answers)
Closed 6 years ago.
I am beginner of C Programming language. I saw a code on the book:
#include<stdio.h>
int main(){
int * * k, *a, b=100;
a = &b;
k = &a;
printf("%d\n",* * k);
}
I don't know the meaning of int * *k. Is that a integer pointer or value? what will it point to? what will it contains/store? what's the use of this variable? How can I understand this expression?
int **k
k is a pointer to pointer to int(double pointer) and holds an address of some other pointer variable.
In your example:
int b = 100; /* 'b' is an int, initialized to value 100 */
int *a = &b; /* a is a pointer-to-int*/
int **k = &a; /* k is a pointer-to-pointer-to-int */
See below picture for better understanding:
int** k is a pointer to an int pointer.
It stores a memory address, in that memory address there another memory address in which some integer value is stored.
It's called double pointer. It can be used to store address from single pointer.
You can also create triple pointer to store address from double pointer.
Example: int ***k;
This is called pointer to a pointer.
Here, the output for **k is 100, the value of b.
*(*k) = *(a) = *(address of b) = value of b
*k
means some code will get a value from address k later.
*(*k)
means some code will get a value from address (*k) later.
int **k
means k is intended to be used for address dereferencing for integer use but with a second level. Having this * character just behind a variable name at its definition, makes it a pointer. So k is a pointer to a pointer to an integer.
To get the value of cell that a pointer points to,
*k
is used just like in the definition. Then when it is a second-order pointer then
**k
is used to get its pointed value.
I have to questions about pointers; one theoretical and one practical.
Why, when declaring a pointer in C, must I preface the *var with a type. If a pointer is simply a variable that contains a memory address why does the compiler/language need any more information than that it is a pointer. What is the difference between an int * and a char *. Does this imply that an int * is pointing a some location that contains 2-4 bytes of memory and a char * contains only 1? I have never read anything about the underlying reasoning for why the type matters if ultimately it is a variable pointing to some hexadecimal number as evidence by %p printing them.
Secondly, given this code
int t = 10;
int *i = &t;
int *j = i;
--
*i == 10;
*j == 10;
Why is it that *j is equal to 10 instead of **j being 10? If j is a pointer to i which is a pointer to t which is 10 don't i need to double dereference the variable j? When writing this code in xcode it forces me to use *j.
So these are a few examples of confusion I have had with pointers.
The datatype is required in order to know how many bytes to read when the pointer is dereferenced.
int *i = &t;
Here, the value stored in i is the address of t.
int *j = i;
So now, the value stored in j is the value stored in i which is the address of t. If you wanted to do a double dereference, you'd need to store the address of i.
int **j = &i
why does the compiler/language need any more information than that it is a pointer
To use the pointer only, the compiler doesn't. The type void* means "a pointer to anything".
However, to use the value that is being pointed to, the compiler needs to know the type of what is being pointed to, so that it knows what can be done with it. Dereferencing a void* will cause a compiler error, unless you first cast it to a typed pointer.
Secondly, given this code
j is not a pointer to i. The assignment int *j = i; sets j to the same value as i, which is the address to t (so j would now point to t).
To make j a pointer to i, you would need to declare it as int **j = &i;
why does the compiler/language need any more information than that it is a pointer.
That's because different data types are of different size and size of data types are needed to allocate memory.
What is the difference between an int * and a char *.
int * is a pointer to int and char * is a pointer to a char.
Why is it that *j is equal to 10 instead of **j being 10? If j is a pointer to i which is a pointer to t which is 10 don't i need to double dereference the variable j?
int *j = i; tells the compiler that declare j as pointer to int and point this pointer to the memory location where pointer i points to. Therefore j is a pointer to variable t.
C is a statically typed language. There are other languages, like JavaScript for example, which are dynamically typed, where you can assign objects of different types to the same variable.
Both approaches have their advantages and disadvantages, the most important advantage of statically typed languages is that many errors can be caught at compilation.
It's a design decision.
Given pointers to char, one can do the following:
char *s = "data";
As far as I understand, a pointer variable is declared here, memory is allocated for both variable and data, the latter is filled with data\0 and the variable in question is set to point to the first byte of it (i. e. variable contains an address that can be dereferenced). That's short and compact.
Given pointers to int, for example, one can do this:
int *i;
*i = 42;
or that:
int i = 42;
foo(&i); // prefix every time to get a pointer
bar(&i);
baz(&i);
or that:
int i = 42;
int *p = &i;
That's somewhat tautological. It's small and tolerable with one usage of a single variable. It's not with multiple uses of several variables, though, producing code clutter.
Are there any ways to write the same thing dry and concisely? What are they?
Are there any broader-scope approaches to programming, that allow to avoid the issue entirely? May be I should not use pointers at all (joke) or something?
String literals are a corner case : they trigger the creation of the literal in static memory, and its access as a char array. Note that the following doesn't compile, despite 42 being an int literal, because it is not implicitly allocated :
int *p = &42;
In all other cases, you are responsible of allocating the pointed object, be it in automatic or dynamic memory.
int i = 42;
int *p = &i;
Here i is an automatic variable, and p points to it.
int * i;
*i = 42;
You just invoked Undefined Behaviour. i has not been initialized, and is therefore pointing somewhere at random in memory. Then you assigned 42 to this random location, with unpredictable consequences. Bad.
int *i = malloc(sizeof *i);
Here i is initialized to point to a dynamically-allocated block of memory. Don't forget to free(i) once you're done with it.
int i = 42, *p = &i;
And here is how you create an automatic variable and a pointer to it as a one-liner. i is the variable, p points to it.
Edit : seems like you really want that variable to be implicitly and anonymously allocated. Well, here's how you can do it :
int *p = &(int){42};
This thingy is a compound literal. They are anonymous instances with automatic storage duration (or static at file scope), and only exist in C90 and further (but not C++ !). As opposed to string literals, compound literals are mutable, i.e you can modify *p.
Edit 2 : Adding this solution inspired from another answer (which unfortunately provided a wrong explanation) for completeness :
int i[] = {42};
This will allocate a one-element mutable array with automatic storage duration. The name of the array, while not a pointer itself, will decay to a pointer as needed.
Note however that sizeof i will return the "wrong" result, that is the actual size of the array (1 * sizeof(int)) instead of the size of a pointer (sizeof(int*)). That should however rarely be an issue.
int i=42;
int *ptr = &i;
this is equivalent to writing
int i=42;
int *ptr;
ptr=&i;
Tough this is definitely confusing, but during function calls its quite useful as:
void function1()
{
int i=42;
function2(&i);
}
function2(int *ptr)
{
printf("%d",*ptr); //outputs 42
}
here, we can easily use this confusing notation to declare and initialize the pointer during function calls. We don't need to declare pointer globally, and the initialize it during function calls. We have a notation to do both at same time.
int *ptr; //declares the pointer but does not initialize it
//so, ptr points to some random memory location
*ptr=42; //you gave a value to this random memory location
Though this will compile, but it will invoke undefined behaviour as you actually never initialized the pointer.
Also,
char *ptr;
char str[6]="hello";
ptr=str;
EDIT: as pointed in the comments, these two cases are not equivalent.
But pointer points to "hello" in both cases. This example is written just to show that we can initialize pointers in both these ways (to point to hello), but definitely both are different in many aspects.
char *ptr;
ptr="hello";
As, name of string, str is actually a pointer to the 0th element of string, i.e. 'h'.
The same goes with any array arr[], where arr contains the address of 0th element.
you can also think it as array , int i[1]={42} where i is a pointer to int
int * i;
*i = 42;
will invoke undefined behavior. You are modifying an unknown memory location. You need to initialize pointer i first.
int i = 42;
int *p = &i;
is the correct way. Now p is pointing to i and you can modify the variable pointed to by p.
Are there any ways to write the same thing dry and concisely?
No. As there is no pass by reference in C you have to use pointers when you want to modify the passed variable in a function.
Are there any broader-scope approaches to programming, that allow to avoid the issue entirely? May be I should not use pointers at all (joke) or something?
If you are learning C then you can't avoid pointers and you should learn to use it properly.