#include <stdio.h>
typedef struct
{
int (*p)[2][2];
} S;
int main()
{
int aa[2][2] = {{1, 2}, {3, 4}};
S s = { .p = &aa };
printf("Four: %p\n", s.p[1][1]);
return 0;
}
I'm expecting a '4' to be printed but I'm getting a memory location instead.
You dereference it like any other pointer, with the unary * operator.
However you have to note that operator precedence will play a role here, since the array subscripting operator has higher precedence than the dereference operator. Therefore you have to do e.g.
(*s.p)[x][y]
Furthermore you use the wrong format to print an integer. The "%p" format is to print an actual pointer, not an integer. Use "%d".
As an alternative, remember that arrays naturally decays to pointers to their first element. That means for your array aa, using it just like that will decay to &aa[0], which is of type int (*)[2]. That means you could make your variable the same type, and use plain aa in the initialization, and use it like a normal "2d" array:
typedef struct
{
int (*p)[2];
} S;
int main()
{
int aa[2][2] = {{1, 2}, {3, 4}};
S s = { .p = aa }; // Note: Not using the address-of operator here
printf("Four: %d\n", s.p[1][1]); // Using array-indexing works as expected here
return 0;
}
p is a pointer to an array in the int (*p)[2][2]; Its not a 2D array as you tried to print.
Replace
printf("Four: %p\n", s.p[1][1]);/** %p is format specifier to prints the address, Instead use %d to print value **/
with
printf("Four: %d\n", (*s.p)[1][1]);
s is a structure containing a pointer to a 2 dimensional array. So with "s.p" you get the pointer to your 2 dimensional array. Considering that:
(*(s.p))[1][1]
will do the work for you.
I guess you did not intend to use the %p placeholder as it is used to print addresses.
Related
I practiced today some C code, especially array with return function and pointers.
And I found some code which were really confusing and want to know why it is.
So I have first a function which print all elements out of the array.
void function(int *arr)
{
...
printf("%d, arr[i]);
}
Now in main I have a 2D array and a 1D array.
int array2D[2][2] = {{1,2}, {3,4}};
int array1D[3] = {1,2,3};
function(*array2D); // Why do I need here the derefernce pointer
function(array1D); // why I don't need here the deference pointer
And in another case:
void disp( int *num)
{
printf("%d ", *num);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
for (int i=0; i<10; i++)
{
/* Passing addresses of array elements*/
disp(&arr[i]); // why i need here & and above in the function not
}
}
This is really confusing me right now. Can someone explain me this?
The first line
function(*array2D);
is equivalent to
function(array2D[0]);
So you are passing the first array [1,2]. In C an array decays into a pointer
when it is passed to a function.
However, your function function1 should also get the number of
elements of the array.
void function(int *arr, size_t len)
{
size_t i;
for(i = 0; i < len; ++i)
printf("%d\n", arr[i]);
}
Then you can call it2
int array2D[2][2] = { { 1,2} ,{3,4}};
int array1D[3] = {1,2,3};
function(*array2D, sizeof *array2D / sizeof **array2D);
function(array1D, sizeof array1D / sizeof *array1D);
disp (&arr[i]); // why i need here & and above in the function not
Because arr[i] would give you the value stored at the position i, disp
expects a pointer, so you use the &-operator which returns the address of the
array at the position i, which is also equivalent to arr + i.
1Don't call your functions function. Technically that is valid name, but it
would be better if you give your function more explicit names so that just by
reading the name, you know what the functions does.
2Note that sizeof array / sizeof *array only works with arrays. If you have a
function and you expect an array, you will get only a pointer to the array.
In this case you also would need to pass the length of the array.
We're used to the fact that int mike[10] decays to int *, which points to the first thing in the array. So it seems like int sam[5][10] might also decay to int * pointing to the first element of the array. But int sam[5][10] is not a "two-dimensional array of int" that decays to an int pointer, it's an array of five arrays of ten integers. The first thing in sam is the first of the five arrays, so sam decays to a pointer to an array of ten integers, which type is written int (*)[10], though it rarely is written.
So your array2D decays to a different type than integer pointer, which is why your call function(array2D); creates a type mismatch. But your call function(*array2D); does work because (as noted above) *array2D is the same as array2D[0], which is an array of integers, and does decay to int *.
For your second case, arr is an array, but arr[i] is an int, since it is just one position in the array. The ampersand operator makes a pointer of what it operates, so &arr[i] is a pointer, and the call works.
I was trying to differentiate integer pointer and integer array pointer and here's the code that I am using as an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ZLEN 5
typedef int zipdig[ZLEN] ;
#define UCOUNT 3
typedef int (*row5_pt)[ZLEN];
int main(int argc, char *argv[]) {
zipdig cmu = {8, 5, 2, 1, 3};
zipdig mit = {0, 2, 1, 3, 9};
zipdig ucb = {9, 4, 7, 2, 0};
int *univ[UCOUNT] = {mit, cmu, ucb};
int result1 = *univ[1];
row5_pt pt[UCOUNT] = {&mit, &cmu, &ucb};
int result2 = (*pt[1])[1];
printf("\nresult is %d \n", result1);
printf("\nthe size of dereferenced univ is %lu bytes \n", sizeof(*univ[1]));
printf("\nresult is %d \n", result2);
printf("\nthe size of dereferenced pt is %lu bytes \n", sizeof(*pt[1]));
return 0;
}
At first I am confused at the following two assignment:
int *univ[UCOUNT] = {mit, cmu, ucb};
row5_pt pt[UCOUNT] = {&mit, &cmu, &ucb};
here univ is an array of 3 integer pointers, and pt is an array of pointers that point to a 5-element int array. And my confusion is that in the first assignment, mit, cmu and ucb, these array identifiers are regarded as pointers, but when it comes to second assignment, why mit, cmu and ucb are regarded as array, not pointers?
Later I realized that this is due to the different pointer type that I use: the first assignment, the element of univ is an integer pointer, and mit, cmu, ucb are exactly regarded as integer pointer, but for second assignment, the element of pt is a pointer pointing to array, not integers, thus we could not directly use mit, cmu or ucb but have to use their address instead.
Is my understanding correct?
Yes, your understanding is correct.
The reason is the type of the the pointers involved. &mit is a pointer to the array whereas mit (in an expression) is gets converted into a pointer to the array's first element.
int a[10];
int *p = a; // 'a' decays into a pointer to its first element i.e. &a[0]
int *q = &a[0]; // Equivalent to the above
int (*x)[10] = &a; // &a is of type int(*)[10] i.e. a pointer to an array of 10 ints
Also see: What is array decaying?
This question already has answers here:
C: differences between char pointer and array [duplicate]
(14 answers)
Closed 7 years ago.
I've read various articles and questions here on SO about pointers and arrays equivalency. Nearly each article explains it different. I know that arrays and pointers are strongly related and bellow are my experiments with pointers and arrays equivalency, including comments which explain given behavior (feel free to correct me if I'm wrong somewhere). My question is: are arrays are just constant pointers or is there also another differences?
#include <stdio.h>
int main ()
{
// declaring array this way in fact declares a pointer with name "a" which points to the first element in the array:
int a[] = {0,1,2,3,4};
// assigning an array to the pointer in fact assigns the address of the first array element to the pointer, those two are thus equivalents:
int *pa1 = a;
int *pa2 = &a[0];
printf("########################\n");
// REFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%p\n", (a+0)); // a+0 == 0+a
printf("%p\n", a);
printf("%p\n", &a[0]);
printf("%p\n", &0[a]); // a+0 == 0+a
printf("########################\n");
// DEREFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%d\n", *(a+0)); // a+0 == 0+a
printf("%d\n", *a);
printf("%d\n", a[0]);
printf("%d\n", 0[a]); // a+0 == 0+a
printf("########################\n");
// REFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%p\n", (a+1));
printf("%p\n", &a[1]);
// REFERENCING: pointers can use array syntax (following are equivalents)
printf("%p\n", (pa1+1));
printf("%p\n", &pa1[1]);
printf("########################\n");
// DEREFERENCING: assigning values via pointers using pointer/array syntax (following are equivalents)
*(pa1+1) = *(pa1+1) + 10;
pa2[1] = pa2[1] + 10;
// DEREFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%d\n", *(a+1));
printf("%d\n", a[1]);
printf("%d\n", 1[a]);
// DEREFERENCING: assigning values via arrays using pointer/array syntax (following are equivalents)
*(a+2) = *(a+2) + 10;
a[2] = a[2] + 10;
// DEREFERENCING: pointers can use array syntax (following are equivalents)
printf("%d\n", *(pa1+2));
printf("%d\n", pa1[2]);
printf("%d\n", 2[pa1]);
printf("########################\n");
// REFERENCING: those two pointers points to the same address
printf("%p\n", pa1);
printf("%p\n", pa2);
// DEREFERENCING: those two pointers points to the same address
printf("%d\n", *pa1);
printf("%d\n", *pa2);
printf("########################\n");
// This is correct:
pa1++;
printf("%p\n", pa1);
printf("%d\n", *pa1);
printf("%p\n", pa2);
printf("%d\n", *pa2);
printf("########################\n");
return 0;
}
I would say that arrays are just constant pointers, the only thing that misleads me is that the error messages are different when I try to increment array and constant pointer, here is what I mean:
#include <stdio.h>
int main (){
int var1=0;
int * const ptr;
int a[] = {0,1,2,3,4,5};
// This gives an error:
// error: increment of read-only variable ‘ptr’
ptr++;
// This gives an error:
// error: lvalue required as increment operand
a++;
return 0;
}
If they are not the same can you please post some scenario where this difference is obvious?
Arrays and pointers are completely different animals.
Under most circumstances, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", but the array object itself is not a pointer.
This behavior has its roots in the B language, from which C was derived. In B, an array object was a pointer, and the subscript operation a[i] was interpreted as *(a + i) (offset i elements from address stored in a, dereference the result).
Ritchie kept the *(a + i) semantics, but got rid of the explicit pointer; C converts the array expression to a pointer expression instead (except when the array expression is the operand of the unary & or sizeof operators).
You may pretend, that arrays are the same as constant pointers, but in fact they are different types. One notable difference is a result of the sizeof operator. For instance:
#include <stdio.h>
int main(void)
{
int a[] = {0, 1, 2, 3, 4, 5};
int * const p = a;
printf("sizeof(a) = %zu\n", sizeof(a));
printf("sizeof(p) = %zu\n", sizeof(p));
}
For the former, you are getting total size of array. Assuming that sizeof(int) = 4, it prints 24. OTOH, for the latter, you just get the same as size of int pointer.
Also, you cannot use array initializer for pointer variable:
int * const p = {0, 1, 2, 3, 4, 5};
results into compiler's error if you set it with -pedantic-errors flag, e.g.:
error: excess elements in scalar initializer
Another important difference is that arrays are copied for each element during a struct assignment:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct threeNumbers {
int t[3];
} a = {{1, 2, 3}}, b = {{4, 5, 6}};
int main(void)
{
a = b;
a.t[0] = 100;
printf("%d\n", a.t[0]); // prints 100
printf("%d\n", b.t[0]); // prints 4
}
This is not the case for pointers. Structures with const pointers cannot be assigned to each other. For non-const pointers members, only an adress is copied. If pointers were set with malloc, then this might result into memory leak.
I'm new in programming and learning about pointers in array. I'm a bit confused right now. Have a look at the program below:
#include <stdio.h>
int fun();
int main()
{
int num[3][3]={23,32,478,55,0,56,25,13, 80};
printf("%d\n",*(*(num+0)+1));
fun(num);
printf("%d\n", *(*(num+0)+1));
*(*(num+0)+0)=23;
printf("%d\n",*(*(num+0)));
return 0;
}
int fun(*p) // Compilation error
{
*(p+0)=0;
return 0;
}
This was the program written in my teacher's notes. Here in the main() function, in the printf() function dereference operator is being used two times because num is pointer to array so first time dereference operator will give pointer to int and then second one will give the value at which the pointer is pointing to.
My question is that when I'm passing the array name as argument to the function fun() then why *p is used; why not **p as num is a pointer to array?
Second thing why *(p+0) is used to change the value of zeroth element of the array; why not *(*(p+0)+0)=0 as in the main() function *(*(num+0)+0) is used to change the value of zeroth element?
The whole thing is very confusing for me but I have to understand it anyway. I have searched about this and found that there is a difference between pointer to array and pointer to pointer but I couldn't understand much.
The trick is the array-pointer-decay: When you mention the name of an array, it will decay into a pointer to its first element in almost all contexts. That is num is simply an array of three arrays of three integers (type = int [3][3]).
Lets analyse the expression *(*(num + 1) + 2).
When you mention num in the expression *(num + 1), it decays into a pointer to its first element which is an array of three integers (type = int (*)[3]). On this pointer pointer arithmetic is performed, and the size of whatever the pointer points to is added to the value of the pointer. In this case it is the size of an array of three integers (that's 12 bytes on many machines). After dereferencing the pointer, you are left with a type of int [3].
However, this dereferencing only concerns the type, because right after the dereferencing operation, we see expression *(/*expression of type int[3]*/ + 2), so the inner expression decays back into a pointer to the first array element. This pointer contains the same address as the pointer that results from num + 1, but it has a different type: int*. Consequently, the pointer arithmetic on this pointer advances the pointer by two integers (8 bytes). So the expression *(*(num + 1) + 2) yields the integer element at an offset of 12 + 8 = 20 bytes, which is the sixth integer in the array.
Regarding your question about the call of fun(), that call is actually broken, and only works because your teacher did not include the arguments in the forward declaration of fun(). The code
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
fun(num);
}
would have generated a compile time error due to the wrong pointer type. The code of your teacher "works", because the pointer to the first array in num is the same as the pointer to the first element of the first array in num, i. e. his code is equivalent to
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
//both calls are equivalent
fun(num[0]);
fun(&num[0][0]);
}
which would compile without error.
This example shows a matrix, pointers to the first integers of arrays, and pointer to pointer
#include<stdio.h>
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */
int main()
{
/* matrix */
int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}};
/* three pointers to first integer of array */
int *pnum[3] = {num[0], num[1], num[2]};
/* pointer to pointer */
int **ppnum = pnum;
printf("%d\n", *(*(num+1)+2));
fun(num);
printf("%d\n", *(*(num+1)+2));
pnum[1][2] = 2;
printf("%d\n", *(*(num+1)+2));
ppnum[1][2] = 3;
printf("%d\n", *(*(num+1)+2));
return 0;
}
int fun(int (*p)[3])
{
p[1][2]=1;
return 0;
}
You do not actually need any pointers to print anything here.
Your int num[3][3] is actually an array of three elements, each of which is an array of three integers. Thus num[0][0] = 23, num[1][1] = 0, and so on. Thus you can say printf("%d", num[0][0]) to print the first element of the array.
Pointer to variable:
Pointer is variable which stores the address( of a variable). Every one know that.
Pointer to Array:
An array is a variable which has the starting point(address) of group of same objects.
And the pointer is a variable which stores the starting point(address) of an Array.
For example:
int iArray[3];
iArray is a variable which has an address value of three integers and the memory is allocated statically. And the below syntax is provided in a typical programming languages.
// iArray[0] = *(iArray+0);
// iArray[1] = *(iArray+1);
// iArray[2] = *(iArray+2);
In the above the iArray is a variable through which we can access the three integer variables, using any of the syntax mentioned above.
*(iArray+0); // Here iArray+0 is the address of the first object. and * is to dereference
*(iArray+1); // Here iArray+1 is the address of the second object. and * is to dereference
So simple, what is there to confuse.
The below lines are for your understanding
int iArray1[3];
int iArray2[3][3];
int *ipArray = 0;
ipArray = iArray1; // correct
ipArray = iArray2[0]; // correct
ipArray = iArray2[2]; // correct
int **ippArray = iArray2; // wrong
As per the above last line, compiler will not take it as a valid assignment. So **p is not used.
Pointer arthmatic cannot be applied on double arrays because of the way memory is allocated.
Im relatively knew to C, i am used to program in Java so i find C a little bit difficult in what concerns arrays. I still cofuse myself with this cases:
int a [];
int* a;
int *a;
In java, i would do something like this to return an array in a function:
int [] returnArr(int [] a){
... modify a ...
return a;
}
int [] a = {...};
int [] b = returnArr(a); ##
How can i do the same in C, specially the parts with ##.
EDITED:
I have this function:
float *normalizeValues(float *v, float maxY){
int size = sizeof(v) / sizeof(float);
float max = findMax(v);
float ratio = maxY / max;
int i;
for(i = 0; i < size ; ++i){
v[i] = v[i] * ratio;
}
return v;
}
And im doing the following:
float vert [] = {306, 319, 360, 357, 375, 374, 387, 391, 391, 70, 82, 94, 91, 108, 114, 125, 127, 131};
int i = 0;
float *vert2;
vert2 = normalizeValues(vert, 0.7);
for(i = 0; i < sizeof(vert2) / sizeof(float); ++i){
fprintf(stdout,": %f\n",vert2[i]);
}
And the output is only 1 element.
EDIT: To directly answer your updated question: you have to pass in the size of the array. C has no mechanism to store the size of arrays like Java does. If the compiler knows about the size of the array because the array is a global or local variable, not dynamically allocated, then you can use the sizeof() operator. Otherwise, you have to know the size separately, or use sentinel values in your array (such as a 0.0 at the end, or a NULL).
As for arrays, pointers and arguments in general, see below:
You will be returning a pointer to the array, which is indicated with the '*' syntax:
int *returnArr(int[] a) {
// modify a...
return a;
}
int a[] = { ... };
int *b;
b = returnArr(a);
A few things to note:
You can't do assignments in variable declarations that involve non-constant expressions (e.g., function calls). This might have changed in C99, though.
The brackets go after the variable name, unlike in Java where they are part of the type. Even though Java's syntax is more consistent, it doesn't quite make sense in C where you often give the array size in the brackets in the variable declaration:
int a[3] = { ... };
There's no way to specify that a function returns an array as opposed to a plain pointer. In C, array references decay to pointers (though pointers and arrays are NOT the same thing, as is commonly claimed). That means that whenever you pass an array around, C only provides a means to a pass a pointer to the array. The whole array isn't actually copied. As it happens, the name of the array is also a pointer to the first element of the array.
Please also take note of what user268396 says in their answer. If you are planning to create a new array and return it, you'll need to either allocate the array dynamically, or have a pointer to an already allocated array be passed in (which is what it seems like you are kind of doing anyway).
You can't. When the function returns the stack frame will be wiped out (typically) and your generated array will be clobbered by that. You can however edit the function prototype to accept a pointer to the array to modify. That kind of function argument is known as an "output parameter". Example:
void function func(int a, int b, int[2] to_modify)
{
to_modify[0] = a;
to_modify[1] = b;
}
int main()
{
int foo[2];
func(1, 2, foo);
printf("Result: foo[0] = %d, foo[1] = %d\n", foo[0], foo[1]);
return 0;
}
This will print "Result: foo[0] = 1, foo[1] = 2".
Hope this helps
#include<stdio.h>
void change(int *c)/*Pointer c now has the first location of the array a[]*/
{
*(c+0) = 0;/*assign values to the array by adding step-size to the first array position*/
*(c+1) = 1;
*(c+2) = 2;
*(c+3) = 3;
*(c+4) = 4;
}
main()
{
int a[5]={10,20,30,40,50}; /* Declare and Assign an array a[] of size 5.*/
int *b = a; /*Declare and assign a Pointer to the location of the array.*/
change(b); /*pass the pointer(which is now pointing to first position of array) to the change() function.*/
printf("%d,%d,%d,%d,%d,",a[0],a[1],a[2],a[3],a[4]);/*Print the changed value.*/
}
Output: 0,1,2,3,4,
From Java point of view, Pointers are simply like(not exactly) Object references.
Object O;
O = New SomeClassName();
Like Object Reference O is pointing to some Actual Object of type SomeClassName, so does pointers in C:
int *b;
b = &a;
Variable b is simply pointing to the address location to a.
Taking a deep dive into array concepts:
int a[5];
int *b = a;
Here we are just saying like Mr.*b point to the first location of group a i.e. a[0].
Now the power pointer in C is that from now on, here after:
*b means a[0]
*(b+1) means a[1]
*(b+2) means a[2]
*(b+3) means a[3]
*(b+4) means a[4]
This means you change in *(b+4), you're changing a[4].
int* returnArr(int a[]){
//modify a
return a;
}
One need mention is when you use an array in the parameter list of a function, it will be converted into a pointer. So in main(...)'s declaration, char *argv[] and char **argv are actually same. In this case, int a[] and int* a are same. But array and pointer is not the same thing.
Take the following code as an example:
int a[10];
int main(){
int *p = a;
p[5] = 4;
return p[5];
}
p is a pointer, when we access p[i], note that the address of p is not the address of a, the content of p is the address of a. Then the code will:
access the memory to get the content of p, i.e. the address of a.
compute the offset based on i and type of the pointer(int).
access the memory to get the result.
a is an array of int, if we access a[i], the address of a is just the address of a[0], the code will:
Compute the offset based on i and the type int.
Access the memory.
Pointer and array are different types. So if you declare int *p in one file and use it in that file, but define the p as an array in another file, that will cause problem.
You may also wonder about int *p = a, in ANSI, if you use an array(its name) as an expression, the compiler will convert it into a pointer, pointing to the very first element of the array.
Update based on Jim Balter's comments:
If you use an array(its name) as an expression, the compiler will not always convert it into a pointer, pointing to the very first element of the array. For instance, in sizeof(p->q->a), p->q->a is an expression but if a is an array it isn't converted into a pointer.
"Except when it is the operand of the sizeof 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’’ that points to the initial
element of the array object.
In C, you can only return a pointer of an array in a function.
For example, if you want to return a string(array of char) in a function, you can return a pointer to a null-ended string. If you want to return an array of some other type(int, user-defined struct, etc), you can alloc some memory to store the array, and return the pointer of the array, return the size of the array in the parameter.
example:
int *function(int *size)
{
*size = 10;
int *intP = (int *)malloc((*size)*sizeof(int));
return intP;
}