简体   繁体   中英

array passed as array and pointer-C

Why does this program produce p and q as outputs? What is the difference between passing an array as a pointer or as an array.

 #include<stdio.h>

  void fun(char i[]){
   printf("%c,%c", i[1],i[2]);
  }
  void fun2(char *i){
    printf("\n%c,%c", i,i+1);
  }
  int main(){
    char ar[] = {"Aba"};   
    fun(ar);
    fun2(ar);
    return 0;
  }

Output:

  b,a
  p,q

You are printing the ASCII conversion of a pointer address in the second function. You must dereference the pointer via *i and *(i+1) .

what is the difference between passing array as pointer or as an array.

Both functions, fun and fun2 , signatures are equivalent. So, you don't really have an array in fun() as you think. This is because in C, when you pass an array to a function, it gets converted into a pointer to its first element.

So, this statement in fun2()

printf("\n%c,%c", i,i+1);

doesn't print the chars but the addresses i and i+1 . And that's not right either since they don't match with the format specifies you have.

When I compiled your code with gcc, it warns:

In function ‘fun2’:
warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat=]
     printf("\n%c,%c", i,i+1);
            ^
warning: format ‘%c’ expects argument of type ‘int’, but argument 3 has type ‘char *’ [-Wformat=]

As you can see, the format specifiers and the arguments you pass don't match. To print values that i and i+1 point to, you can print it just like how you do in fun() :

 int fun2(char *i){
    printf("\n%c,%c", i[1],i[2]);
 }

To print the value you should use either *i and *(i+1) or i[0] and i[1] in both the functions. i contains the first address cell of the array you have passed. In either cases, both pass their address.

Hope my long answer here helps!

I have taken integers, the concept remains the same with any data type: char, floats, etc, etc.

Okay, a quick short lesson on arrays and pointers.

Thumb rule 1: Arrays and pointers are almost always interchangable but there are exceptions!

Taking a 1-D array, we can declare it like this :-

int arr[10];

This declares a variable named arr which can hold 10 integer elements.

I can similarly use the pointer notation to represent this array using a pointer variable or by using the array name ( arr ) itself.

printf ("%d", arr[2]); // Array method : will print out the third element, indexing starts from 0

Thumb rule 2: Array name(be it 1D 2D 3D 4D) always decays into a pointer or an address.

printf ("%lu", arr) //will print out the base address of the array, i.e address of the first element

How to print the value using a pointer ? Simply, dereference it using * operator.

printf("%d", *arr) //Pointer notation - will print the first value

How to reference the array using another variable?

 int *ptr = arr; //Pointer notation - just simply write the array name as it decays into an address

printf("%d", *ptr); //Pointer notation - prints the first element

Many people say int *ptr is pointer to an array.

In reality it's not. It's actually a pointer to an integer not an array. Why?

Because in the first place we are storing the address of the first integer of the array and then we can traverse it by incrementing the pointer. So, in real pointer is storing the address of an integer(First integer).

Now, coming to 2D arrays :-

Declaration:-

int arr[2][3]; // arrays of 2 rows and 3 columns, total 6 elements

Same above rules implies :-

printf("%d", arr[0][1]); //prints the second element of the first row.

printf("%lu", arr) //prints the base address of the 2D array

Coming to Pointer Notation :-

printf("%d", *(*(arr + 0) + 1); // how this works?

arr contains the address. Adding a integer to it with make you jump to that row.

arr + 1 // gives the second row, i.e. arr is currently pointing to the first element of second row.

Now, further adding an integer to it, will make you skip to that specified column in that particular row.

((arr + 1) // second row  +  2 ) // will you skip to third element of the second row

This is the implicit pointer notation that language gives you, when you choose to treat the array name as a pointer.

Now coming to your problem : - Explicit Pointer Notation:-

What are you trying to achieve is, storing the base address of the 2D array in a pointer.

How to correctly do that ?

int (*ptr)[3]; //reading it goes like this - ptr is a pointer to a 1D array of 3 ints

The 3 here specifies the number of columns your 2D array has.

So what it is doing is, trying to store the base address of first 1D array of that 2D array (which means 0th row base address) into the pointer.

The rest remains the same.

int (*ptr)[3] = arr; // storing the 2D array in ptr

Now, you can use it as a normal pointer(Pointer notation applies on it)

(ptr + 1) //now ptr is pointer to the Second 1D array of that 2D array or you can say to the second row's first element.

Another way you can catch an array in a function is like this:-

I use it very less though.

int main()
{
    int arr[2][2];
    fun(arr);
}

void fun(int catch[][])
{


}


// This is simple to understand and as well as to relate. Now, again catch can be used as pointer or as an array. It depends on you :)

void fun1(int (*ptr)[2])
{
      //my way
printf("%d", ptr[1][1]);
printf("%d", *(*(ptr + 1) + 1));

//answer will be the same
}

//Ptr now contains that 2D array base address, again can be used as an array or a pointer :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM