Understanding Pointers

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • touches
    New Member
    • Sep 2010
    • 5

    Understanding Pointers

    hello.. I am learning C using the book Let US C.. I have a doubt regarding pointers... I want to pass a 2d array to a functiona nd display the elements using pointers.. the function prototype is

    Code:
    void show(int(*q)[4],int,int);
    i want to pass the 2d array
    Code:
    int a[3][4]={{1,2,3,4},
    		{5,6,7,8},
    		{9,10,11,12}
    		};
      show(a,3,4);
    the function definition is
    Code:
    void show(int (*q)[4],int r,int c){
    	int i,j;
    	int *p;
    	for(i=0;i<r;i++){
    		printf("\n");
    
    		p=(int *)&q[i];
    		for(j=0;j<c;j++)
    			printf("%3d",*(p+j));
    	}
    }
    here though the output is correct i am unable to understand the expression p=(int*)&q[i].. Can anybody please explain it as i am a beginner.. thank you
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Read this and post again if you still have questions:

    Comment

    • Oralloy
      Recognized Expert Contributor
      • Jun 2010
      • 988

      #3
      @touches

      If you think about it, the expression @q[i] is the address of the "Ith" element of array q.

      Which is to say that it is a pointer to an array of four integers.

      By casting to an integer pointer with (int *)&q[i], you cheat and say that it's really not a pointer to an array of four integers, but actually a pointer to an integer. That can then be dereferenced to give you an integer.

      All that said, now that you've seen fancy type casting in C, just don't do it. Most of the time when you do a type cast to other than a (void *), you're doing something wrong. Either there's a design problem somewhere, or there's an actual bug that's in the code, or someone is being inappropriately lazy.

      Comment

      • donbock
        Recognized Expert Top Contributor
        • Mar 2008
        • 2427

        #4
        Code:
        void show(int (*q)[4],int r,int c);
        I don't recognize the syntax used for parameter q. It is not quite a function pointer; it is not quite a pointer to int.

        Could it be a pointer to the first element of a 4-element int array? I'm positive C90 does not let you do that. (I don't know about C99.)

        My best guess is that it is a pointer to a pointer to an int; and that you would get the same thing if you deleted the "4".

        Comment

        • Oralloy
          Recognized Expert Contributor
          • Jun 2010
          • 988

          #5
          @donbock,

          Let's try to explain by way of analogy/construction... .

          Code:
          int q[4];
          is easy, right - it's an array of four integers.

          Code:
          int *q;
          is also easy - it's a pointer to an integer.

          Code:
          int (*q);
          is a little more complex - q is a pointer ... to an integer - all the parentheses do is to bind the asterisk to q explicitly, rather than counting on parsing precedence.

          Code:
          int *q[4];
          is common, too - q is an array of four pointers to integers.

          Code:
          int *(q[4]);
          same thing - q is an array of four .... pointers .... to integers.

          so, let us move the parentheses ...

          Code:
          int (*q)[4];
          in this case, we have - q is a pointer ..... to an array of four .... integers

          Does that help?

          If not, try looking at it with typedefs:

          Code:
          typedef int integer;
          
          typedef integer arrayOf4Integers[4];
          
          typedef arrayOf4Integers *pointerToArrayOf4Integers;
          
          pointerToArrayOf4Integers q;
          Cheers!
          Last edited by Oralloy; Sep 9 '10, 11:20 PM. Reason: Inserted missing code tag.

          Comment

          • touches
            New Member
            • Sep 2010
            • 5

            #6
            Hello thanks guys for the reply and explanation..
            I have got another doubt if q is an pointer to an array of 4 integers then would it hold the addresses of the first four integers in the array??

            And secondly why do we need to cast it and store it in another pointer?? (i.e) in my example *p?? Cant we just dereference from q and print out the values???

            I know my doubts may sound very silly but i am just learning C and i am very much foxed and scared by the concept of pointers

            Comment

            • donbock
              Recognized Expert Top Contributor
              • Mar 2008
              • 2427

              #7
              @Oralloy:
              No argument from me. That is a good summary of variable definitions/declarations, but the situation is a little different for function parameters.

              Code:
              void foo(int *p);
              The parameter is a pointer to int.

              Code:
              void foo(int p[]);
              The programmer wants to pass an array of int, but the compiler converts that into a pointer to int.

              Code:
              void foo(int p[4]);
              The programmer wants to pass an array of int, but once again the compiler converts that into a pointer to int and blithely ignores the "4". Thus the compiler does not care if the caller passes arrays of differing dimension; and the function can't detect the dimension of the array that was passed. That's why the prototype for main has both argc and argv[].

              Code:
              void foo(int *p[4]);
              Here you get one level of indirection due to the "*" and another level of indirection due to the "[4]". Hence, the argument is a pointer to a pointer to an int. Again, the dimension of "4" is ignored. Thus, it is the same as:
              Code:
              void foo(int **p);
              -or-
              void foo(int p[][]);

              This is what people mean when they say arrays decay into pointers. The C FAQ discusses this here, here, and here.

              I haven't used the square-bracket notation for function parameters in over 10 years, [that makes me sound old!] so I'm pretty rusty on the details. I'm confident that's how C90 works. It would be great if one of the C99 enhancements was to provide a way to preserve array dimension through a function call; but I don't know if that is the case.
              Last edited by donbock; Sep 10 '10, 12:14 PM. Reason: Added FAQ citations

              Comment

              • donbock
                Recognized Expert Top Contributor
                • Mar 2008
                • 2427

                #8
                @touches:

                I'll reiterate the advice weaknessforcats gave in your first reply: you should look at the article Arrays Revealed. Pay special attention to the difference between static and dynamic two-dimensional arrays.

                Comment

                • donbock
                  Recognized Expert Top Contributor
                  • Mar 2008
                  • 2427

                  #9
                  I recant my earlier replies!
                  Too much of what I wrote is just plain wrong; most of what remains isn't pertinent to the question.

                  I routinely refer OPs to the excellent Arrays Revealed article. When I finally decided to follow my own advice and reread it I realized that I didn't understand this stuff as much as I thought I did.

                  Code:
                  int a[3][4]={{1,2,3,4}, 
                          {5,6,7,8}, 
                          {9,10,11,12} 
                          };
                  This declares an array of 3 elements, where each element is an array of 4 ints.

                  Code:
                  void show(int (*q)[4],int r,int c);
                  This declares q as a pointer to an array of 4 ints. The article recommends the parentheses around *q -- I suppose they're needed to make this a pointer-to-array rather than an array-of-pointers. I wonder if you might not get the same effect with this:
                  Code:
                  void show(int q[][4],int r,int c);

                  Code:
                          p=(int *)&q[i];
                  Here, q[i] is an array of 4 ints, &q[i] is a pointer to an array of 4 ints, but the program wants to point at individual ints so it casts that pointer with (int *). I wonder if you might not get the same effect with this:
                  Code:
                          p=&q[i][0];

                  Comment

                  Working...