简体   繁体   English

需要理解C中的一些指针

[英]Need to understand some pointers in C

Well, i have this simple example that we must use in school but i dont understand why we must use pointers and what they exactly do in same cases.好吧,我有一个我们必须在学校使用的简单示例,但我不明白为什么我们必须使用指针以及它们在相同情况下的作用。

   int **create(int lines, int columns)
   {
   int **p, i;
   p = (int **) malloc(lines * sizeof(int *));
   for(i = 0; i < lines; i++)
      p[i] = (int *) malloc(columns * sizeof(int));   
   return p; 
   } 

I google that ** is pointer to pointer.我谷歌**是指向指针的指针。 Simply pointer pointing to pointer that has stored address of variable.简单地指向已存储变量地址的指针的指针。 But WHY I should do that?但为什么我应该这样做? And then these two lines of code looks to have totally random pointers然后这两行代码看起来有完全随机的指针

p = (int **) malloc(lines * sizeof(int *));
p[i] = (int *) malloc(columns * sizeof(int));

Basically I understand that pointer is pointing to address of variable or something but don't know what is happening here.基本上我知道指针指向变量的地址或其他东西,但不知道这里发生了什么。 Please if can somebody explain it to me.请有人向我解释一下。 Thanks for your time.谢谢你的时间。

A pointer can also be understood as an array.指针也可以理解为数组。 You allocate some space with malloc , and you can set items with the [] operator, just like as arrays.您可以使用malloc分配一些空间,并且可以使用[]运算符设置项目,就像数组一样。

int* arr = (int*)malloc(sizeof(int)*3);
arr[1] = 5;
printf("%d", arr[1]); //output is 5

Pointers to pointers can be understood as two-dimensional arrays: You allocate space for the pointers , then allocate each pointer as an array.指向指针的指针可以理解为二维数组:您为指针分配空间,然后将每个指针分配为一个数组。

int** arr = (int**)malloc(sizeof(int*) * 3);
for (int i = 0; i < 3; i++) {
    arr[i] = (int*)malloc(sizeof(int) * 3); // each element is going to be an array of 3 integers
}
arr[2][2] = 4;
printf("%d", arr[2][2]); // 4

This function creates a matrix which is a two dimensional array.此函数创建一个矩阵,它是一个二维数组。

An array is a sequence of elements stored contiguously in memory.数组是连续存储在内存中的元素序列。 With malloc we allocate a memory block that can be used as an array.使用malloc我们分配了一个可以用作数组的内存块。 We then hold a pointer to the block of elements.然后我们持有一个指向元素块的指针。 We can then use the notation a[i] to identify the ith element of the array whose address is stored in a .然后我们可以使用符号a[i]来标识数组的第 i 个元素,其地址存储在a

The expression malloc(n * sizeof(int));表达式malloc(n * sizeof(int)); allocates a memory block with room for n integers.n整数分配一个内存块。 Note that it returns a pointer to an integer : int * .请注意,它返回一个指向整数的指针: int *

When we create a two dimensional array, each row is an array allocated with the above instruction.当我们创建一个二维数组时,每一行都是一个用上述指令分配的数组。 n is replaced by the number of columns. n被列数替换。

All the rows are then bundled together with an array of arrays.然后将所有行与一组数组捆绑在一起。 Remember that an array is of type int * .请记住,数组的类型是int * Thus an array of arrays has int * values as element.因此,数组数组以int *值作为元素。 It's type is then int ** .它的类型是int **

The first malloc in your code allocates the array that will hold all the rows array.代码中的第一个malloc分配将保存所有行数组的数组。 This is why its type is int ** .这就是为什么它的类型是int ** Its byte size is lines time the byte size of an int * .它的字节大小是lines int *的字节大小。

In the for loop, each row is instantiated and assigned to the corresponding element of the array p .for循环中,每一行都被实例化并分配给数组p的相应元素。

The pleasant thing of the returned two dimensional array is that you may then identify on of its elements by the expression a[i][j] .返回的二维数组令人愉快的事情是,您可以通过表达式a[i][j]识别其元素。


