What is the difference between
int(*a)[5];
int b[5] = { 1, 2, 3, 4, 5 };
i = 0;
a = &b;
for (i = 0; i < 5; i++)
printf("%d\n", *(*a+i));
and
int b[5] = { 1, 2, 3, 4, 5 };
int *y = b;
for (i = 0; i < 5; i++)
printf("%d\n", *y+i);
Both snippets produce same output but I dont understand what is the difference in initialization?
How is
int *y = b;
different to
int(*a)[5];
How to explain this kind of dereferencing?
printf("%d\n", *(*a+i));
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 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 and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
In your second code snippet
int b[5] = { 1, 2, 3, 4, 5 };
int *y = b;
in the declaration of the pointer y the array designator b used as an initializer is implicitly converted to pointer to its first element. The above declaration is equivalent to
int *y = &b[0];
Dereferencing the pointer y you will get the first element of the array of the type int.
Try the following demonstration program.
#include <stdio.h>
int main( void )
{
int b[5] = { 1, 2, 3, 4, 5 };
int *y = b;
printf( "sizeof( *y ) = %zu, *y = %d\n", sizeof( *y ), *y );
}
Its output might look like
sizeof( *y ) = 4, *y = 1
Thus in this for loop
for (i = 0; i < 5; i++)
printf("%d\n", *y+i);
you just outputting the value of the first element of the array b plus the value of the variable i. That is actually the loop does not output elements of the array b because they even are not accessed except the first element of the array..
If you want to output elements of the array you need to write
for (i = 0; i < 5; i++)
printf("%d\n", *( y+i ));
It is the same as to write
for (i = 0; i < 5; i++)
printf("%d\n", y[i] );
because the subscript operator is evaluated like (the C Standard, 6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
In your first code snippet
int(*a)[5];
int b[5] = { 1, 2, 3, 4, 5 };
i = 0;
a = &b;
for (i = 0; i < 5; i++)
printf("%d\n", *(*a+i));
the pointer a is declared as a pointer to array of the type int[5]. So dereferencing the pointer you get an array of the type int[5].
Consider the following demonstration program,
#include <stdio.h>
int main( void )
{
int(*a)[5];
int b[5] = { 1, 2, 3, 4, 5 };
printf( "sizeof( *a ) = %zu\n", sizeof( *a ) );
}
Its output might look like
sizeof( *a ) = 20
In this for loop
for (i = 0; i < 5; i++)
printf("%d\n", *(*a+i));
the expression *a yields the pointed array b that used in the expression *a + i is converted to pointer to its first element. To make it clear you could rewrite the for loop the following way
for (i = 0; i < 5; i++)
{
int *p = *a;
printf("%d\n", *(p + i));
}
That is in this declaration
int *p = *a;
the array obtained by dereferencing the pointer a is implicitly converted to pointer to its first element according to the first provided quote from the C Standard..
Consider one more example. Let's assume that you have a two-dimensional array like for example
int b[2][5] =
{
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 }
};
As it was pointed out above the array used in expressions with rare exception is converted to pointer to its initial (first) element.
The type of elements of the array is int[5]. So you can declare a pointer like
int ( *a )[5] = b;
In this case to output the array you can write for example
for ( int i = 0; i < 2; i++ )
{
for ( int j = 0; j < 5; j++ )
{
printf( "%d\n", *( *a + j ) );
}
++a;
}
After this statement
++a;
the pointer a will point to the second element of the array b that is to its second "row" of the type int[5] due to the pointer arithmetic..
And again this declaration
int ( *a )[5] = b;
is equivalent to
int ( *a )[5] = &b[0];
Almost a side note, but some of the code is incorrect.
Referring to the code below ...
Note that the first snippet, which I'll call foo is correct.
But, the second snippet which I'll call bar is incorrect. It only works [serendipitously] because the b array is 1, 2, 3, 4, 5 (i.e. in sorted order).
If the b array is not sorted, then bar will not print the correct order. This is because *y + i must be *(y + i)
For *y + i, the value fetched for all loop iterations is b[0] to which we add the value of i. To use array/index syntax, we are doing: y[0] + i
What we want is to fetch: b[0] b[1] ... b[4]
The corrected version is in baz. So, we use *(y + i). In array/index syntax, this is y[i].
Here is the code that illustrates this:
#include <stdio.h>
#if SORTED
int b[5] = { 1, 2, 3, 4, 5 };
#else
int b[5] = { 5, 4, 1, 2, 3 };
#endif
void
foo(void)
{
int (*a)[5];
a = &b;
printf("\n");
for (int i = 0; i < 5; i++)
printf("foo: %d\n", *(*a + i));
}
void
bar(void)
{
int *y = b;
printf("\n");
// NOTE/BUG: "*y + i" is incorrect -- see baz
for (int i = 0; i < 5; i++)
printf("bar: %d\n", *y + i);
}
void
baz(void)
{
int *y = b;
printf("\n");
// NOTE/FIX: correct fix for bar
for (int i = 0; i < 5; i++)
printf("baz: %d\n", *(y + i));
}
int
main(void)
{
foo();
bar();
baz();
return 0;
}
Here is the program output:
foo: 5
foo: 4
foo: 1
foo: 2
foo: 3
bar: 5
bar: 6
bar: 7
bar: 8
bar: 9
baz: 5
baz: 4
baz: 1
baz: 2
baz: 3
Related
#include <stdio.h>
int main() {
int a[] = { 5, 5, 8, 34, 12, 2 };
int *p;
int i = 0, c = 0;
int sum = 0;
for(p = &a[i]; i < sizeof(a) / sizeof(a[0]); i++) {
sum += *p;
}
printf("the sum is %d\n", sum);
}
I tried to find the sum of array elements using pointer, but the result is not correct. The value of i does seem to increment, but it is not observed in the expression a[i]. I want to know why incrementing i is not having an effect on indexing the array a.
In this for loop
for(p=&a[i];i<sizeof(a)/sizeof(a[0]);i++){
sum+= *p;
}
the pointer p always points to the first element of the array because the pointer is initialized only once p=&a[i] when i is equal to 0 and is not being changed within the for loop.
If you want to use a pointer to access elements of the array in the for loop then the variable i is redundant. Instead write
int a[] = { 5, 5, 8, 34, 12, 2 };
const size_t N = sizeof( a ) / sizeof( *a );
int sum = 0;
for ( const int *p = a; p != a + N; ++p ){
sum += *p;
}
printf( "the sum is %d\n",sum );
Pay attention to that in this declaration within the for statement
const int *p = a;
the array designator a is implicitly converted to pointer to its first element. So it is enough to write as shown above instead of
const int *p = &a[0];
If you want to use pointers, then you need to get rid of the residue from your earlier code which used the subscript operator.
Here p points at &a[0] (a alone decays into an int* here so no need to write out &a[0]) and end points at one element beyond the last element. The iteration should therefore stop when p == end.
#include <stdio.h>
int main(void) {
int a[] = {5, 5, 8, 34, 12, 2};
int sum = 0;
for (int *p = a, *end = a + sizeof a / sizeof *a; p != end; ++p) {
sum += *p;
}
printf("the sum is %d\n", sum);
}
My background is Java therefore I'm not used to pointers, the following code throws error and I can't see way:
#include <stdio.h>
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int a[3][DIM] = {
{1, 6} ,
{4, 9} ,
{3,17} };
sort_intervals(a, 3);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[0][0]);//<--- error here
}
Error: Access violation reading location
I'm not allowed to change the function signiture
Then you need an array of pointers that point to arrays.
int a_1[DIM] = {1, 6};
int a_2[DIM] = { ... };
int a_3[DIM] = { ... };
int *a[3] = { a_1, a_2, a_3, }; // array of 3 pointers
sort_intervals(a, 3);
or exactly equivalent using compound literals you can:
int *a[3] = { (int[DIM]){1, 6}, (int[DIM]){2, 7}, (int[DIM]){3, 17}};
sort_intervals(a, 3);
even:
sort_intervals((int*[3]){
(int[DIM]){1, 6},
(int[DIM]){2, 7},
(int[DIM]){3, 17},
}, 3);
I am assuming you can change main function.
You could also initialize a as double pointer such as:
int **a = (int**)calloc(3, sizeof(int*)); //setting a as array of 3 pointers
for (int i = 0; i < 3; i++)
*a = (int*) calloc(DIM, sizeof(int)); //assigning pointer to a[0], a[1] and a[2]
Here a is array of 3 integer pointers. a[0],a[1] and a[2] are int pointers.
You can modify a as a[0][0] = 5;
If you can't change the signature as you explained in your comment, then you can get it done using a jagged array:
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int **a = malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++) {
a[i] = malloc(DIM * sizeof(int));
}
a[0][0] = 1; a[0][1] = 6;
a[1][0] = 4; a[1][1] = 9;
a[2][0] = 3; a[2][1] = 17;
sort_intervals(a, 3);
for (int i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[2][0]);//<--- error here
}
How to write this C program pass by pointers and pass by value? I created this program that generates a 10x10 array from -100 to 100 and the main diagonal is read from bottom to top, but I do not know how to create two other programs that are pass by pointers and value
I have to write two more programs with the same input and output only through these two methods. I am a beginner in C and I do not know how to make this.
#include <stdio.h>
#include <stdlib.h>
#define N 10
#define M 10
int my_rand(int max, int min)
{
return (min + rand() / (RAND_MAX / (max - min + 1) + 1));
}
void generate_array(int(*array)[M])
{
printf("Table:");
for (int i = 0; i < N; i++)
{
printf("\n");
for (int j = 0; j < M; j++)
{
array[i][j] = my_rand(-100, 100);
printf("%4d ", array[i][j]);
}
}
}
void print_diagonal(int(*array)[M])
{
printf("\n\nThe main diagonal read from bottom to top:\n");
for (int i = N - 1; i >= 0; i--)
{
printf("%4d ", array[i][i]);
}
}
int *create_array(int(*array)[M])
{
static int new_array[M] = { 0 };
for (int i = 0; i < N; i++)
new_array[i] = array[i][i];
return new_array;
}
void reverseArray(int arr[], int start, int end)
{
int temp;
while (start < end)
{
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
void printArray(int arr[])
{
int i;
for (i = N; i < N; i++)
printf("%4d ", arr[i]);
printf("\n");
}
int main(void)
{
int array1[N][M] = { 0 }, *aux_array;
generate_array(array1);
print_diagonal(array1);
aux_array = create_array(array1);
reverseArray(aux_array, 0, N - 1);
printArray(aux_array);
}
Any help would be much appreciated.
C only supports pass by value. The formal argument in the function definition is always a different object in memory from the actual argument in the function call (assuming the actual argument is itself an object, which it doesn't have to be).
We can fake pass-by-reference semantics by passing a pointer (which is passed by value). Here's a typical example:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
Instead of receiving to integer objects, we receive pointers to two integer objects. We use the unary * operator to dereference the pointers and access the pointed-to objects. If we call that function like so:
int main( void )
{
int x = 1;
int y = 2;
...
swap( &x, &y );
...
return 0;
}
Given the above code, the following are true when we enter the swap function:
a == &x // int *
*a == x == 1 // int
b == &y // int *
*b == y == 2 // int
After we execute the body of the swap function, the following are true:
a == &x // no change
*a == x == 2
b == &y // no change
*b == y == 1
Where things get weird is when you pass array expressions as function arguments. C has a rule that when an array expression is not the operand of the sizeof or unary & operators, or is not a string literal used to initialize a character array in a declaration, the expression is converted ("decays") from an array type to a pointer type, and the value of the expression is the address of the first element.
IOW, given the code
int arr[10];
foo( arr );
Since it's not the operand of the sizeof or unary & operators, the expression arr in the call to foo is automatically converted from type "10-element array of int" to "pointer to int", and the value that gets passed to foo is the address of the first element; IOW, that call is identical to writing
foo( &arr[0] );
and the function definition would be written as
void foo( int *a ) // or int a[], which means the same thing
{
// do something with a[i]
}
IOW, you cannot pass arrays by value in C.
So, looking at your code:
int my_rand(int max, int min)
Both max and min are being passed by value
void generate_array(int(*array)[M])
void print_diagonal(int(*array)[M])
These are receiving a pointer to the first element of a 2D array, so we're faking pass-by-reference.
void reverseArray(int arr[], int start, int end)
We're receiving a pointer to first element of the array (T a[] and T a[N] are both interpreted as T *a in a function parameter declaration), start and end are being passed by value.
void printArray(int arr[])
Again, we're receiving a pointer to the first element of the array.
I'm having an array, that has arrays in every cell. For example, the big array is called arr:
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b}
Now the problem is, if I want to print the small arrs, inside the big array.
Here is my code:
#include <stdio.h>
void printArr(int arr [], int n)
{
for (int i = 0 ; i < n ; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int main()
{
int a[5] = {1, 8, 4, 2, 0};
int b[3] = {1, 4, 2};
int *arr [2] = {a, b};
int n = 0;
for (int i = 0 ; i < 2 ; i++)
{
printArr(*(arr + i), n);
}
}
The output is supposed to be something like this:
1 8 4 2 0
1 4 2
But I can't get the size of each array, since sizeof(*(arr + i) gives me 4, which is the size of the pointer (the name of the array), and not all the array it self.
So what can I do?
Thanks!
The Problem:
The C language only provides a way of finding the size of types.
This gives the subtle differences between applying sizeof to:
1) An array of a type such as:
int a[3];
sizeof(a); // => 3 * sizeof(int)
2) A pointer to the type:
int *ptr;
sizeof(ptr); // => sizeof(int *)
or
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b};
sizeof(arr[1]); // => sizeof(int *)
Some solutions:
Store the size
As jfly proposes store the size of the arrays.
Makes finding the size a constant time operation.
Append an end marker
Adding a end marker like '\0' as used for c-style strings.
You might use INT_MAX or INT_MIN in this case.
The printArr implementation would need to change to:
void printArr(int *arr)
{
int *it = arr;
while(arr != INT_MIN);
{
printf("%d ", *it);
}
printf("\n");
}
Disadvantages:
Finding the size of the array requires iterating over the full array.
Gives the risk of an actual value colliding with the end marker value.
Advantages:
The varying sized array can be passed as a single argument.
Using iterators
Store the pointer to the first and one past the last value.
void printArr(int *begin, int *end)
{
for (int *it = begin; it != end; it++)
{
printf("%d ", *it);
}
printf("\n");
}
int *end_arr[2] = {a + 3, b + 2};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], end_arr[i]);
}
Can be extended to other data structures.
Since arr is an array of pointers, so you can't get the size of array from the pointer which points to an array, you need additional size info:
int size_arr[2] = {sizeof(a) / sizeof(int), sizeof(b) / sizeof(int)};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], size_arr[i]);
}
I am having a hard time understanding where I can use a pointer to an array,
e.g: char (*a)[10];.
So two basic questions.
Please give me a simple example of how just a pointer to an array can be used in C code.
Why would one use it as apposed to just declaring a variable as a pointer and then incrementing/decrementing the address after that point.
Say you have a database query that returns a set of strings. Further, say that you know that these strings are no longer than 9 characters in length. Only, you don't know how many elements are in the set returned by the query.
char (*a)[10] = malloc( NumRecords * sizeof *a );
if ( a == NULL )
{
/* Handle error appropriately */
return EXIT_FAILURE; /* Naive */
}
for ( i = 0 ; i < NumRecords ; ++i )
{
assert(strlen(DbRecordSet[i]) < 10);
strcpy(a[i], DbRecordSet[i]);
}
Example: how to print the elements of an array of num_row rows and 3 columns:
#include <stdio.h>
#define NUM_ROW(x) (sizeof (x) / sizeof *(x))
// print elements of an array of num_row rows and 3 columns
void print(int (*a)[3], size_t num_row)
{
size_t num_col = sizeof *a / sizeof **a;
for (int i = 0; i < num_row; i++) {
for (int j = 0; j < num_col; j++) {
printf("%d\n", a[i][j]);
}
}
}
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(a, NUM_ROW(a));
print(b, NUM_ROW(b));
return 0;
}
Any time you pass an expression with a multi-dimensioned array type to a function, you're going to be working with a pointer to an array:
int a[10][20];
foo(a);
void foo(int (*p)[20]) // or int p[][20]
{ ... }