Multidimensional arrays understanding for c - c

I have a question regarding passing an array to another function.
#include <stdio.h>
void print (int ar[]);
main () {
int array[2][2] = {1,2,3,4};
print(array);
}
void print (int ar[]) {
printf("%d\n", ar[0]);
printf("%d\n", *(ar+1));
}
So let's say if i'm passing array to function print. Am I passing address of the first 1-D array (array[0]) or am i just passing the address of the very first variable (array[0][0]).
And as for the print function, in this case, am I correct to say that by printing ar[0], I am printing array[0][0]?
But why is it that for the case of printing *(ar+1), I am actually printing array[0][1] instead of array[1][0]?
Thank you everyone in advance!

If you are passing a two-dimensional array to a function:
int array[NROWS][NCOLUMNS];
print(array);
the function's declaration must match:
void print(int array[][NCOLUMNS])
{ ... }
or
void print(int (*ap)[NCOLUMNS]) /* ap is a pointer to an array */
{ ... }
The 2D arrays which is array of arrays decays a pointer to an array rather than a pointer to a pointer.

So let's say if [I]'m passing array to function print. Am I passing address of the first 1-D array (array[0]) or am [I] just passing the address of the very first variable (array[0][0]).
You are passing a pointer to the first element of array, array[0], which is itself an array. That pointer has the same value as a pointer to array[0][0], but different type. In fact, your code is incorrect in that the argument's type and the function parameter's type do not agree, but as long as the types int(*)[] and int * have the same representation, the reinterpretation will work in practice.
And as for the print function, in this case, am I correct to say that by printing ar[0], I am printing array[0][0]?
Yes, when you call print() as you do in your example, provided that type representations agree as described above.
But why is it that for the case of printing *(ar+1), I am actually printing array[0][1] instead of array[1][0]?
Because ar is a pointer to the first element of array, i.e. the 1D array array[0]. Its elements are array[0][0], array[0][1], etc.. ar + 1 is therefore a pointer to the second element of array[0], which is array[0][1].
You have two options to make your code correct, both of which might help clarify the issues involved. You could change the argument you pass to print() to agree with the function:
print(array[0]);
Alternatively, you could change the declared type of print()'s argument, whith a corresponding alteration to its use:
void print(int (*ar)[2]) {
printf("%d\n", ar[0][0]);
printf("%d\n", *(ar+1)[0]);
}
or
void print(int ar[][2]) {
printf("%d\n", ar[0][0]);
printf("%d\n", *(ar+1)[0]);
}
The latter two change the meaning of *(ar + 1).

Your code is probably not doing what you want. Compile with Wall and you will see some warnings.
You need to change print argument to accept a 2D array (now you are passing int (*)[2] but the function is expecting int *), and then you can print the values correctly.
#include <stdio.h>
void print (int ar[][2]);
int main () {
int array[2][2] = {
{1,2},
{3,4}
};
print(array);
return 0;
}
void print (int ar[][2]) {
printf("%d\n", ar[0][0]); // 1
printf("%d\n", ar[1][0]); // 4
}

When you pass an array to a function, you are using "pass-by-reference" meaning you pass the address of the array.
Am I passing address of the first 1-D array (array[0]) or am i just passing the address of the very first variable (array[0][0]).
No. The way you are passing array currently you are giving the function the 2-D array.
And as for the print function, in this case, am I correct to say that by printing ar[0], I am printing array[0][0]?
No. You still need to specify the number you want to print from ar[0]
But why is it that for the case of printing *(ar+1), I am actually printing array[0][1] instead of array[1][0]?
This is because you are telling the program to go to array in memory and use pointer arithmetic to traverse the array. For example, if you have a char * str variable that contains characters abcde\0 and want to get the character at position 2 you can either do str[2] or *(str+2) which means the same thing and both give the character 'c'.

Related

Is this code well defined by using sizeof operator?

