difficulty in multidimensional pointers in c? - c

I have a C program that uses pointers but I am not able to understand the output. Why is the first output 1 and the other is 210. They are both pointers to a 3 dimensional array.
I'm not able to find a solution
int main() {
char arr[5][7][6];
char (*p)[5][7][6] = &arr;
printf("%d\n", (&arr + 1) - &arr);
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
return 0;
}
the first output is 1 and the last is 210

C does pointer arithmetic in units of the pointed-to type.
In (&arr + 1) - &arr, &arr is the address of a char [5][7][6] (an array of 5 arrays of 7 arrays of 6 char). Then &arr +1 is the address of one char [5][7][6] beyond &arr and (&arr + 1) - &arr is distance from &arr to &arr + 1 measured in units of char [5][7][6], so the distance is one unit.
In (char *)(&arr + 1) - (char *)&arr), the two addresses are converted to char *, so the arithmetic is done in units of char. So the result is the distance from &arr to &arr + 1 measured in units of char. Since the distance from &arr to &arr + 1 is one char [5][7][6], it is 5•7•6 char, which is 210 char, so the result is 210.
Incidentals
Do not use %d to print the results of subtracting pointers. When two pointers are subtracted, the type of the result is ptrdiff_t, and it may be printed with %td, as in printf("%td\n", (&arr + 1) - &arr));.
To convert pointers to integers, it is preferable to use uintptr_t, defined in <stdint.h>, rather than unsigned.
To print unsigned values, use %u, not %d.
To print uintptr_t values, include <inttypes.h> and use "%" PRIuPTR, as in printf("%" PRIuPTR "\n", (uintptr_t) (p + 1) - (uintptr_t) p);.

First, it's not safe to use %d to print pointer differences, which have type ptrdiff_t (which is a signed version of size_t).
Ignoring that, you have the following declarations:
char arr[5][7][6];
char (*p)[5][7][6] = &arr;
When subtracting two pointers, result is divided by the size of the target (i.e., the inverse of what happens when you add an integer to a pointer, in which case the integer is scaled by the size).
For the first example:
(&arr + 1) - &arr
Here both &arr and &arr + 1 have type char (*)[5][7][6], so the size of what they point to is sizeof(char [5][7][6]). The pointer addition multiplies 1 by this size, and the pointer subtraction divides the difference by this size, canceling it out. So the result is 1, regardless of the target size.
For the second example:
(char *)(&arr + 1) - (char *)&arr
Here the pointer addition again multiplies 1 by sizeof(char [5][7][6]), which is sizeof(char)*5*7*6, i.e. 1*5*7*6 which is 210. But the subtraction divides by sizeof(char) which is 1. So the result is 210.
For the third example:
(unsigned)(arr + 1) - (unsigned)arr
The effect of the unsigned casts is similar to the effect of the char * casts in the previous example. However, in this one two pointers are arr and arr + 1. In this context, the array types "decay" to the pointer types char (*)[7][6]. The size of the pointer target is therefore sizeof(char)*7*6 i.e. 1*7*6 which is 42. So the result is 42.
Finally, for the last example:
(unsigned)(p + 1) - (unsigned)p)
Both p and p + 1 have type char (*)[5][7][6], so the target size is 210. The unsigned casts again result in straight address subtraction, with no division applied to the result. So the result is 210.

char (*p)[5][7][6] = &arr;
Here p is an array of pointers to chars, not a pointer to an array of chars.
printf("%d\n", (&arr + 1) - &arr);
& sign returns address. you are doing math on addresses not values! and anything plus 1 and minus itself will result in 1
(unsigned)p
this casting behavior is not guaranteed and is not safe to do. and you are not dereferencing your pointer anywhere.
You should read more about pointers, types and casting and operator priority before doing this.
I recommend this two videos by Brian Will:
the C language (part 2 of 5)
the C language (part 5 of 5)

Related

C getting the size of an array

the code:
int arr[5] = {10, 20, 30, 40, 50};
printf("%lu %lu\n", *(&arr + 1), arr); // 6422036 6422016
printf("%lu\n", *(&arr + 1) - arr); // 5
Why the second printf prints 5 instead of 20?
There are two points in your interesting question :
How does operation on pointers work ?
What is the difference between arr and &arr ?
1 : How does operation on pointers work ?
Try the following code :
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char **argv) {
int simpleInt= 10 ;
printf("Output 1 : %p %p \n", &simpleInt+1, &simpleInt); // 61FE20 and 61FE1C
printf("Output 2 : %lld \n", &simpleInt+1 - &simpleInt); // 1
printf("Output 3 : %lld\n", (uint64_t)(&simpleInt+1) - (uint64_t)(&simpleInt)); // 4
}
Output 1 : Clearly, the difference between the two printed pointer values is 4
Output 2 : You are performing operation on int *. 1 is added to an operand of type int * and after an operand of type int * is substracted. From an " int * point of view" (if I could simplify it like that), only one is added. So, the output is 1.
Ouput 3 : Each operands of the substraction are casted to a long long unsigned int. So the substraction is done on integers and not on pointers. The ouput is 4, as expected.
2. What is the difference between arr and &arr ?
Let's have a look to the following code
int arr[5] = {10, 20, 30, 40, 50};
printf("Output 1 : %p %p %p \n", arr, &arr, *(&arr) ); //Seems to be the same thing but NOT. int*, int*[5], int*, respectively
// printf("%lld\n", arr - &arr ); // compilation error : int * and int(*)[5]
printf("Output 2 : %lld\n", arr - *(&arr) );
//printf("%lld\n", &arr - *(&arr) ); // compilation error : int(*)[5] and int *
printf("Output 3 : %p %p %p \n", (arr + 1), (&arr + 1), *(&arr + 1) ); // +4, +20, +20
printf("Output 4 : %lld\n", *(&arr + 1) - arr);
printf("Output 5 : %lld\n", (uint64_t)(*(&arr + 1)) - (uint64_t)(arr));
Ouput 1 : The value are the same but not the type of arguments. And this point is very important. The name of an array is a pointer to its first element. In your case, your array is an array of int, so arr is a pointer to int : int*. &arr is the address of your variable arr which is an array of 5 integers. So the type of &arr is int(*)[5]. And the type of *(&arr) is int*
Output 2 : Some lines give compilation errors because of the explanation above. And you could do operations on the same pointer type : arr and *(&arr)
Output 3 : Depending which kind of pointer is incremented, +4 or +20 is obtained. +20 because 1 is added to an operand of type int(*)[5] : 5 * 4 (sizeof int = 4)
Output 4 & 5 : As, in the first point (operation on pointer), your are performing a substraction with int* as operand
Why the second printf prints 5 instead of 20?
Code is living on the edge.
&arr is the address of the array, so + 1 is the address of the next array: 5 int later. So far, this is good.
*(&arr + 1) de-references that address. So we get that next array. Not so good #RobertS supports Monica Cellio. An array passed to a ... function like printf() is converted to the address of the first element, an int *.
*(&arr + 1) - arr subtracts two pointers of the same type int * that are 5 int apart leading to difference of 5 of type intptr_t. Recall that pointer subtraction is the difference of the number of the referenced types (int in this case), not the difference of the pointer values. 5 not 20.
Code attempts to print a intptr_t as an unsigned long with "%lu", which might work, might not (UB). Not so good. Better to use "%td".
printf("%td\n", *(&arr + 1) - arr);

When subtracting two pointers in C

