int pointer expressions - c

#include<stdio.h>
#include<stdlib.h>
int main ()
{
int a[]={0,1,2,3,4};
int *p[]={a,a+1,a+2,a+3,a+4};
int **ptr=p;
ptr++;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
*ptr++;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
*++ptr;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
++*ptr;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
return 0;
}
The answer for this program is
1 1 1
2 2 2
3 3 3
3 4 4
with gcc.But why is the output for the first printf giving 1 1 1 shouldn't it be 4 4 1?
lets say if p=6004 and and ptr would be 6004 and ptr++ would be 6008.then ptr-p should give 4.pls correct me.thanks..

The result of pointer arithmetic is not exactly the result of their address arithmetic. The output should be ((address of ptr) - (address of p)) / (sizeof(pointed_type))
For example:
int a[] = {0,1,2,3,4};
int *p=a;
int *p2 = p+1;
printf("%d",p2-p) // will print 1

I modified it a little to be certain. The point here is that subtracting pointer returns the number of units i.e. address / size of pointer, not plain difference of address locations.
printf("ptr before %p\n", ptr);
ptr++;
printf("ptr after %p and p %p\n", ptr, p);
printf("%ld %ld %d\n",ptr-p,*ptr-a,**ptr);
On my 64 bit machine, the printed addresses are 8 locations apart with just a single ++. On a 32 bit machine this would be 4. But still the arithmetic difference would return 1.

Related

why does int *b[5] forms a difference of 8 bits instead of 4?

I wrote a program to understand a concept of pointer, where i declared an array of 5 integer pointers and then i tried to print the address of various indices of the array. But what I do not understand is that why is the difference between the consecutive address of indices of 8 bits and not of 4 bits in the output?
My code is:
#include<stdio.h>
void main()
{
int i;
int *b[5];
for(i = 0; i < 5; i++){
b[i] = (int *) malloc(10 * (sizeof(int)));}
printf(" b = %u \n\n",b);
printf(" (b+1) = %u \n\n", (b+1));
printf(" (b+2) = %u \n\n", (b+2));
printf(" *(b+2) = %u \n\n", *(b+2));
printf(" *(b+2)+3) = %u \n\n", *(b+2) + 3);
*(*(b+2) + 3) = 5;
printf(" b[2][3] = %u \n\n", b[2][3]);
}
The output is as follows
b = 79107440
(b+1) = 79107448
(b+2) = 79107456
*(b+2) = 3293532864
*(b+2)+3) = 3293532876
b[2][3] = 3293533008
Clearly the difference between (b+1) and b is of 8 bits.WHY?
First of all, the addresses are in bytes, not bits. Second as to why the difference is 8 bytes, it is because you are on a system that uses 64 bit (8 byte) addresses.
int *b[5] is an array of pointers on int so the difference between b and b + 1 is equal to sizeof(int*) witch is 8 bytes on you pc
First of all, you might use %p to show your pointer's address, not %u. In fact, %d is a signed integer, while %u is an unsigned integer and %p a pointer.
Concerning the answer, on your machine, int is apparently 4 bytes but pointers are 8 bytes (typical 64 bit machine).

Same C pointer showing different values?

I'm running this program:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = &num;
char *pointChar = poinTer+1;
*pointChar = 'A';
printf("Size of Integer: %d\n", sizeof(int));
printf("Address: %d, Value: %d\n", poinTer, *poinTer);
printf("Address: %d, Value: %c\n", poinTer+1, *(poinTer+1));
printf("Address: %d, Value: %c\n", pointChar, *pointChar);
}
*pointChar and *(poinTer+1) should output same result but the output that I'm getting is different. *pointChar is not outputting any value:
Size of Integer: 4
Address: 1704004844, Value: 1025
Address: 1704004848, Value: A
Address: 1704004673, Value:
What's happening here?
When you perform + 1 on a pointer, it does not necessarily increase the memory address by 1. It increases it by sizeof(*ptr).
In this case, poinTer + 1 is equivalent to (char*)poinTer + sizeof(int). This actually makes dealing with arrays much easier.
The good old fashioned ptr[i] is syntactic sugar for *(ptr + i). So, if you have an array of 10 integers, ptr[4] will point to the 5th element rather than 4 bytes away from the base address (since integers are generally 4 or 8 bytes).
So what you've actually done is:
Create an int (num) on the stack and gave it the value 1025
Created a int*(poinTer) on the stack and assigned it the memory address of num
Incremented the pointer by sizeof(int) (which unintentionally points to a different memory address), then cast it to a char* and assigned it to a new pointer.
Assigned the byte pointed to at this new memory address the value 65 ('A').
This is probably what you wanted to do:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = &num;
char *pointChar = (char*)poinTer + 1;
*pointChar = 'A';
printf("Size of Integer: %d\n", sizeof(int));
printf("Address: %d, Value: %d\n", poinTer, *poinTer);
printf("Address: %d, Value: %c\n", (char*)poinTer + 1, *((char*)poinTer+1));
printf("Address: %d, Value: %c\n", pointChar, *pointChar);
}

successive pointer casting in C

I am looking through some example code which employs an API to understand how to properly use the API. I came across some code which I found confusing. Below are the relevant chunks of code:
typedef struct myStruct_id{
randomStruct1 var1;
void *var2;
unsigned char *var3;
randomStruct2 var4;
int var5;
}myStruct_name;
//Function Prototype
void randomFunction(const randomStruct1 *in1, const randomStruct2 *in2, void *handle);
//Global Variables
//assuming data1-5 are of the correct types corresponding to randomStruct1, void, etc.
myStruct_name myStruct_var = {data1, data2, data3, data4, data5};
void *handle = (void*)myStruct_var;
void main(){
myStruct_name *local_var = (myStruct_name *)handle;
//Other code here
local_var.var2 = randomFunction(&local_var.var1, &local_var.var4, &(local_var));
}
My understanding is that the variable handle is a null generic pointer, pointing to the variable myStruct_var (which has been type cast as a null generic pointer). In the main function, the variable local_var is a pointer to the struct myStruct_name, pointing to the value of the pointer handle (which is type cast as a pointer to type myStruct_name) which is pointing to the variable myStruct_var. Next the function randomFunction takes as inputs a pointer just to var1, a pointer to just to var2, and a pointer to the variable local_var.
My confusion is this: the function randomFunction requires as input pointers pointing to structs and a null generic pointer. If local_var is already a pointer, why is the address operator (&) required? Is not the value of local_var already an address? Or is my understanding of what is going on with local_var incorrect?
Also, is there a reason why the final input to randomFunction is parenthetical? That is, why is it &(local_var) instead of just &local_var? Are the parenthesis doing something?
Thanks for reading and any responses!
EDIT: Thanks for the responses indicating I am not referring to a null pointer. I'm referring to the void "data type" here as generic.
If your background is in Java or some other "safe" language, pointers can genuinely be very hard to wrap one's head around. But at the core you're just dealing with memory.
First question - Why address of pointer?
Here's some sample code you can play with. It tries to implement a "shallow" swap in two ways.
#include <stdio.h>
typedef struct {int x; int y; int z;} XYZ;
XYZ s1 = {1, 2, 3};
XYZ s2 = {4, 5, 6};
void swap1(XYZ *a, XYZ *b);
void swap2(XYZ **a, XYZ **b);
int main()
{
XYZ *p = &s1;
XYZ *q = &s2;
printf("Before\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
swap1(p, q);
printf("Swap 1\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
swap2(&p, &q);
printf("Swap 2\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
return 0;
}
void swap1(XYZ *a, XYZ *b)
{
XYZ *t;
t = a;
a = b;
b = t;
}
void swap2(XYZ **a, XYZ **b)
{
XYZ *t;
t = *a;
*a = *b;
*b = t;
}
When you compile and run the above code, you'll get something like this:
Before
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 1 2 3 q: 4 5 6
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280
Swap 1
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 1 2 3 q: 4 5 6
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280
Swap 2
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 4 5 6 q: 1 2 3
Addresses: 0x60103c 0x601048 0x601048 0x60103c 0x7ffd29c58288 0x7ffd29c58280
Note that swap 1 didn't do anything, it was only at swap 2, where addresses of the pointers were used, that a swap happened. Also note that s1 and s2 were left unaltered. You might use this function to implement a sort which doesn't need to copy entire structures.
Second question: Why &(local_var) vs. &local_var?
The differences are not functionally significant. It might have been a remnant of a previous expression, cut & paste, anything. Lots of reasons.

Error while printing the address of array elements in C

I have an error message:
cannot increment value of type int[2]
Is that because the size of int or what?
int arr[2]={10,20};
printf("%p \t %p \t",arr,++arr);
The only reason you are not able to modify its value is once you define a static array with n size then a variable name given to it is treated as constant pointer (Whose value can't be changed).
This restriction is imposed by the compiler because it thinks if you change the value arr then there no way to ensure the accuracy of the program because the base address has been modified
But if you really want to play with the pointers then check these codes:
int main() {
int arr[] = {1,2,3,0};
int *ptr = arr;
while(*ptr != 0) {
printf("%i ",*ptr);
ptr++; // or ++ptr;
}
return 0;
}
Output: 1 2 3
int main() {
int *arr = (int*)malloc(4*sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 0;
while(*arr != 0) {
printf("%i ",*arr);
arr++;
}
return 0;
}
Output: 1 2 3
I hope i made myself clear. Any doubt most welcome.
Please note that you are trying to modify address of array.
Consider:
printf("%p \t %p \t",arr,++arr);
I think you want to print the address of the array element at 2nd position(index 1).
To print the address if arr[1] you can try:
&a[1]
(a+1)
use pointers
use dynamically allocated arrays
#define ARRAY_COUNT 10
int main() {
int *arr = (int*)malloc(ARRAY_COUNT*sizeof(int));
while(*arr != 0) {
printf("%p ",arr);
arr++;
}
return 0;
}
Final Code:
#include <stdio.h>
int main()
{
int arr[2]={10,20};
int *ptr=arr;
printf("%p \t %p \t\n",ptr,ptr+1);
printf("%p \t %p \t\n",arr,arr+1);
printf("%p \t %p \t\n",arr,&arr[1]);
return 0;
}
Sample Output:
sh-4.3$ gcc -o main *.c
sh-4.3$ main
0x7fffdf064110 0x7fffdf064114
0x7fffdf064110 0x7fffdf064114
0x7fffdf064110 0x7fffdf064114
Also note that the statement:
printf("%p \t %p \t",arr,++arr);
is an Unspecified or Implementation-specific behavior since it can (and does) produce different results on different machines. To be concise, the order(left to right or otherwise) of passing the arguments to functions is not strictly specified by C.
Here:
printf("%p \t %p \t",arr,++arr);
Case 1: Left to right parameter passing causes arr address(address of a[0]) to be printed first and then incremented to print the next address(address of a[1])
Output:
0x7fffdf064110 0x7fffdf064114
0x7fffdf064110 0x7fffdf064114
0x7fffdf064110 0x7fffdf064114
Case 2: Right to left parameter passing causes arr address to be incremented first and printed (address of a[1]) and then print the address(address of a[1])
Output:
0x7fffdf064114 0x7fffdf064114
0x7fffdf064114 0x7fffdf064114
0x7fffdf064114 0x7fffdf064114

Pointers in C — adding 1

I have a question about pointers. I am beginning to grasp the concept, but this particular piece of code is threatening that understanding, and I just want to clear it up.
Please note line "B", which is printf("ptr + %d = %d\n",i, *ptr++); /*<--- B*/
I was under the impression that, since *ptr was initialized to &my_array[0], then *ptr++ (which would translate to "whatever is at the address stored in ptr, add one to it") would print out 23, which is the value at my_array[1].
Yet, it prints out the value at my_array[0], which is 1.
I'm confused as to whether the ++ adds to the address itself (like, 1004 becomes 1005) and, since the integer takes up about 4 bytes of space, it would fall into the range of my_array[0] (because that value, 1, would take up addresses 1001, 1002, 1003, 1004, and since my_array[0] starts out at 1001 and only goes up to 1002, then *ptr++ would still print out my_array[0], which is 1)...
or...
Whether *ptr++ goes from my_array[0] (which is just *ptr) to my_array[1] *ptr++, which is what I originally thought.
Basically, please explain what *ptr++ does to this program in particular. Please explain it to me as though I was a five year old.
I really appreciate it, and here's the code:
#include <stdio.h>
int my_array[] = { 1, 23, 17, 4, -5, 100 };
int *ptr;
int main(void)
{
int i;
ptr = &my_array[0]; /* point our pointer to the first
element of the array */
printf("\n\n");
for (i = 0; i < 6; i++)
{
printf("my_array[%d] = %d ", i, my_array[i]); /*<-- A */
printf("ptr + %d = %d\n", i, *ptr++); /*<--- B*/
}
return 0;
}
Change this:
printf("ptr + %d = %d\n",i, *ptr++); /*<--- B*/
to this:
printf("ptr + %d = %d\n",i, *(++ptr)); /*<--- B*/
When you use the postfix version if the increment operator, the value of the object before the increment is returned by value by the expression. The prefix increment operator (which the second set of code in this answer uses) will return the incremented object by reference.
*ptr++ will increment after the printf. You should use *(++p).

Resources