#include <stdio.h>
void test(int arr[]);
int main ()
{
int *arr[3];
int ar1[2] = { 1, 2 };
int ar2[3] = { 3, 4, 5 };
int vla[ar2[1]];
arr[0] = ar1;
arr[1] = ar2;
arr[2] = vla;
for (int i = 0; i < 3; i++)
{
test(arr[i]);
}
}
void test(int arr[])
{
printf("%zu\r\n", sizeof(arr));
}
As the title say: is this valid? and if so, is there a way to make test() output different values by using sizeof on function argument handed in like on array?
Yes it is valid and will give the size of an int pointer (that's what the type of the arr parameter is, there are no array parameters in C) in bytes. 1
To get the size of an array in bytes with sizeof, the argument has to be an actual array, not a pointer.
Consequently, it's not possible to get the size of an array passed as a parameter inside a function without passing an extra parameter specifying the size.
So,
is there a way to make test() output different values by using sizeof on function argument handed in like on array?
no. (Without editing the function body.)
1 If you're wondering how it's possible to pass an array as a pointer parameter, it's because of the implicit array-to-pointer conversion, known as array decaying.
Is this:
void test(int arr[]) {
printf("%d\r\n", sizeof(arr));
}
valid?
It is NOT a valid1 code, however it is equivalent to: sizeof(int*), not size of the array, arr, because as you pass the array as an argument it decays to a pointer2 i.e. it looses the information about the size of the whole array. The only way to convey this information into a function is through an additional, second, parameter.
Is there a way to make test() output different values by using sizeof on function argument handed in like on array?
If you want to print the size of the array you are passing, you could use something like: sizeof(array) as an second argument of the function, where the function signature would be:
void test(int arr[], size_t size);
you could insert the above as second argument and get the size of the first argument.
1. There is a type mismatch between size_t(the returning type of sizeof()) and int (the expected type matching the specifier "%d" in the printf(),, which leads to undefined behaviour.
2. arr[] outside the function represents the whole array as an object and that is why if you apply sizeof() you will get the size of the whole array, however, when passed as argument, arr decays to a pointer of the array's first element and if you apply sizeof() you'll get the size of the type of the pointer.
Is this code well defined by using sizeof operator?
Pedantically: No
sizeof() returns type size_t. "%d" expects type int. Using mis-match type results in undefined behavior (UB). Step 1: Use matching specifier
// printf("%d\r\n", sizeof(arr));
printf("%zu\r\n", sizeof(arr));
// or
printf("%d\r\n", (int) sizeof(arr));
The following prints the size of a pointer arr. The code in main() is not relevant.
void test(int arr[]) {
printf("%zu\r\n", sizeof(arr));
}
// or simply: remove (), \r of dubious value
printf("%zu\n", sizeof arr);

What is the difference between pointer to array and pointer to pointer?

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.

How to print array of element which is store in pointer to an array and this pointer to an array is store in array of pointer?

Hi How to print array of element which is sotre in pointer to an array and this pointer to an array is store in array of pointer?
/* note- ptoa is pointer to an array
aofp is array of pointer */
#include<stdio.h>
int main() {
int i;
int arr[3] = {1,2,3}; // integer array with 3 integers
int (*ptoa)[3]; // ponter to an array
ptoa = &arr; // here i am storing 3 integer
// to ponter to an array
int *aofp[1]; // this is array of pointer
aofp[1] = ptoa; // here i am sotring pointer to an array
/* here i am trying to print all element of arr[3]
using aofp i.e array of pointer*/
for (i = 0; i < 3; i++)
printf("%d", **aofp[i]); // i know this is invalid
//please help me i want print all
//element of arr i.e 1,2,3 using aofp?
}
The Problem
int *aofp[1]; // this is array of pointer
aofp is a one-element array of pointer to int.
aofp[1]=ptoa; // here i am sotring pointer to an array
Here you are trying to assign a pointer to array of int to aofp. These are not compatible types. Also, element [1] doesn't exist. You have two options here, possibly more:
Option 1
You need to declare aofp with the correct type, and access element [0]:
int (*aofp[1])[3];
aofp[0]=ptoa;
for(i=0;i<3;i++)
printf("%d",(*aofp[0])[i]);
putchar ('\n');
The parenthesis in the declaration of aofp are important, because int *aofp[1][3] would be an array-of-array-of-pointers, rather than an array-of-pointers-to-array. Accessing the values of the array uses the same syntax as the declaration. Retrieve element [0] of the array of pointers, dereference the pointer (*), and retrieve element [i] of the array of ints.
However, all this is unnecessarily convoluted, because a one-element array of pointers is pretty much the same as a single pointer. You might as well declare aofp as a pointer to array of int:
int (*aofp)[3];
And now we see that the type of aofp is exactly the same as that of ptoa. You could just as well skip aofp and print out the array pointed at by ptoa directly:
for (i=0;i<3;i++)
printf("%d",(*ptoa)[i]);
putchar ('\n');
Of course, aofp might be declared to have more than one element at a later time.
Option 2
You need to assign a pointer-to-int to aofp[0]. Since ptoa is a pointer-to-array-of-int, dereferencing it results in a pointer to the first element of the int array. (Actually the result is an expression of type array-of-int, but you can't have array values in C, so it is immediately converted to a pointer-to-int.)
int *aofp[1];
aofp[0] = *ptoa;
for (i=0;i<3;i++)
printf("%d",aofp[0][i]);
putchar ('\n');
And, like the previous example, a single-element array is rather useless. You might as well write:
int *aofp;
aofp = *ptoa;
for (i=0;i<3;i++)
printf("%d",aofp[i]);
putchar ('\n');
Or just print out arr[i] directly.
Final note
You may have noticed that I have added a putchar ('\n') call at the end. The reason for this is that a C program might not produce any visible result unless it ends with a new-line.
Okay, you start off all good, except for the typing mistakes in comments maybe; but then you start doing invalid actions after some point, specifically at the line:
int *aofp[1];
This itself is all good actually. You are properly declaring a variable called aofp here, as an array of pointers to integers with a single element, with this statement. However, with the next line:
aofp[1]=ptoa;
It appears that you did not really want to declare that as an array of pointers to integers with a single element, but rather as an array of pointers to arrays of integers with three elements with a single element. This is because, the latter italicised thing is exactly what ptoa is of.
Another important thing here is that arrays in C are zero-based, which means that if you declare an array with the size denoted within square-brackets during declaration, the elements are indexed from [0] to [size - 1], so you should be making the assignment like:
aofp[0]=ptoa;
But this is only after declaring the aofp properly as I've mentioned.
The following code would be the thoroughly corrected version of your code, without changing the way you're handling the job:
#include<stdio.h>
int main( )
{
int i;
int arr[3] = {1, 2, 3};
int(*ptoa)[3];
ptoa = &arr;
// previously was: int *aofp[1];
int(*aofp[1])[3]; // aofp is declared as an
/* 1 2 3 4 */ // array of 1 (3)
// pointer to (2)
// array of 3 (4)
// integers (1)
// previously was: aofp[1] = ptoa;
aofp[0] = ptoa;
for (i = 0; i<3; i++)
// previously was: printf("%d", **aofp[i]);
printf("%d", (*aofp[0])[i]);
return 0; // should be there in C
}
For a code that compiles without warnings/errors, although it might be violating some rules, the following minimal changes could be done:
At your own risk.
aofp[1]=ptoa; to aofp[0] = (int *) ptoa;
**aofp[i] inside printf to (*((int (*)[3]) aofp[0]))[i]
Should do it, but I wouldn't recommend it.
this is exactly what you want:
int main()
{
int i;
int arr[3]={1,2,3};// integer array with 3 integers
int *ptoa = arr;// ponter to an array
int *aofp[1]; // this is array of pointer
aofp[0]=ptoa; // here i am sotring pointer to an array
for(i=0;i<3;i++)
printf("%d",*aofp[0]+i);
}
Is it this what you want to do (http://coliru.stacked-crooked.com/a/f342849a8018de37)?
/* note- ptoa is pointer to an array
aofp is array of pointer */
#include<stdio.h>
int main()
{
int i;
int arr[3]={1,2,3}; // integer array with 3 integers
int* ptoa = arr; // pointer to an array
int* aofp[3]; // this is array of pointer
aofp[0] = ptoa; // here i am storing pointer to an element of array
aofp[1] = ptoa+1; // here i am storing pointer to an element of array
aofp[2] = ptoa+2; // here i am storing pointer to an element of array
/* here i am trying to print all element of arr[3]
using aofp i.e array of pointer*/
for(i=0;i<3;i++)
printf("%d", *aofp[i]);
}

C - Assigning a char* to a char array

I have a function that has an argument 'char *argument', like:
function(char *x) { ... }
When I call this function, I pass a char array as the argument
function(char_array);
In the function, I want to iterate the elements of the array char by char, so my thought was creating an array in the function and to it assign the argument of the function (i.e., char *x) so I'm able to iterate the elements of the array one by one, however, I don't seem to be able to do this assignment and I get an error that says:
incompatible types when assigning to type ‘char[8000]’ from type ‘char *’
So the question is: How do I assign a char pointer to a char array?
You can't. But what you can do is iterate x directly as pointers can be used like arrays just as arrays can be converted to pointers. E.g.
function(char *x)
{
for(int i = 0; i < 100; i++)
printf("%d ", x[i]);
}
Short answer: you can't unless you manually copy the memory from the pointer (and somehow either store the size of the memory into another parameter or get it from another source).
To retain information on the sizeof() of the array, pass it by reference:
void function( const char (&arr)[8000] )
Alternatively you can just use the pointer to access the data (also if the array name decays into a pointer)
void function(char* arr) {
printf("%c", arr[2]);
}
make sure to respect the array boundaries in that case.

statically allocated array as function argument in C

Can I do this in C:
void myFunc(int *vp) {
// do some stuff with vp
}
int main() {
int v[5] = {1,2,3,4,5};
myFunc(v);
return 0;
}
I mean, what would be the correct? myFunc(&v); ?
Thanks!!
Arrays decay to pointers when you pass them as arguments. However, array decay is not the same as taking the address of an array.
"Decay" is how some types are transformed when passed as function arguments. Even though v's type is int [5], it becomes int* when you pass it to a function. This is a behavior a lot of people don't like, but there's nothing to do about it.
Note that, on the other hand, the type of &v is int (*)[5], that is, a pointer to an array of 5 integers. This type doesn't decay, that is, it doesn't transform automatically into another type if you pass it as a function parameter (and that's also why it wouldn't work if you used it in your example, since you need a pointer to integers, not a pointer to an array of integers).
The "correct" thing to do (assuming decay is OK) is to do myFunc(v), just as you're doing in your snippet. Keep in mind that you lose array bounds information when you do it.
Yes ... Your code is correct.
Here v==&v[0] array name is equal to address of first element of array
myFunc(v);
passing array name as argument that means you are passing address of first element in array.
void myFunc(int *vp)
Here you are using pointer. which store the address of first element of array which is passed so you can access the block which is covered with the array.by incrementing the pointer location.
And
myFunc(&v);
&v==&&v[0];
&v is address of address of array first element.
Now
void myFunc(int *vp)
Here You got address of address of array first element, This is not pointing to array. Instead pointing some memory location.Now You can't access the array by incrementing the pointer.
Your code is correct It will work....
But you should take extra care to check the boundary condition.
Please look through the code.
void myFunc(int *vp) {
vp[5] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
similarly
void myFunc(int *vp) {
vp[5] = 30;
myFunc2(vp);
}
void myFunc2(int *vp) {
vp[6] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
This will result in segmentation fault due to stack curruption. Since local variables are in stack.

Resources