I was playing with pointers in order to fully get the concept and then wanted to subtract two pointers expecting the distance between these two addresses or something, but apparently I was wrong, so here is my code.
int x = 5, y = 7;
int *p = &y;
int *q = &x;
printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));
Why does the program output p - q is 1? Thank you.
It is undefined behavior. According to the standard (N1570):
6.5.6 Additive operators
....
9 When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements.
Note that when allowed, the result is the subscripts difference. So if pointers point to two sequential elements of the same type, the subtraction gives 1, regardless of the size of the type. (This is perhaps the reason why you get 1 in your concrete case.)
Your particular case is cause for undefined behavior since p and q point to unrelated objects.
You can make sense of p-q only if p and q point to the same array/one past the last element of the same array.
int array[10];
int* p = &array[0];
int* q = &array[5];
ptrdiff_t diff1 = q - p; // Valid. diff1 is 5
ptrdiff_t diff2 = p - q; // Valid. diff2 is -5
q - p is 5 in this case since they point to elements of the array that are 5 elements apart.
Put another way, p+5 is equal to q. If you start from p and step over 5 elements of the array, you will point to the same element of the array that q points to.
As an aside, don't use the format specifier %d for printing pointers. Use %p. Use %td for ptrdiff_t.
printf(" p is %p\n q is %p\n p-q is :%td", p, q, p-q);`
// ^^ ^^
See http://en.cppreference.com/w/c/io/fprintf for the valid format specifiers for the different types.
Pointer arithmetic works like that. It doesn't give you differences between two addresses. Instead it will show difference between two variables as if they are stored in an array. so, no matter if your variables (of same type ) are 4 bytes, 8 bytes or 1 byte, if stored in adjacent memory location their pointer subtraction will always result in 1 or -1.
The subtraction of 2 pointers give the distance in between the 2 variables.
For eg.
//let the address of a is 1000 then of a+1 will be 1004
int a[]={1,2,3};
int *p1=a;
int *p2=a+1;
printf("%u",p2-p1);
The result of this will be 1 not 4.
Same here in your case the the location of x and y are consecutive that is why the ans. is 1.
The formula used by pointer substraction is:
( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )
with T being the type of both p1 and p2.
int array[10];
int* p1 = array + 2;
int* p2 = array + 5;
int* a = p2 - p1; // == 3
int* b = p1 - p2; // == -3
int a=5,b=6;
int *ptr=&a,*diff;
diff=ptr;
printf("%p\n",diff);
ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;
printf("%p\n",ptr);
printf("diff==%td\n",(ptr-diff)*sizeof(int));
(diff-ptr) will provide the distance between two variables, but will not provide the memory gap between two pointers.
Important: only the same type of pointer can be subtracted.
The subtraction of two pointers in array will give the distance between the two elements.
Let the address of first element i.e., is 1000 then address of second element a+1 will be 1004. Hence p1 = 1000 and p2 =1004.
p2-p1 = (1004- 1000) /size of int = (1004-1000)/4 =4/4 =1

Different ways on calling array data types to print? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So, I got this for my computer exam (C gcc-4.9.2):
Will the following statements give the same output? Assume a is an array.
a) printf("%d", a + 1);
b) printf("%d", &a + 1);
c) printf("%d", a[0] + 1);
Will the following statements give the same output?
Short answer: No.
Details below:
Assuming a to be defined as
int a[N];
with
N >= 1
and at least the 1st element of a had been initialised properly (case 3. depends on this latter perquisite).
printf("%d", a + 1);
a + 1
evaluates to a pointer with the value
((char*) &a[0]) + 1 * sizeof a[0]
Printing it using %d invokes UB. Anything could happen/be printed. Use %p to print void-pointer's value. Cast the pointer passed using (void*).
printf("%d", &a + 1);
&a + 1
evaluates to a pointer with the value
((char*) &a) + 1 * sizeof a
(The latter value is different from the result of 1. if N > 1.)
Printing it using %d invokes UB. Anything could happen/be printed. Use %p to print void-pointer's value. Cast the pointer passed using (void*).
printf("%d", a[0] + 1);
Some integer value + 1 as per the array's 1st element's initialisation will be printed.
a) printf("%d", a + 1); takes the address of the array a. Adding 1 to it means the pointer now points to the second element (i.e. the pointer is incremented with sizeof(int) bytes). Printing an address as a number is not defined. To print an address, use printf("%p", a);.
b) printf("%d", &a + 1); In &a the type is 'pointer to array of int' and adding 1 will add the size of the whole array, not of an int. So the address of the first element beyond the array will be provided to printf (see above for printing addresses).
c) printf("%d", a[0] + 1); will print the value of the first element of a, plus 1.
C11 draft standard n1570: 6.3.2.1 Lvalues, arrays, and function designators 3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’[...]
Thanks to user EOF who pointed out some errors in earlier versions of this answer.
Note: The name of array variable gives its starting address.
printf("%d", a + 1);
So a equals &a[0]. So the above statement is equal to &a[0]+sizeof(a)*1 which equals &a[1]. That is address of a[1].
printf("%d", &a + 1);
This can be approximated to address of address of a[0] + 1 which will be some gibberish.
printf("%d", a[0] + 1);
This is value of a[0]+1.

%u format Specifier in C

I compiled this code and it gave the the value of '&x' 3 times. That is if &x = 2000 it printed 2036 three times. I want to know the reason for this behaviour assuming an integer requires 4 bytes of memory.
#include <stdio.h>
int main(void) {
// your code goes here
int x[4][3] = {0};
printf("%u %u %u", x+3, *(x+3), *(x+2)+3);
return 0;
}
What will be the output of this code
Anything can happen as the code provokes undefined behaviour by printing a pointer value using the conversion specifier for an unsigned.
To print pointer values use the conversion specifier p.
The address of an array and the address of its 1st element are the same. Pointers to them both however are of different type.
x as well as x + 3 are of type int (*)[3], that is pointing to an array of three ints. Assuming int to be of size 4, an array of three ints is of size 12.
Increasing x (a pointer to int (*)[3]) by three elements one ends up with an address 3 * 12 bytes beyond where x points to. This is called pointer arithmetic.
You're misusing a format specifier and invoking undefined behavior because of that. At that point, what happens is arbitrary and uninteresting.
If you want to print a pointer, use the %p specifier.
x is a pointer to an array of pointers. The array of pointers has 4 elements. Each of these four elements points to 3 integers.
Hence if x = 2000 then,
x[0] = 2000, x[1] = 2012, x[2] = 2024, x[3] = 2036.
Therefore,
x + 3 = 2036 (because x is an array pointer and it increases by 12 each time.)
*(x+3) = x[3] = 2036 again.
*(x+2)+3 = x[2] + 3 = 2024 + 3*4 = 2036 again.
Hence the output will be three same numbers.

Implementation of sizeof operator

I have tried implementing the sizeof operator. I have done in this way:
#define my_sizeof(x) ((&x + 1) - &x)
But it always ended up in giving the result as '1' for either of the data type.
I have then googled it, and I found the following code:
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
And the code is working if it is typecasted, I don't understand why. This code is also PADDING a STRUCTURE perfectly.
It is also working for:
#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)
Can anyone please explain how is it working if typecasted?
The result of pointer subtraction is in elements and not in bytes. Thus the first expression evaluates to 1 by definition.
This aside, you really ought to use parentheses in macros:
#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
Otherwise attempting to use my_sizeof() in an expression can lead to errors.
The sizeof operator is part of the C (and C++) language specification, and is implemented inside the compiler (the front-end). There is no way to implement it with other C constructs (unless you use GCC extensions like typeof) because it can accept either types or expressions as operand, without making any side-effect (e.g. sizeof((i>1)?i:(1/i)) won't crash when i==0 but your macro my_sizeof would crash with a division by zero). See also C coding guidelines, and wikipedia.
You should understand C pointer arithmetic. See e.g. this question. Pointer difference is expressed in elements not bytes.
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
This my_sizeof() macro will not work in the following cases:
sizeof 1 - 4 byte (for a platform with 4-byte int)
my_sizeof(1) - won't compile at all.
sizeof (int) - 4 byte(for a platform with 4-byte int)
my_sizeof(int) - won't compile code at all.
It will work only for variables. It won't work for data types like int, float, char etc., for literals like 2, 3.4, 'A', etc., nor for rvalue expressions like a+b or foo().
#define my_sizeof(x) ((&x + 1) - &x)
&x gives the address of the variable (lets say double x) declared in the program and incrementing it with 1 gives the address where the next variable of the type x can be stored (here addr_of(x) + 8, for the size of a double is 8Byte).
The difference gives the result that how many variables of type of x can be stored in that amount of memory which will obviously be 1 for the type x (for incrementing it with 1 and taking the difference is what we've done).
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
typecasting it into char* and taking the difference will tell us how many variables of type char can be stored in the given memory space (the difference). Since each char requires only 1 Byte of memory therefore (amount of memory)/1 will give the number of bytes between two successive memory locations of the type of variable passed on to the macro and hence the amount of memory that the variable of type x requires.
But you won't be able to pass any literal to this macro and know their size.
But it always ended up in giving the result as '1' for either of the data type
Yes, that's how pointer arithmetic works. It works in units of the type being pointed to. So casting to char * works units of char, which is what you want.
This will work for both literals and variables.
#define my_sizeof(x) (char*) (&(((__typeof__(x) *)0)[1])) - (char *)(&(((__typeof__(x) *)0)[0]))
#define my_sizeof(x) ((&x + 1) - &x)
This is basically (difference of two memory values) / (size of the data type).
It gives you the number in which how many number of elements of type x can be stored. And that is 1. You can fit one full x element in this memory space.
When we typecast it to some other datatype, it represents how many number of elements of that datatype can be stored in this memory space.
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
Typecasting it to (char *) gives you the exact number of bytes of memory because char is of one byte.
#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)
It will give you compilation error as you are typecasting a pointer type to int.
I searched this yesterday, and I found this macro:
#define mysizeof(X) ((X*)0+1)
Which expands X only once (no error as double evaluation of expression like x++), and it works fine until now.
# define my_sizeof(x) ((&x + 1) - &x)
&x gives the address of your variable and incrementing it with one (&x + 1), will give the address, where another variable of type x could be stored.
Now if we do arithmetic over these addresses like ((&x + 1) - &x), then it will tell that within ((&x + 1) - &x) address range 1 variable of type x could be stored.
Now, if we typecast that amount of memory with (char *) [because size of char is 1 byte and incrementing a char * would move with one byte only], then we would get the number of bytes type x is consuming
#include<bits/stdc++.h>
using namespace std;
//#define mySizeOf(T) (char*)(&T + 1) - (char*)(&T)
template<class T>
size_t mySizeOf(T)
{
T temp1;
return (char*)(&temp1 + 1) - (char*)(&temp1);
}
int main()
{
int num = 5;
long numl = 10;
long long numll = 100;
unsigned int num_un_sz = 500;
cout<<"size of int="<<mySizeOf(num) << endl;
cout<<"size of long="<<mySizeOf(numl) << endl;
cout<<"size of long long ="<<mySizeOf(numll) << endl;
cout<<"size of unsigned int="<<mySizeOf(num_un_sz) << endl;
return 0;
}

Resources