I m running this using rextester (online compiler). I followed a tutorial but there is something I don't understand.
I thought it would be better to write my question directly inside the code.
//gcc 5.4.0
#include <stdint.h>
#include <stdio.h>
uint8_t var1 = 17;
uint8_t var2 = 23;
uint8_t arr[] ={7,9,11};
uint64_t *ptr1;//pointer
uint64_t *ptr2;
uint64_t *ptr3;
int main(void)
{
printf("var1: %d\n", var1) ;
//connecting pointer to address
ptr1 = &var1;
printf("address of ptr1: %d\n", ptr1) ;
printf("value of ptr1: %d\n\n", *ptr1) ;
//connecting pointer to address + 1
ptr2 = &var1 +1;
printf("address of ptr2: %d\n", ptr2) ;
//assign value to pointer
*ptr2 = var2;
printf("value of ptr2: %d\n\n", *ptr2) ;
//try on array
ptr3= &arr;//no need to point element 0, or yes?
printf("address of ptr3: %d\n", ptr3) ;
printf("value of ptr3: %d\n\n", *ptr3) ;//i expect 7
return 0;
}
Any help would be very appreciate to help me understand the right behaviour of pointers in c and cpp
I made a lot of tries but i m not able to link a pointer to an array
Edit after response of mato:
Do you think this is a clean way to work with pointer and array? Or there are better solution which take care of not overwriting memory?
//gcc 5.4.0
#include <stdint.h>
#include <stdio.h>
uint16_t var = 17;
uint16_t arr[] ={3,5,7,11,13};
uint16_t *ptr;
int main(void)
{
printf("var: %d\n", var) ;
//connecting pointer to address
ptr = &var;
printf("address of ptr: %d\n", ptr) ;
printf("value of ptr: %d\n\n", *ptr) ;
//try on array
for (uint16_t n =0;n<5;n++){
ptr= &arr[n] ;
printf("item: %d value: %d ads: %d pointer: %d\n", n, arr[n], ptr, *ptr) ;
}
return 0;
}
It seems that you do understand what pointers are and you can use them with basic types.
There are two problems in your code. First is this part:
//connecting pointer to address + 1
ptr2 = &var1 + 1;
Here you assigned some address to variable ptr2. Up to this point there is nothing dangerous about that.
But then you assign a value to memory at that address
//assign value to pointer
*ptr2 = var2;
This is dangerous because you, as a developer, don't know what is stored at that address. Even if you are lucky right now, and that part of memory isn't being used for anything else, it will most likely change once your program gets longer and then you will have hard time searching for the bug.
Now arrays usually are a bit confusing, because when you create an array like this:
uint8_t arr[] = {7,9,11};
three things happen.
Your program allocates continual block of memory, that fits 3 variables of type uint8_t. The 3 variables in this context are called elements.
The elements will get the provided initial values 7, 9 and 11.
An address of first element (the one that contains value 7) will be stored in arr.
So arr is actually of type uint8_t *.
In order to get the last part do what you expect, you just need to change this one line (remove the &):
ptr3 = arr;
EDIT: BTW watch and understand this course and you will be expert on C memory manipulation. Video is a bit dated, but trust me, the guy is great.
EDIT2: I just realised the other answer is absolutely correct, you really need to match the types.
You are doing many mistakes. Up to the point, that g++ does not compile the code and explains why pretty good.
Pointer is an address. There is no "connecting pointer to address". ptr1 = &var1; means literally "store address of var1 in variable named ptr1"
You use incompatible pointer types. So as long as you dereference it (e.g. using *) you are going into undefined behaviour.
I am pretty sure you can reinterpret any type of data as char* or unsigned char*, I image this is true for equivalent types like uint8_t, i.e. single byte types.
You, however, are going the other way, you declare 1-byte data, and are pretending it's a 4 byte int. Basically you force the program to read memory out the variable bounds.
Fact, that *ptr1 and *ptr2 give result you expect is a rather lucky coincidence. Probably memory behind them was zeroed. For ptr3 it isn't because you have filled it with other element of the array (7 and 9).
I believe you also use wrong type specifier for printing. %d is for int, uint8_t should be described as hhu and uint64_t as lu. I am not 100% convinced how fatal this is, because of platform specific widths and integer promotions.
You should use matching types for your pointers and variables.
Related
What is the difference between int* i and int** i?
Pointer to an integer value
int* i
Pointer to a pointer to an integer value
int** i
(Ie, in the second case you will require two dereferrences to access the integer's value)
int* i : i is a pointer to a object of type int
int** i : i is a pointer to a pointer to a object of type int
int*** i : i is a pointer to a pointer to a pointer to object of type int
int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
...
int* pi
pi is a pointer to an integer
int **ppi
ppi is a pointer to a pointer to an integer.
EDIT :
You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.
Let's say you're a teacher and have to give notes to one of your students.
int note;
Well ... I meant the whole class
int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */
Well ... don't forget you have several classes
int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */
And, you also teach at several institutions
int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */
etc, etc ...
I don't think this is specific to opencv.
int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.
int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.
Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)
Imagine you have a few friends, one of them has to give you something (a treasure... :-)
Say john has the treasure
int treasure = 10000; // in USD, EUR or even better, in SO rep points
If you ask directly john
int john = treasure;
int you = john;
If you cannot join john, but gill knows how to contact him,
int john = treasure;
int *gill = &john;
int you = *gill;
If you cannot even join gill, but have to contact first jake who can contact gill
int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;
Etc... Pointers are only indirections.
That was my last story for today before going to bed :-)
I deeply believe that a picture is worth a thousand words. Take the following example
// Finds the first integer "I" in the sequence of N integers pointed to by "A" .
// If an integer is found, the pointer pointed to by P is set to point to
// that integer.
void f(int N, int *A, int I, int **P) {
for(int i = 0; i < N; i++)
if(A[i] == I) {
// Set the pointer pointed to by P to point to the ith integer.
*P = &A[i];
return;
}
}
So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.
int Is[] = { 1, 2, 3 };
int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);
&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.
int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer
int* i; // i is a pointer to integer. It can hold the address of a integer variable.
int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.
Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)
As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.
Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.
Note that
int *i
is not fully interchangeable with
int i[]
This can be seen in that the following will compile:
int *i = new int[5];
while this will not:
int i[] = new int[5];
For the second, you have to give it a constructor list:
int i[] = {5,2,1,6,3};
You also get some checking with the [] form:
int *i = new int[5];
int *j = &(i[1]);
delete j;
compiles warning free, while:
int i[] = {0,1,2,3,4};
int j[] = {i[1]};
delete j;
will give the warnings:
warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted
warning C4154: deletion of an array expression; conversion to pointer supplied
Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.
(Win32 console C++ project, Visual studio 2010)
Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).
T var; // var has type T
T* var; // var has type "pointer to T"
This works no matter what T is:
int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double
// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
// also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
// aka "pointer to int[3]"
int (*var)[3]; // same as above, note how the array type from the typedef
// gets "unwrapped" around the declaration, using parens
// because [] has higher precedence than *
// ("int* var[3];" is an array (size 3) of pointers to int)
This works when T is itself a pointer type:
typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
// which means pointer to pointer to int
// same as:
int** var;
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 4 years ago.
Improve this question
C++ implicitly converts char to int (a larger data type than char) in an expression, which means the following runs without a compile time error:
char a = 'a';
int b = a;
cout << b << endl;
// output
97
Why does the following then throw a compile time error:
char a = 'a';
char* str = &a;
int* ptr;
ptr = str;
Since pointers are of a fixed size (depending on 32/64 bit OS) irrespective of data type they are pointing to, please help me understand why this conversion is illegal.
"Since pointers are of a fixed size" the problem is not the size of the pointer, but the pointed type, a char is not an int, so a char * is not an int *
If you do after *str = <value> all is ok because you only change one byte, but *ptr = <value> will write into more than one byte with unexpected consequences etc
What you want to do is undefined behavior.
You start with a char and get a pointer to it. That's fine. For instance, the pointer could be 0x01. Then you say, actually that pointer to 1 byte, let's make it to a pointer to 4 bytes (32bits assumption for an int).
Obviously, that cannot work. Where are the other 3 bytes coming from?
Then, let's say that it does work. You get alignment issues, because the int should be aligned on 4bytes boundaries, and your pointer is not.
Hence lots and lots of issues what you want to do:
access to inexistent memory
bad memory access (alignement).
This cannot work.
When you assign a char to an int, you create a new variable, a new place with 4 bytes that can receive your data. Here, you don't create a new variable that can hold that data.
You had stated:
C++ implicitly typecasts char to int (a larger data type than char) in an expression, which means the following runs without a compile time error:
char a = 'a';
int b = a;
cout << b << endl;
Output:
97
Then you asked:
Why does the following then throw a compile time error:
char a = 'a';
char* str = &a;
int* ptr;
ptr = str;
In your first example, you declare a char variable named a and assign it the character 'a'. Then you declare an int variable named b and assign it the value of a. Then you call cout on b. This gives a value of 97 which is expected.
What is happening here is the compiler will implicitly cast the value of the char a to an integer. The reason you are seeing the value 97 is because this is the assigned ASCII code for the lower case a. The variable sizes here don't matter.
In your second example where you begin to ask about your compiler error is as follows:
You declare the same char variable as above and assign it the same character value a.
This time you create a pointer to a char and name it str and assign it to the address of a. str now points to a. Next you created a pointer to an int named ptr, then you try to assign str to ptr. Yes all pointers have the same size in memory, but what you are failing to understand here, is how pointer addressing works. Since you are not using new & delete respectively these pointers are on the stack. So on my machine I have ran this code:
#include <iostream>
int main() {
char a = 'a';
char* str = &a;
std::cout << &str << '\n'; // print str's address
int* ptr; // don't assign ptr to anything...
std::cout << &ptr << '\n'; // print ptr's address
}
On my machine the output is:
003BFC34 // this is the stack address of str
003BFC28 // this is the stack address of ptr
Yes both pointers themselves typically take up 4 bytes of memory on a 32bit machine. However, str is pointing to a char type of 1 byte, and ptr is pointing to a int type of 4 bytes on a 32bit machine.
So when you try to assign one pointer to another; this will only work when the pointer types are of the same type! Otherwise, you will either have a compiler error in your case or UB.
Your assumption in the first case is that the char became an int and that is not the case. What happens in your first case is it is taking the value that is represented by 1 byte and implicitly converts it to an integer type that takes 4 bytes and the integer representation of the lowercase a is the ASCII value of 97.
Therefore your 2nd case will not compile:
int main() {
char a = 'a';
char* str = &a;
int* ptr = str; // fails to compile.
return 0;
}
However, there is a way to convert pointers from one type to another
int main() {
char a = 'a';
char* str = &a;
int* ptr = (int*)(str); // C Style Cast - Will Compile!
int* ptr = reinterpret_cast<int*>( str ); // This will compile!
return 0;
}
When you assign int value to char variable and vice versa the compiler do the casting implictly.
But if you assign pointer of type int to address of char variable, it's illegal, because it's int pointer it should point to int variable.
The other direction is the same, char pointer should point to char integer.
The reason is because in memory char represented in one byte while int represented with four bytes.
It's important for memory allocating and freeing.
I'm sure this has been asked before, but a cursory google and stack overflow search didn't turn up the answer.
#include <stdio.h>
int main() {
char a[128][1024];
strcpy(a[0], "hello");
strcpy(a[1], "foo");
strcpy(a[2], "bar");
char **b = a;
printf("%s\n", a[0]); //same as printf("%s\n", a)
printf("%s\n", a[2]+1); //print from 2nd char of 3rd string
printf("%s\n", b); //same as printf("%s\n", a), makes sense
printf("%s\n", b[0]); //segfault???
}
First off, why is the last one a segfault? I'd expect same behavior as array a. How would I access the n-th string from b in a generalized way? What are the differences in treatment between a and b?
On a similar note, the way I understand it, a[n] is syntactic sugar for *(a+n). Is this correct, both for pointers and for arrays? Yet it seems getting different behavior for a and b.
Thanks!
char **b says “At the place where b points, b[0], there is a pointer to a char. And, if I use b[1], b[2],…, those are also pointers to char.”
In contrast char a[128][1024] says “a is 128 arrays of 1024 char.” When you do this, at the place where a is, there are no pointers. There are just char. In memory, it looks like 131,072 char in a row (128•1024 = 131,072).
When you assign char **b = a, assuming the compiler allows you to, you set b to be the address of a. When you use b[0], there should be a pointer there. But there is not. There are just char there. When you pass b[0] to printf, the compiler goes to where b points, loads several bytes as if they were a pointer, and passes the resulting value to printf. Then printf crashes, because the bytes point to some bad location.
A proper definition of b would be char (*b)[1024] = a;.
This
char **b = a;
is a type mismatch as a is char[][] which used without index is a char *.
You might like to switch an all compiler warning (on gcc this is doen via -Wall).
This line
printf("%s\n", b[0]);
dereferences a pointer to a pointer to character, that is an address value. Then it tries to print the address value value as a (0-terminated) string, what most likely is going to access random memory.
Consider the following program.
#include <stdio.h>
int main()
{
int a[10]={0};
printf("%p %p\n", a, &a);
printf("%d %d\n", *a, *(&a));
return 0;
}
a and &a are same. But *a and *(&a) are not. I am out of answers. Please help.
a[i] is the same as *(a + i). So the first element is at the same address as the array itself.
You'll find a more detailed explanation in another question here on SO: How come an array's address is equal to its value in C?
There is no "array base pointer", i.e. there no pointer variable that points to the array. The name of the array refers to the array itself. Therefore you can not take an address of a, instead, &a is handled as a special case.
When you use the name of an array in an expression, it decays into a pointer that points to the first element of the array. However, & and sizeof operators are exceptions.
ANSI C specifies that &a means the address of the array itself, and its type is "pointer to array", not "pointer to array element".
In pre-ANSI compilers, &a would cause a warning.
The address of an array is one of those things you learn early on in C. The address of the buffer is the address of its first element. In the case of
printf("%d %d\n", *a, *(&a));
*a takes the value of a.
*(&a) first take's a's address, and then deferences from that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char szBuffer[100];
char *pBufferPtr = NULL;
int main(int argc, char *argv[])
{
pBufferPtr = szBuffer;
printf("%s %i\n %s %i\n %s %i\n",
"szBuffer's address: ", (int ) szBuffer,
"&szBuffer[0]'s address: ", (int ) &szBuffer[0],
"pBufferPtr's address: ", (int ) pBufferPtr);
printf("\n%s\n", "Program ended.");
return 0;
}
As I learned many years ago, sometimes the best thing to do with pointers is write what used to be called "stub" code, and then examine in the debugger or use "print" (printf) statements. What gets trickier is when you want to modify what a pointer points to, instead of its contents.
a and &a have the same value, but they are different types: int * and int **. You should have got a warning when you compiled you code.
Your second line will work if you add an extra * like this:
printf("%d %d\n", *a, **(&a));
This does make sense: if *a dereferences a and gives the first element of the array, and &a means take the address of a, then *(&a) takes the address of a, dereferences that, and arrives back at a once more.
What is the difference between int* i and int** i?
Pointer to an integer value
int* i
Pointer to a pointer to an integer value
int** i
(Ie, in the second case you will require two dereferrences to access the integer's value)
int* i : i is a pointer to a object of type int
int** i : i is a pointer to a pointer to a object of type int
int*** i : i is a pointer to a pointer to a pointer to object of type int
int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
...
int* pi
pi is a pointer to an integer
int **ppi
ppi is a pointer to a pointer to an integer.
EDIT :
You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.
Let's say you're a teacher and have to give notes to one of your students.
int note;
Well ... I meant the whole class
int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */
Well ... don't forget you have several classes
int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */
And, you also teach at several institutions
int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */
etc, etc ...
I don't think this is specific to opencv.
int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.
int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.
Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)
Imagine you have a few friends, one of them has to give you something (a treasure... :-)
Say john has the treasure
int treasure = 10000; // in USD, EUR or even better, in SO rep points
If you ask directly john
int john = treasure;
int you = john;
If you cannot join john, but gill knows how to contact him,
int john = treasure;
int *gill = &john;
int you = *gill;
If you cannot even join gill, but have to contact first jake who can contact gill
int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;
Etc... Pointers are only indirections.
That was my last story for today before going to bed :-)
I deeply believe that a picture is worth a thousand words. Take the following example
// Finds the first integer "I" in the sequence of N integers pointed to by "A" .
// If an integer is found, the pointer pointed to by P is set to point to
// that integer.
void f(int N, int *A, int I, int **P) {
for(int i = 0; i < N; i++)
if(A[i] == I) {
// Set the pointer pointed to by P to point to the ith integer.
*P = &A[i];
return;
}
}
So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.
int Is[] = { 1, 2, 3 };
int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);
&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.
int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer
int* i; // i is a pointer to integer. It can hold the address of a integer variable.
int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.
Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)
As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.
Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.
Note that
int *i
is not fully interchangeable with
int i[]
This can be seen in that the following will compile:
int *i = new int[5];
while this will not:
int i[] = new int[5];
For the second, you have to give it a constructor list:
int i[] = {5,2,1,6,3};
You also get some checking with the [] form:
int *i = new int[5];
int *j = &(i[1]);
delete j;
compiles warning free, while:
int i[] = {0,1,2,3,4};
int j[] = {i[1]};
delete j;
will give the warnings:
warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted
warning C4154: deletion of an array expression; conversion to pointer supplied
Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.
(Win32 console C++ project, Visual studio 2010)
Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).
T var; // var has type T
T* var; // var has type "pointer to T"
This works no matter what T is:
int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double
// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
// also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
// aka "pointer to int[3]"
int (*var)[3]; // same as above, note how the array type from the typedef
// gets "unwrapped" around the declaration, using parens
// because [] has higher precedence than *
// ("int* var[3];" is an array (size 3) of pointers to int)
This works when T is itself a pointer type:
typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
// which means pointer to pointer to int
// same as:
int** var;