435,041 Members | 1,793 Online
Need help? Post your question and get tips & solutions from a community of 435,041 IT Pros & Developers. It's quick & easy.

# Understanding Pointers

 P: 5 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 Expand|Select|Wrap|Line Numbers void show(int(*q)[4],int,int); i want to pass the 2d array Expand|Select|Wrap|Line Numbers int a[3][4]={{1,2,3,4},         {5,6,7,8},         {9,10,11,12}         };   show(a,3,4);     the function definition is Expand|Select|Wrap|Line Numbers void show(int (*q)[4],int r,int c){     int i,j;     int *p;     for(i=0;i
8 Replies

 Expert Mod 5K+ P: 9,197 Read this and post again if you still have questions: http://bytes.com/topic/c/insights/77...rrays-revealed Sep 9 '10 #2

 Expert 100+ P: 983 @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. Sep 9 '10 #3

 Expert 100+ P: 2,400 Expand|Select|Wrap|Line Numbers 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". Sep 9 '10 #4

 Expert 100+ P: 983 @donbock, Let's try to explain by way of analogy/construction.... Expand|Select|Wrap|Line Numbers int q[4]; is easy, right - it's an array of four integers. Expand|Select|Wrap|Line Numbers int *q; is also easy - it's a pointer to an integer. Expand|Select|Wrap|Line Numbers 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. Expand|Select|Wrap|Line Numbers int *q[4]; is common, too - q is an array of four pointers to integers. Expand|Select|Wrap|Line Numbers int *(q[4]); same thing - q is an array of four .... pointers .... to integers. so, let us move the parentheses ... Expand|Select|Wrap|Line Numbers 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: Expand|Select|Wrap|Line Numbers typedef int integer;   typedef integer arrayOf4Integers[4];   typedef arrayOf4Integers *pointerToArrayOf4Integers;   pointerToArrayOf4Integers q; Cheers! Sep 9 '10 #5

 P: 5 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 Sep 10 '10 #6

 Expert 100+ P: 2,400 @Oralloy: No argument from me. That is a good summary of variable definitions/declarations, but the situation is a little different for function parameters. Expand|Select|Wrap|Line Numbers void foo(int *p); The parameter is a pointer to int. Expand|Select|Wrap|Line Numbers void foo(int p[]); The programmer wants to pass an array of int, but the compiler converts that into a pointer to int. Expand|Select|Wrap|Line Numbers 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[]. Expand|Select|Wrap|Line Numbers 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: Expand|Select|Wrap|Line Numbers 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. Sep 10 '10 #7

 Expert 100+ P: 2,400 @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. Sep 10 '10 #8

 Expert 100+ P: 2,400 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. Expand|Select|Wrap|Line Numbers 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. Expand|Select|Wrap|Line Numbers 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: Expand|Select|Wrap|Line Numbers void show(int q[][4],int r,int c); Expand|Select|Wrap|Line Numbers         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: Expand|Select|Wrap|Line Numbers         p=&q[i][0]; Sep 10 '10 #9