Note that there is a mistake in this code.请注意,这段代码有一个错误。

The for loop is for(i = 0; i < riadky; i++) . for 循环是for(i = 0; i < riadky; i++) riadky is an undefined variable. riadky是一个未定义的变量。 It's not the right variable name.这不是正确的变量名。

Now that you hopefully understand the code, could you find the correct variable name to put there ?现在您希望理解代码,您能找到正确的变量名吗? You should be able to find it from my explanations.你应该能够从我的解释中找到它。

Some pictures should help.一些图片应该会有所帮助。

We start with the object p :我们从对象p开始:

   int **
   +–––+
p: |   |
   +–––+

p has type int ** , meaning it can store the address of an object of type int * . p类型为int ** ,这意味着它可以存储类型为int *的对象的地址。

For simplicity's sake, we'll assume both lines and columns are 2 .为简单起见,我们假设linescolumns都是2 So we start by dynamically allocating enough space for two objects of type int * , and store the address of the first of those objects into p :因此,我们首先为两个int *类型的对象动态分配足够的空间,并将这些对象中p一个的地址存储到p

   int **        int *
   +–––+         +–––+
p: |   | ––––––> |   |
   +–––+         +–––+
                 |   |
                 +–––+

The array subscript operation a[i] is defined as *(a + i) - given a starting address a , offset i elements ( not bytes ) from that address 1 and dereference the result 2 .数组下标操作a[i]定义为*(a + i) - 给定起始地址a ,从该地址1偏移i元素不是字节)并取消引用结果2 So the expression p[0] refers to the first element and p[1] the second:所以表达式p[0]指的是第一个元素,而p[1]指的是第二个:

   int **        int *
   +–––+         +–––+
p: |   | ––––––> |   | p[0]
   +–––+         +–––+
                 |   | p[1]
                 +–––+

Now, for each p[i] , we allocate enough space for 2 int objects and assign the address of the first of each set into p[i] :现在,对于每个p[i] ,我们为 2 个int对象分配足够的空间,并将每个集合中p[i]一个的地址分配给p[i]

   int **        int *          int
   +–––+         +–––+          +–––+
p: |   | ––––––> |   | p[0]-––> |   | p[0][0]
   +–––+         +–––+          +–––+
                 |   | p[1]–+   |   | p[0][1]
                 +–––+      |   +–––+
                            |
                            |   +–––+
                            +-> |   | p[1][0]
                                +–––+
                                |   | p[1][1]
                                +–––+

As for why you need to use multiple levels of indirection ( ** , *** , etc.)...至于为什么需要使用多个间接级别( *****等)...

For any object E of type T , the expression &E evaluates to the address of that object, and the type of that expression is T * (pointer to T ).对于任何类型为T对象E表达式&E计算结果为该对象的地址,并且该表达式的类型为T * (指向T指针)。 If we repace T with a pointer type P * , then the type of &E is P ** .如果我们用指针类型P *替换T ,则&E的类型是P ** IOW, the type of an object that holds the address of another object must have one more level of indirection than the pointed-to object. IOW,保存另一个对象地址的对象的类型必须比指向的对象多一级间接。


  1. Pointer arithmetic works in terms of objects, not bytes.指针算法在对象方面起作用,而不是字节。 If p has type int * and points to an int object, then p+1 points to the next int object immediately following, whether that object is 2, 4, or more bytes away.如果p类型为int *并指向一个int对象,则p+1指向紧随其后的下一个int对象,无论该对象是 2、4 还是更多字节。
  2. ”But everyone says arrays are not pointers, how is a an address?” “但大家都说数组不是指针,是如何a地址?” Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type “N-element array of T ” will be converted (“decay”) to an expression of type “pointer to T ” and the value of the expression will be the address of the first element.除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则类型为“ T N 元素数组”的表达式将被转换(“衰减”)为“指向T指针”类型的表达式,表达式的值将是第一个元素的地址。

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

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