简体   繁体   English

数组作为数组和指针C传递

[英]array passed as array and pointer-C

Why does this program produce p and q as outputs? 为什么该程序产生pq作为输出? 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. 您正在第二个函数中打印指针地址的ASCII转换。 You must dereference the pointer via *i and *(i+1) . 您必须通过*i*(i+1)解引用指针。

what is the difference between passing array as pointer or as an array. 将数组作为指针或数组传递有什么区别?

Both functions, fun and fun2 , signatures are equivalent. funfun2这两个函数的签名是等效的。 So, you don't really have an array in fun() as you think. 因此,您实际上并不像您想的那样在fun()有一个数组。 This is because in C, when you pass an array to a function, it gets converted into a pointer to its first element. 这是因为在C语言中,当您将数组传递给函数时,它将转换为指向其第一个元素的指针。

So, this statement in fun2() 所以,这条语句在fun2()

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

doesn't print the chars but the addresses i and i+1 . 不打印字符,但地址ii+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: 当我使用gcc编译您的代码时,它会发出警告:

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() : 要打印ii+1指向的值,可以像在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*(i+1)i[0]i[1] i contains the first address cell of the array you have passed. i包含您传递的数组的第一个地址单元。 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. 我采用整数,该概念对于任何数据类型均相同:char,floats等,等等。

Okay, a quick short lesson on arrays and pointers. 好吧,关于数组和指针的简短课程。

Thumb rule 1: Arrays and pointers are almost always interchangable but there are exceptions! 经验法则1:数组和指针几乎总是可以互换的,但是也有例外!

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. 这将声明一个名为arr的变量,该变量可以容纳10个整数元素。

I can similarly use the pointer notation to represent this array using a pointer variable or by using the array name ( arr ) itself. 我可以类似地使用指针表示法通过指针变量或通过使用数组名( arr )本身来表示此数组。

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. 经验法则2:数组名称(无论是1D 2D 3D 4D)总是衰减为指针或地址。

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. 许多人说int * ptr是指向数组的指针。

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. arr包含地址。 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. 您要实现的目标是将2D数组的基地址存储在指针中。

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. 此处的3指定2D数组具有的列数。

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. 因此,它正在尝试将2D数组的第一个 1D数组的基地址(即第0行基地址)存储到指针中。

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 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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