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.
Related
Sry, for the weird question. I have written the following programm:
#include <stdio.h>
int main()
{
int a[2];
int **vararr = (int **)a;
int testarr[]= {1, 2 ,3};
printf("%d %d %d\n", testarr[0], testarr[1], testarr[2]);
vararr[0] = (int *)testarr;
printf("%d %d %d\n", testarr[0], testarr[1], testarr[2]);
printf("%d %d %d\n", vararr[0][0], vararr[0][1], vararr[0][2]);
}
which returns:
1 2 3
32765 2 3
32765 2 3
I expected: vararr[0][0] == 1 && testarr[0] == 1
If I rerun the Program the 32765 changes by +-2
I really don't see what I did wrong. I couldn't find anything concerning my problem, since i don't really know how to formulate it properly.
int **vararr = (int **)a; is an invalid conversion since the types are not compatible.
A pointer to pointer:
is not an array
is not a 2D array
cannot point at an array
cannot point at a 2D array
may be used to point at the first element of an array of pointers
Meaning that unless you have an int* array[n] laying around somewhere, there is no sense in using an int**.
Replace the int** with a int* and everything will work fine.
You reinterpret a pointer to integer (decayed from an array) as a pointer to pointer to integer. The pointed types (int and pointer to int) are not pointer-interconvertible, so when you attempt to access the pointed object by indirecting through the reinterpreted pointer, the behaviour of the program is undefined.
I want an array of int pointers
You can declare an array of int pointers like this:
int* ptr_arr[] {testarr};
This is an array of one element. The element is a pointer to int. It points to the first element of testarr.
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.
I wrote two programs which prints out the variable the pointer p points to:
First program:
#include <stdio.h>
int main (void){
int *p;
int a=5, q;
p=&a;
q=*p;
printf("%d", q);
}
Second program:
#include <stdio.h>
int main(void)
{
int a=5;
int*p;
p= (int*)&a;
printf("%d", *p);
return 0;
}
My question:
Both the programs print the value of a which is 5. However, the second program uses p=(int*)&a; instead of just p=&a;. Could someone please tell me the significance of (int*) casting here?
Casting is a way for a programmer to tell the computer that, even though the computer thinks something is one type, we want to treat it as another type.
But here the cast is of no use as here a is an integer and thus address of a will need no cast here for integer pointer.
There is no significance, rather, this cast is superfluous and not required.
In your code, a is of type int, p is of type int *. Hence,
p= (int*)&a;
and
p= &a;
are same and the second one here is recommended.
It's useless.
a is an int, so &a is already a pointer to int.
Useless use of type casting. It's like,
int a = (int) 10 ;
That is typecasting ,to tell the compiler that the value that is assigned to the pointer p that is &a is an integer type(int) but there it is of no use as &a return the address that is assigned to the variable a and it is always an integer.
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.
I know that int (*p)[5] means a pointer which points to an array of 5 ints.
So I code this program below:
#include <iostream>
using namespace std;
int main()
{
int a[5]={0,1,2,3,4};
int (*q)[5]=&a;
cout<<a<<endl;
cout<<q<<endl;
cout<<*q<<endl;
cout<<**q<<endl;
return 0;
}
On my machine the result is:
0xbfad3608
0xbfad3608 //?__?
0xbfad3608
0
I can understand that *q means the address of a[0] and **q means the value of a[0], but why does q have the same value as a and *q? In my poor mind, it should be the address of them! I'm totally confused. Somebody please help me. Please!
Look at it this way:
q == &a
*q == a
**q == *a
You didn't try printing &a. If you do, you'll see that it has the same value as a. Since &a == a, and q == &a, and *q == a, by transitivity q == *q.
If you want to know why &a == a, check out Why is address of an array variable the same as itself?
q and &a are pointers to the array.
*q and a are "the array". But you can't really pass an array to a function (and std::ostream::operator<< is a function); you really pass a pointer to the first element, which is created implicitly (called pointer decay). So *q and a become pointers to the first element of the array.
The beginning of the array is at the same location in memory that the array is, trivially. Since none of the pointers involved are pointers-to-char (which are handled specially so that string literals will work as expected), the addresses just get printed out.
That because array is automatically converted to a pointer, which just has the value of the address of the array. So when you are trying to print print the array using <<a or <<*q, you are in fact printing its address.