Precedence, Parentheses, Pointers with iterative array functions
I'm teaching myself a little C and have run across an exercise that I want to make sure I understand completely. The exercise is asking me to pass a pointer to a multidimensional array of integers to a function and iterate through the array. So I started with a print function before moving on to one taking input to populate the array. I tried all sorts of things but after finding a bit of code on type casting and iterating pointers I have the below program that seems to work but I'm not quite understanding what is going on. In my comments I have questions labeled 1-3, referring to the questions below the code. I was hoping someone more intelligent than myself could enlighten me.
//passing multi-Array to a simple print function
#include <stdio.h>
//simple print function prototype
void printMyArr(int (*pt)[4]);
int main()
{
//declare and initialize a multi-array. I picked 4x4 and some arbitrary
//numbers for simplicity's sake
int myArr[4][4] = { {12, 16, 19, 20},
{5, 99, 102, 200},
{12, 20, 25, 600},
{65, 66, 999, 1000} };
//declare a pointer to an array of integers and an int for a loop counter
int (*pt)[4], counter;
//initialize the pointer
pt = myArr;
//for loop calling printMyArr function to iterate through arrays -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printMyArr(pt++); //<-------------Question 1
return 0;
}
//function called to print array elements to the console
void printMyArr(int(*pt)[4])
{
//declare a counter....and apparently another pointer
int counter, *p;
//initialize new pointer to old pointer and type cast array as int
p = (int *)pt; //<-------------Question 2
//for loop to iterate through elements of array -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++); //<------Question 3
}
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0]
, myArr[1][0]
, myArr[2][0]
, myArr[3][0]
)? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
So
1: pass pointer as assigned -> myArr[0][0]
then print the values in myArr[0][0]
, myArr[0][1]
, myArr[0][2]
, and myArr[0][3]
, then increment pointer myArr[1][0]
2: pass pointer as assigned ->myArr[1][0]
then print the values in myArr[1][0]
, myArr[1][1]
, myArr[1][2]
and myArr[1][3]
increment pointer to myArr[2][0]
3: pass pointer as assigned ->myArr[2][0]
then print the values in myArr[2][0]
, myArr[2][1]
, myArr[2][2]
and myArr[2][3]
increment pointer to myArr[3][0]
4: pass pointer as assigned ->myArr[3][0]
then print the values in myArr[3][0]
, myArr[3][1]
, myArr[3][2]
and myArr[3][3]
increment pointer to myArr[4][0]
and if this is the case what is the pointer pointing to since there shouldn't be a myArr[4][0]
?
c
add a comment |
I'm teaching myself a little C and have run across an exercise that I want to make sure I understand completely. The exercise is asking me to pass a pointer to a multidimensional array of integers to a function and iterate through the array. So I started with a print function before moving on to one taking input to populate the array. I tried all sorts of things but after finding a bit of code on type casting and iterating pointers I have the below program that seems to work but I'm not quite understanding what is going on. In my comments I have questions labeled 1-3, referring to the questions below the code. I was hoping someone more intelligent than myself could enlighten me.
//passing multi-Array to a simple print function
#include <stdio.h>
//simple print function prototype
void printMyArr(int (*pt)[4]);
int main()
{
//declare and initialize a multi-array. I picked 4x4 and some arbitrary
//numbers for simplicity's sake
int myArr[4][4] = { {12, 16, 19, 20},
{5, 99, 102, 200},
{12, 20, 25, 600},
{65, 66, 999, 1000} };
//declare a pointer to an array of integers and an int for a loop counter
int (*pt)[4], counter;
//initialize the pointer
pt = myArr;
//for loop calling printMyArr function to iterate through arrays -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printMyArr(pt++); //<-------------Question 1
return 0;
}
//function called to print array elements to the console
void printMyArr(int(*pt)[4])
{
//declare a counter....and apparently another pointer
int counter, *p;
//initialize new pointer to old pointer and type cast array as int
p = (int *)pt; //<-------------Question 2
//for loop to iterate through elements of array -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++); //<------Question 3
}
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0]
, myArr[1][0]
, myArr[2][0]
, myArr[3][0]
)? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
So
1: pass pointer as assigned -> myArr[0][0]
then print the values in myArr[0][0]
, myArr[0][1]
, myArr[0][2]
, and myArr[0][3]
, then increment pointer myArr[1][0]
2: pass pointer as assigned ->myArr[1][0]
then print the values in myArr[1][0]
, myArr[1][1]
, myArr[1][2]
and myArr[1][3]
increment pointer to myArr[2][0]
3: pass pointer as assigned ->myArr[2][0]
then print the values in myArr[2][0]
, myArr[2][1]
, myArr[2][2]
and myArr[2][3]
increment pointer to myArr[3][0]
4: pass pointer as assigned ->myArr[3][0]
then print the values in myArr[3][0]
, myArr[3][1]
, myArr[3][2]
and myArr[3][3]
increment pointer to myArr[4][0]
and if this is the case what is the pointer pointing to since there shouldn't be a myArr[4][0]
?
c
2
It's awesome to see such a thoroughly considered and well written question. Nicely done.
– Daniel Farrell
Jan 2 at 19:45
1
Understand, on accessint myArr[3][5]
the first level of indirection (e.g. the first[..]
) is converted to a pointer to the first element in the array. With a 2D array the first element is a pointer to the first row (array). So it is converted(*myArr)[5]
which is a pointer-to-array ofint [5]
. You can't just use*myArr[5]
as[ ]
binds tighter than'*'
from a precedence standpoint which would result in an array-of-pointers toint
(5 pointers). With(*myArr)[5]
the pointer advances by 20-bytes (5-int) per-increment, with*myArr[5]
the pointer advances bysizeof a_pointer
.
– David C. Rankin
Jan 2 at 19:51
2
The reference in the standard is C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (note the exceptions when it is NOT converted to a pointer)
– David C. Rankin
Jan 2 at 19:53
add a comment |
I'm teaching myself a little C and have run across an exercise that I want to make sure I understand completely. The exercise is asking me to pass a pointer to a multidimensional array of integers to a function and iterate through the array. So I started with a print function before moving on to one taking input to populate the array. I tried all sorts of things but after finding a bit of code on type casting and iterating pointers I have the below program that seems to work but I'm not quite understanding what is going on. In my comments I have questions labeled 1-3, referring to the questions below the code. I was hoping someone more intelligent than myself could enlighten me.
//passing multi-Array to a simple print function
#include <stdio.h>
//simple print function prototype
void printMyArr(int (*pt)[4]);
int main()
{
//declare and initialize a multi-array. I picked 4x4 and some arbitrary
//numbers for simplicity's sake
int myArr[4][4] = { {12, 16, 19, 20},
{5, 99, 102, 200},
{12, 20, 25, 600},
{65, 66, 999, 1000} };
//declare a pointer to an array of integers and an int for a loop counter
int (*pt)[4], counter;
//initialize the pointer
pt = myArr;
//for loop calling printMyArr function to iterate through arrays -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printMyArr(pt++); //<-------------Question 1
return 0;
}
//function called to print array elements to the console
void printMyArr(int(*pt)[4])
{
//declare a counter....and apparently another pointer
int counter, *p;
//initialize new pointer to old pointer and type cast array as int
p = (int *)pt; //<-------------Question 2
//for loop to iterate through elements of array -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++); //<------Question 3
}
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0]
, myArr[1][0]
, myArr[2][0]
, myArr[3][0]
)? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
So
1: pass pointer as assigned -> myArr[0][0]
then print the values in myArr[0][0]
, myArr[0][1]
, myArr[0][2]
, and myArr[0][3]
, then increment pointer myArr[1][0]
2: pass pointer as assigned ->myArr[1][0]
then print the values in myArr[1][0]
, myArr[1][1]
, myArr[1][2]
and myArr[1][3]
increment pointer to myArr[2][0]
3: pass pointer as assigned ->myArr[2][0]
then print the values in myArr[2][0]
, myArr[2][1]
, myArr[2][2]
and myArr[2][3]
increment pointer to myArr[3][0]
4: pass pointer as assigned ->myArr[3][0]
then print the values in myArr[3][0]
, myArr[3][1]
, myArr[3][2]
and myArr[3][3]
increment pointer to myArr[4][0]
and if this is the case what is the pointer pointing to since there shouldn't be a myArr[4][0]
?
c
I'm teaching myself a little C and have run across an exercise that I want to make sure I understand completely. The exercise is asking me to pass a pointer to a multidimensional array of integers to a function and iterate through the array. So I started with a print function before moving on to one taking input to populate the array. I tried all sorts of things but after finding a bit of code on type casting and iterating pointers I have the below program that seems to work but I'm not quite understanding what is going on. In my comments I have questions labeled 1-3, referring to the questions below the code. I was hoping someone more intelligent than myself could enlighten me.
//passing multi-Array to a simple print function
#include <stdio.h>
//simple print function prototype
void printMyArr(int (*pt)[4]);
int main()
{
//declare and initialize a multi-array. I picked 4x4 and some arbitrary
//numbers for simplicity's sake
int myArr[4][4] = { {12, 16, 19, 20},
{5, 99, 102, 200},
{12, 20, 25, 600},
{65, 66, 999, 1000} };
//declare a pointer to an array of integers and an int for a loop counter
int (*pt)[4], counter;
//initialize the pointer
pt = myArr;
//for loop calling printMyArr function to iterate through arrays -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printMyArr(pt++); //<-------------Question 1
return 0;
}
//function called to print array elements to the console
void printMyArr(int(*pt)[4])
{
//declare a counter....and apparently another pointer
int counter, *p;
//initialize new pointer to old pointer and type cast array as int
p = (int *)pt; //<-------------Question 2
//for loop to iterate through elements of array -- or this is what I understand it to mean
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++); //<------Question 3
}
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0]
, myArr[1][0]
, myArr[2][0]
, myArr[3][0]
)? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
So
1: pass pointer as assigned -> myArr[0][0]
then print the values in myArr[0][0]
, myArr[0][1]
, myArr[0][2]
, and myArr[0][3]
, then increment pointer myArr[1][0]
2: pass pointer as assigned ->myArr[1][0]
then print the values in myArr[1][0]
, myArr[1][1]
, myArr[1][2]
and myArr[1][3]
increment pointer to myArr[2][0]
3: pass pointer as assigned ->myArr[2][0]
then print the values in myArr[2][0]
, myArr[2][1]
, myArr[2][2]
and myArr[2][3]
increment pointer to myArr[3][0]
4: pass pointer as assigned ->myArr[3][0]
then print the values in myArr[3][0]
, myArr[3][1]
, myArr[3][2]
and myArr[3][3]
increment pointer to myArr[4][0]
and if this is the case what is the pointer pointing to since there shouldn't be a myArr[4][0]
?
c
c
edited Jan 2 at 22:41
Dan
asked Jan 2 at 19:42
DanDan
384213
384213
2
It's awesome to see such a thoroughly considered and well written question. Nicely done.
– Daniel Farrell
Jan 2 at 19:45
1
Understand, on accessint myArr[3][5]
the first level of indirection (e.g. the first[..]
) is converted to a pointer to the first element in the array. With a 2D array the first element is a pointer to the first row (array). So it is converted(*myArr)[5]
which is a pointer-to-array ofint [5]
. You can't just use*myArr[5]
as[ ]
binds tighter than'*'
from a precedence standpoint which would result in an array-of-pointers toint
(5 pointers). With(*myArr)[5]
the pointer advances by 20-bytes (5-int) per-increment, with*myArr[5]
the pointer advances bysizeof a_pointer
.
– David C. Rankin
Jan 2 at 19:51
2
The reference in the standard is C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (note the exceptions when it is NOT converted to a pointer)
– David C. Rankin
Jan 2 at 19:53
add a comment |
2
It's awesome to see such a thoroughly considered and well written question. Nicely done.
– Daniel Farrell
Jan 2 at 19:45
1
Understand, on accessint myArr[3][5]
the first level of indirection (e.g. the first[..]
) is converted to a pointer to the first element in the array. With a 2D array the first element is a pointer to the first row (array). So it is converted(*myArr)[5]
which is a pointer-to-array ofint [5]
. You can't just use*myArr[5]
as[ ]
binds tighter than'*'
from a precedence standpoint which would result in an array-of-pointers toint
(5 pointers). With(*myArr)[5]
the pointer advances by 20-bytes (5-int) per-increment, with*myArr[5]
the pointer advances bysizeof a_pointer
.
– David C. Rankin
Jan 2 at 19:51
2
The reference in the standard is C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (note the exceptions when it is NOT converted to a pointer)
– David C. Rankin
Jan 2 at 19:53
2
2
It's awesome to see such a thoroughly considered and well written question. Nicely done.
– Daniel Farrell
Jan 2 at 19:45
It's awesome to see such a thoroughly considered and well written question. Nicely done.
– Daniel Farrell
Jan 2 at 19:45
1
1
Understand, on access
int myArr[3][5]
the first level of indirection (e.g. the first [..]
) is converted to a pointer to the first element in the array. With a 2D array the first element is a pointer to the first row (array). So it is converted (*myArr)[5]
which is a pointer-to-array of int [5]
. You can't just use *myArr[5]
as [ ]
binds tighter than '*'
from a precedence standpoint which would result in an array-of-pointers to int
(5 pointers). With (*myArr)[5]
the pointer advances by 20-bytes (5-int) per-increment, with *myArr[5]
the pointer advances by sizeof a_pointer
.– David C. Rankin
Jan 2 at 19:51
Understand, on access
int myArr[3][5]
the first level of indirection (e.g. the first [..]
) is converted to a pointer to the first element in the array. With a 2D array the first element is a pointer to the first row (array). So it is converted (*myArr)[5]
which is a pointer-to-array of int [5]
. You can't just use *myArr[5]
as [ ]
binds tighter than '*'
from a precedence standpoint which would result in an array-of-pointers to int
(5 pointers). With (*myArr)[5]
the pointer advances by 20-bytes (5-int) per-increment, with *myArr[5]
the pointer advances by sizeof a_pointer
.– David C. Rankin
Jan 2 at 19:51
2
2
The reference in the standard is C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (note the exceptions when it is NOT converted to a pointer)
– David C. Rankin
Jan 2 at 19:53
The reference in the standard is C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (note the exceptions when it is NOT converted to a pointer)
– David C. Rankin
Jan 2 at 19:53
add a comment |
3 Answers
3
active
oldest
votes
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])?
more or less. pt
starts at the address of myArr
. You know there's 4 things in the array so you loop 4 times, incrementing pt
after accessing it (read below) every time to pass to printMyArr
each of the 4 elements of the "top level", "outer" array. Then printMyArr
iterates over the 4 elements of the inner array to show each number.
Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done increment the pointer."?
Functionally, yes. Technically the order of operations looks like this:
1) get the value of pt
2) increment pt
3) call function, passing the previous value of pt
from step 1
pt
is incremented as part of the pt++
call, but pt++
evaluates to the old value. As an argument to a funciton, pt++
must be evaluated before the function it's passed to runs. But the timing looks the same as it evaluating directly after the function runs for your case.
Let's take questions 2 and 3 together because they're both part of the answer.
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
p = (int *)pt;
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++);
p
stores an address of an integer. You set it to the address of the first element of the inner array (which is the address of the inner array itself, so to speak). Then, knowing you have 4 elements in the array, you'r able to loop 4 times, doing a similar pointer post-increment operation on p
that you did with pt
on the outer array.
The first iteration, p
is the same as pt
, the address of the first of 4 integer values in memory. *p
, dereferencing the pointer, gets the first integer. *p++
, due to order of operations ( ++ being of the highest precedence, and dereferencing * being lower), returns the integer at p
, leaving p
pointing to the next integer address for the next loop.
In general, casting values in C should be avoidid whenever possible. You merely have to do a dereference here to point p
to the set of integers. pt
holds the address of one of 4 addresses ( outer array ) of contiguous sets of 4 integers (inner array) in memory. The value at *pt
is the address of the "current" set of 4 contiguous integers in memory. So you can simply say,
int* p=*pt;
Which doesn't arbitrarily cast a type and is very straightforward and clear. (Thanks @WhozCraig)
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existentmyArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can testcounter
and evaluate it to <4
– Dan
Jan 2 at 20:13
4
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to useint *p = *pt;
– WhozCraig
Jan 2 at 20:14
1
That's a great question. Actuallypt
andp
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because thefor
loop's condition is violated on the 5th pass, when an out-of-boundsp
orpt
would be dereferenced . So though the last value ofpt
andp
is an invalid one, that value is never actually accessed.
– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
2
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have someint *p
, then*p
gets you theint
being pointed-to, and++p
(or p++ post-facto) advances the pointer to the nextint
. That said, your function argument is a pointer to an array[4]
ofint
. That's important, because that mean++p
will advance to the nextint[4]
(not what you want to do). That's probably where the wheels came off.
– WhozCraig
Jan 2 at 20:34
|
show 5 more comments
A multy D array is kept in memory as a continuous array so if you have an array [2][2] it will allocate 4 continuous sizeof(int). The reason you need to define array[COL] is to let the compiler know how the pointer arithmetic should be done.
so- for Q1- you are right, each time you increment you do so for(sizeof(int)*COL). so each time you move by a row.
Q2- now for each row you want to print one int value at a time, so when you have int* p- this means each increment is done by sizeof(int).
Q3- the increment is for the pointer- not the value- its easy to see for yourself if you do another print in your main.
Hope this help, good luck!
1
I appreciate the help!!!
– Dan
Jan 2 at 20:44
add a comment |
The in-memory view of 2D
myArr
array would be something like this:
myArr
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
myArr[1] | 5 | 99 |102 |200 |
---------------------
myArr[2] | 12 | 20 | 25 |600 |
---------------------
myArr[3] | 65 | 66 |999 |1000|
---------------------
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Answer of question 1:
int (*pt)[4]
pt
is pointer to an array of 4
integer. This statement
pt = myArr;
makes the pt
pointing to first 1D
array of myArr
2D
array. It is similar to:
pt = &myArr[0];
The impact of both the statement will be like this:
pt--------|
|/
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
When you increment a pointer, it gets incremented in steps of the object size that the pointer can point to. Here
printMyArr(pt++);
first the pt
pointer value passed to printMyArr()
and then pt
will be incremented and since its type is int (*)[4]
that means it can point to an object which is an array of 4
integers, so after increment the pt
will point to the address (which is address pointing to
+ size of array of 4 int
) i.e. to myArr[1]
address.
Note that this:
for(counter=0; counter<4; counter++)
printMyArr(pt++);
is same as this:
for(counter=0; counter<4; counter++)
printMyArr(&myArr[counter]);
^^^^^^^^^^^^^^^
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Answer of question 2:
Here
p = (int *)pt; // pt is pointer to an array of `4` integer
if you remove the (int *)
cast, you will find that the compiler is giving a warning message on this statement. The reason is p
and pt
are not the compatible pointer types. The type of p
is int *
whereas the type of pt
is int (*)[4]
. This incompatible pointer assignment is working because the address of an array and address of first element of an array is numerically same though their type is different. Instead, you should do
p = &(*pt)[0];
From C Standards#6.5.2.1
The definition of the subscript operator is that E1[E2] is identical to (*((E1)+(E2)))
by this rule
&(*pt)[0] --> &(*((*pt)+(0))) --> ((*p)+(0)) --> *p
The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another.
Hence, this statement
p = &(*pt)[0];
is same as this statement
p = *pt;
Question 3: Am I correct thinking that I am incrementing each element here?
Answer of question 3:
Yes.p
is a pointer pointing to first element of array of 4
integer and its type is int *
i.e. it can point to an object which is an int
. When you are doing *p++
, this will first dereference p
and get the value at the address it is pointing to then the p
will be incremented and pointing to next element of array.
add a comment |
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54012242%2fprecedence-parentheses-pointers-with-iterative-array-functions%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])?
more or less. pt
starts at the address of myArr
. You know there's 4 things in the array so you loop 4 times, incrementing pt
after accessing it (read below) every time to pass to printMyArr
each of the 4 elements of the "top level", "outer" array. Then printMyArr
iterates over the 4 elements of the inner array to show each number.
Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done increment the pointer."?
Functionally, yes. Technically the order of operations looks like this:
1) get the value of pt
2) increment pt
3) call function, passing the previous value of pt
from step 1
pt
is incremented as part of the pt++
call, but pt++
evaluates to the old value. As an argument to a funciton, pt++
must be evaluated before the function it's passed to runs. But the timing looks the same as it evaluating directly after the function runs for your case.
Let's take questions 2 and 3 together because they're both part of the answer.
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
p = (int *)pt;
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++);
p
stores an address of an integer. You set it to the address of the first element of the inner array (which is the address of the inner array itself, so to speak). Then, knowing you have 4 elements in the array, you'r able to loop 4 times, doing a similar pointer post-increment operation on p
that you did with pt
on the outer array.
The first iteration, p
is the same as pt
, the address of the first of 4 integer values in memory. *p
, dereferencing the pointer, gets the first integer. *p++
, due to order of operations ( ++ being of the highest precedence, and dereferencing * being lower), returns the integer at p
, leaving p
pointing to the next integer address for the next loop.
In general, casting values in C should be avoidid whenever possible. You merely have to do a dereference here to point p
to the set of integers. pt
holds the address of one of 4 addresses ( outer array ) of contiguous sets of 4 integers (inner array) in memory. The value at *pt
is the address of the "current" set of 4 contiguous integers in memory. So you can simply say,
int* p=*pt;
Which doesn't arbitrarily cast a type and is very straightforward and clear. (Thanks @WhozCraig)
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existentmyArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can testcounter
and evaluate it to <4
– Dan
Jan 2 at 20:13
4
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to useint *p = *pt;
– WhozCraig
Jan 2 at 20:14
1
That's a great question. Actuallypt
andp
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because thefor
loop's condition is violated on the 5th pass, when an out-of-boundsp
orpt
would be dereferenced . So though the last value ofpt
andp
is an invalid one, that value is never actually accessed.
– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
2
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have someint *p
, then*p
gets you theint
being pointed-to, and++p
(or p++ post-facto) advances the pointer to the nextint
. That said, your function argument is a pointer to an array[4]
ofint
. That's important, because that mean++p
will advance to the nextint[4]
(not what you want to do). That's probably where the wheels came off.
– WhozCraig
Jan 2 at 20:34
|
show 5 more comments
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])?
more or less. pt
starts at the address of myArr
. You know there's 4 things in the array so you loop 4 times, incrementing pt
after accessing it (read below) every time to pass to printMyArr
each of the 4 elements of the "top level", "outer" array. Then printMyArr
iterates over the 4 elements of the inner array to show each number.
Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done increment the pointer."?
Functionally, yes. Technically the order of operations looks like this:
1) get the value of pt
2) increment pt
3) call function, passing the previous value of pt
from step 1
pt
is incremented as part of the pt++
call, but pt++
evaluates to the old value. As an argument to a funciton, pt++
must be evaluated before the function it's passed to runs. But the timing looks the same as it evaluating directly after the function runs for your case.
Let's take questions 2 and 3 together because they're both part of the answer.
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
p = (int *)pt;
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++);
p
stores an address of an integer. You set it to the address of the first element of the inner array (which is the address of the inner array itself, so to speak). Then, knowing you have 4 elements in the array, you'r able to loop 4 times, doing a similar pointer post-increment operation on p
that you did with pt
on the outer array.
The first iteration, p
is the same as pt
, the address of the first of 4 integer values in memory. *p
, dereferencing the pointer, gets the first integer. *p++
, due to order of operations ( ++ being of the highest precedence, and dereferencing * being lower), returns the integer at p
, leaving p
pointing to the next integer address for the next loop.
In general, casting values in C should be avoidid whenever possible. You merely have to do a dereference here to point p
to the set of integers. pt
holds the address of one of 4 addresses ( outer array ) of contiguous sets of 4 integers (inner array) in memory. The value at *pt
is the address of the "current" set of 4 contiguous integers in memory. So you can simply say,
int* p=*pt;
Which doesn't arbitrarily cast a type and is very straightforward and clear. (Thanks @WhozCraig)
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existentmyArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can testcounter
and evaluate it to <4
– Dan
Jan 2 at 20:13
4
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to useint *p = *pt;
– WhozCraig
Jan 2 at 20:14
1
That's a great question. Actuallypt
andp
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because thefor
loop's condition is violated on the 5th pass, when an out-of-boundsp
orpt
would be dereferenced . So though the last value ofpt
andp
is an invalid one, that value is never actually accessed.
– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
2
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have someint *p
, then*p
gets you theint
being pointed-to, and++p
(or p++ post-facto) advances the pointer to the nextint
. That said, your function argument is a pointer to an array[4]
ofint
. That's important, because that mean++p
will advance to the nextint[4]
(not what you want to do). That's probably where the wheels came off.
– WhozCraig
Jan 2 at 20:34
|
show 5 more comments
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])?
more or less. pt
starts at the address of myArr
. You know there's 4 things in the array so you loop 4 times, incrementing pt
after accessing it (read below) every time to pass to printMyArr
each of the 4 elements of the "top level", "outer" array. Then printMyArr
iterates over the 4 elements of the inner array to show each number.
Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done increment the pointer."?
Functionally, yes. Technically the order of operations looks like this:
1) get the value of pt
2) increment pt
3) call function, passing the previous value of pt
from step 1
pt
is incremented as part of the pt++
call, but pt++
evaluates to the old value. As an argument to a funciton, pt++
must be evaluated before the function it's passed to runs. But the timing looks the same as it evaluating directly after the function runs for your case.
Let's take questions 2 and 3 together because they're both part of the answer.
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
p = (int *)pt;
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++);
p
stores an address of an integer. You set it to the address of the first element of the inner array (which is the address of the inner array itself, so to speak). Then, knowing you have 4 elements in the array, you'r able to loop 4 times, doing a similar pointer post-increment operation on p
that you did with pt
on the outer array.
The first iteration, p
is the same as pt
, the address of the first of 4 integer values in memory. *p
, dereferencing the pointer, gets the first integer. *p++
, due to order of operations ( ++ being of the highest precedence, and dereferencing * being lower), returns the integer at p
, leaving p
pointing to the next integer address for the next loop.
In general, casting values in C should be avoidid whenever possible. You merely have to do a dereference here to point p
to the set of integers. pt
holds the address of one of 4 addresses ( outer array ) of contiguous sets of 4 integers (inner array) in memory. The value at *pt
is the address of the "current" set of 4 contiguous integers in memory. So you can simply say,
int* p=*pt;
Which doesn't arbitrarily cast a type and is very straightforward and clear. (Thanks @WhozCraig)
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])?
more or less. pt
starts at the address of myArr
. You know there's 4 things in the array so you loop 4 times, incrementing pt
after accessing it (read below) every time to pass to printMyArr
each of the 4 elements of the "top level", "outer" array. Then printMyArr
iterates over the 4 elements of the inner array to show each number.
Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done increment the pointer."?
Functionally, yes. Technically the order of operations looks like this:
1) get the value of pt
2) increment pt
3) call function, passing the previous value of pt
from step 1
pt
is incremented as part of the pt++
call, but pt++
evaluates to the old value. As an argument to a funciton, pt++
must be evaluated before the function it's passed to runs. But the timing looks the same as it evaluating directly after the function runs for your case.
Let's take questions 2 and 3 together because they're both part of the answer.
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Question 3: Am I correct thinking that I am incrementing each element here?
p = (int *)pt;
for(counter=0; counter<4; counter++)
printf("nnn%d", *p++);
p
stores an address of an integer. You set it to the address of the first element of the inner array (which is the address of the inner array itself, so to speak). Then, knowing you have 4 elements in the array, you'r able to loop 4 times, doing a similar pointer post-increment operation on p
that you did with pt
on the outer array.
The first iteration, p
is the same as pt
, the address of the first of 4 integer values in memory. *p
, dereferencing the pointer, gets the first integer. *p++
, due to order of operations ( ++ being of the highest precedence, and dereferencing * being lower), returns the integer at p
, leaving p
pointing to the next integer address for the next loop.
In general, casting values in C should be avoidid whenever possible. You merely have to do a dereference here to point p
to the set of integers. pt
holds the address of one of 4 addresses ( outer array ) of contiguous sets of 4 integers (inner array) in memory. The value at *pt
is the address of the "current" set of 4 contiguous integers in memory. So you can simply say,
int* p=*pt;
Which doesn't arbitrarily cast a type and is very straightforward and clear. (Thanks @WhozCraig)
edited Jan 2 at 20:29
answered Jan 2 at 20:01
Daniel FarrellDaniel Farrell
6,18711417
6,18711417
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existentmyArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can testcounter
and evaluate it to <4
– Dan
Jan 2 at 20:13
4
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to useint *p = *pt;
– WhozCraig
Jan 2 at 20:14
1
That's a great question. Actuallypt
andp
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because thefor
loop's condition is violated on the 5th pass, when an out-of-boundsp
orpt
would be dereferenced . So though the last value ofpt
andp
is an invalid one, that value is never actually accessed.
– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
2
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have someint *p
, then*p
gets you theint
being pointed-to, and++p
(or p++ post-facto) advances the pointer to the nextint
. That said, your function argument is a pointer to an array[4]
ofint
. That's important, because that mean++p
will advance to the nextint[4]
(not what you want to do). That's probably where the wheels came off.
– WhozCraig
Jan 2 at 20:34
|
show 5 more comments
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existentmyArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can testcounter
and evaluate it to <4
– Dan
Jan 2 at 20:13
4
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to useint *p = *pt;
– WhozCraig
Jan 2 at 20:14
1
That's a great question. Actuallypt
andp
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because thefor
loop's condition is violated on the 5th pass, when an out-of-boundsp
orpt
would be dereferenced . So though the last value ofpt
andp
is an invalid one, that value is never actually accessed.
– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
2
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have someint *p
, then*p
gets you theint
being pointed-to, and++p
(or p++ post-facto) advances the pointer to the nextint
. That said, your function argument is a pointer to an array[4]
ofint
. That's important, because that mean++p
will advance to the nextint[4]
(not what you want to do). That's probably where the wheels came off.
– WhozCraig
Jan 2 at 20:34
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existent
myArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can test counter
and evaluate it to <4– Dan
Jan 2 at 20:13
...and on the last iteration? The compiler knows not to increment the pointer to point at the non-existent
myArr[4][0]
or is that included in the <? Seems like to me given the order of operations the pointer is incremented before the loop can test counter
and evaluate it to <4– Dan
Jan 2 at 20:13
4
4
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to use
int *p = *pt;
– WhozCraig
Jan 2 at 20:14
Question #2: The proper syntax without the hard cast (avoided by seasoned programmers, nearly always a sign of misunderstanding or masking type issues by beginners), is to use
int *p = *pt;
– WhozCraig
Jan 2 at 20:14
1
1
That's a great question. Actually
pt
and p
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because the for
loop's condition is violated on the 5th pass, when an out-of-bounds p
or pt
would be dereferenced . So though the last value of pt
and p
is an invalid one, that value is never actually accessed.– Daniel Farrell
Jan 2 at 20:16
That's a great question. Actually
pt
and p
are post-incremented to the first "non-existent" address on the last iteration of the loop, but they're not dereferenced again because the for
loop's condition is violated on the 5th pass, when an out-of-bounds p
or pt
would be dereferenced . So though the last value of pt
and p
is an invalid one, that value is never actually accessed.– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
That's a great point @WhozCraig I'll add it to the answer.
– Daniel Farrell
Jan 2 at 20:16
2
2
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have some
int *p
, then *p
gets you the int
being pointed-to, and ++p
(or p++ post-facto) advances the pointer to the next int
. That said, your function argument is a pointer to an array [4]
of int
. That's important, because that mean ++p
will advance to the next int[4]
(not what you want to do). That's probably where the wheels came off.– WhozCraig
Jan 2 at 20:34
@Dan First, pointers in C point to stuff (bear with me). You dereference a pointer to get to what it points to. The underlying type of the thing being pointed to dictates many things, among them outcome of pointer arithmetic. If you have some
int *p
, then *p
gets you the int
being pointed-to, and ++p
(or p++ post-facto) advances the pointer to the next int
. That said, your function argument is a pointer to an array [4]
of int
. That's important, because that mean ++p
will advance to the next int[4]
(not what you want to do). That's probably where the wheels came off.– WhozCraig
Jan 2 at 20:34
|
show 5 more comments
A multy D array is kept in memory as a continuous array so if you have an array [2][2] it will allocate 4 continuous sizeof(int). The reason you need to define array[COL] is to let the compiler know how the pointer arithmetic should be done.
so- for Q1- you are right, each time you increment you do so for(sizeof(int)*COL). so each time you move by a row.
Q2- now for each row you want to print one int value at a time, so when you have int* p- this means each increment is done by sizeof(int).
Q3- the increment is for the pointer- not the value- its easy to see for yourself if you do another print in your main.
Hope this help, good luck!
1
I appreciate the help!!!
– Dan
Jan 2 at 20:44
add a comment |
A multy D array is kept in memory as a continuous array so if you have an array [2][2] it will allocate 4 continuous sizeof(int). The reason you need to define array[COL] is to let the compiler know how the pointer arithmetic should be done.
so- for Q1- you are right, each time you increment you do so for(sizeof(int)*COL). so each time you move by a row.
Q2- now for each row you want to print one int value at a time, so when you have int* p- this means each increment is done by sizeof(int).
Q3- the increment is for the pointer- not the value- its easy to see for yourself if you do another print in your main.
Hope this help, good luck!
1
I appreciate the help!!!
– Dan
Jan 2 at 20:44
add a comment |
A multy D array is kept in memory as a continuous array so if you have an array [2][2] it will allocate 4 continuous sizeof(int). The reason you need to define array[COL] is to let the compiler know how the pointer arithmetic should be done.
so- for Q1- you are right, each time you increment you do so for(sizeof(int)*COL). so each time you move by a row.
Q2- now for each row you want to print one int value at a time, so when you have int* p- this means each increment is done by sizeof(int).
Q3- the increment is for the pointer- not the value- its easy to see for yourself if you do another print in your main.
Hope this help, good luck!
A multy D array is kept in memory as a continuous array so if you have an array [2][2] it will allocate 4 continuous sizeof(int). The reason you need to define array[COL] is to let the compiler know how the pointer arithmetic should be done.
so- for Q1- you are right, each time you increment you do so for(sizeof(int)*COL). so each time you move by a row.
Q2- now for each row you want to print one int value at a time, so when you have int* p- this means each increment is done by sizeof(int).
Q3- the increment is for the pointer- not the value- its easy to see for yourself if you do another print in your main.
Hope this help, good luck!
answered Jan 2 at 20:06


H.cohenH.cohen
47019
47019
1
I appreciate the help!!!
– Dan
Jan 2 at 20:44
add a comment |
1
I appreciate the help!!!
– Dan
Jan 2 at 20:44
1
1
I appreciate the help!!!
– Dan
Jan 2 at 20:44
I appreciate the help!!!
– Dan
Jan 2 at 20:44
add a comment |
The in-memory view of 2D
myArr
array would be something like this:
myArr
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
myArr[1] | 5 | 99 |102 |200 |
---------------------
myArr[2] | 12 | 20 | 25 |600 |
---------------------
myArr[3] | 65 | 66 |999 |1000|
---------------------
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Answer of question 1:
int (*pt)[4]
pt
is pointer to an array of 4
integer. This statement
pt = myArr;
makes the pt
pointing to first 1D
array of myArr
2D
array. It is similar to:
pt = &myArr[0];
The impact of both the statement will be like this:
pt--------|
|/
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
When you increment a pointer, it gets incremented in steps of the object size that the pointer can point to. Here
printMyArr(pt++);
first the pt
pointer value passed to printMyArr()
and then pt
will be incremented and since its type is int (*)[4]
that means it can point to an object which is an array of 4
integers, so after increment the pt
will point to the address (which is address pointing to
+ size of array of 4 int
) i.e. to myArr[1]
address.
Note that this:
for(counter=0; counter<4; counter++)
printMyArr(pt++);
is same as this:
for(counter=0; counter<4; counter++)
printMyArr(&myArr[counter]);
^^^^^^^^^^^^^^^
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Answer of question 2:
Here
p = (int *)pt; // pt is pointer to an array of `4` integer
if you remove the (int *)
cast, you will find that the compiler is giving a warning message on this statement. The reason is p
and pt
are not the compatible pointer types. The type of p
is int *
whereas the type of pt
is int (*)[4]
. This incompatible pointer assignment is working because the address of an array and address of first element of an array is numerically same though their type is different. Instead, you should do
p = &(*pt)[0];
From C Standards#6.5.2.1
The definition of the subscript operator is that E1[E2] is identical to (*((E1)+(E2)))
by this rule
&(*pt)[0] --> &(*((*pt)+(0))) --> ((*p)+(0)) --> *p
The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another.
Hence, this statement
p = &(*pt)[0];
is same as this statement
p = *pt;
Question 3: Am I correct thinking that I am incrementing each element here?
Answer of question 3:
Yes.p
is a pointer pointing to first element of array of 4
integer and its type is int *
i.e. it can point to an object which is an int
. When you are doing *p++
, this will first dereference p
and get the value at the address it is pointing to then the p
will be incremented and pointing to next element of array.
add a comment |
The in-memory view of 2D
myArr
array would be something like this:
myArr
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
myArr[1] | 5 | 99 |102 |200 |
---------------------
myArr[2] | 12 | 20 | 25 |600 |
---------------------
myArr[3] | 65 | 66 |999 |1000|
---------------------
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Answer of question 1:
int (*pt)[4]
pt
is pointer to an array of 4
integer. This statement
pt = myArr;
makes the pt
pointing to first 1D
array of myArr
2D
array. It is similar to:
pt = &myArr[0];
The impact of both the statement will be like this:
pt--------|
|/
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
When you increment a pointer, it gets incremented in steps of the object size that the pointer can point to. Here
printMyArr(pt++);
first the pt
pointer value passed to printMyArr()
and then pt
will be incremented and since its type is int (*)[4]
that means it can point to an object which is an array of 4
integers, so after increment the pt
will point to the address (which is address pointing to
+ size of array of 4 int
) i.e. to myArr[1]
address.
Note that this:
for(counter=0; counter<4; counter++)
printMyArr(pt++);
is same as this:
for(counter=0; counter<4; counter++)
printMyArr(&myArr[counter]);
^^^^^^^^^^^^^^^
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Answer of question 2:
Here
p = (int *)pt; // pt is pointer to an array of `4` integer
if you remove the (int *)
cast, you will find that the compiler is giving a warning message on this statement. The reason is p
and pt
are not the compatible pointer types. The type of p
is int *
whereas the type of pt
is int (*)[4]
. This incompatible pointer assignment is working because the address of an array and address of first element of an array is numerically same though their type is different. Instead, you should do
p = &(*pt)[0];
From C Standards#6.5.2.1
The definition of the subscript operator is that E1[E2] is identical to (*((E1)+(E2)))
by this rule
&(*pt)[0] --> &(*((*pt)+(0))) --> ((*p)+(0)) --> *p
The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another.
Hence, this statement
p = &(*pt)[0];
is same as this statement
p = *pt;
Question 3: Am I correct thinking that I am incrementing each element here?
Answer of question 3:
Yes.p
is a pointer pointing to first element of array of 4
integer and its type is int *
i.e. it can point to an object which is an int
. When you are doing *p++
, this will first dereference p
and get the value at the address it is pointing to then the p
will be incremented and pointing to next element of array.
add a comment |
The in-memory view of 2D
myArr
array would be something like this:
myArr
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
myArr[1] | 5 | 99 |102 |200 |
---------------------
myArr[2] | 12 | 20 | 25 |600 |
---------------------
myArr[3] | 65 | 66 |999 |1000|
---------------------
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Answer of question 1:
int (*pt)[4]
pt
is pointer to an array of 4
integer. This statement
pt = myArr;
makes the pt
pointing to first 1D
array of myArr
2D
array. It is similar to:
pt = &myArr[0];
The impact of both the statement will be like this:
pt--------|
|/
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
When you increment a pointer, it gets incremented in steps of the object size that the pointer can point to. Here
printMyArr(pt++);
first the pt
pointer value passed to printMyArr()
and then pt
will be incremented and since its type is int (*)[4]
that means it can point to an object which is an array of 4
integers, so after increment the pt
will point to the address (which is address pointing to
+ size of array of 4 int
) i.e. to myArr[1]
address.
Note that this:
for(counter=0; counter<4; counter++)
printMyArr(pt++);
is same as this:
for(counter=0; counter<4; counter++)
printMyArr(&myArr[counter]);
^^^^^^^^^^^^^^^
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Answer of question 2:
Here
p = (int *)pt; // pt is pointer to an array of `4` integer
if you remove the (int *)
cast, you will find that the compiler is giving a warning message on this statement. The reason is p
and pt
are not the compatible pointer types. The type of p
is int *
whereas the type of pt
is int (*)[4]
. This incompatible pointer assignment is working because the address of an array and address of first element of an array is numerically same though their type is different. Instead, you should do
p = &(*pt)[0];
From C Standards#6.5.2.1
The definition of the subscript operator is that E1[E2] is identical to (*((E1)+(E2)))
by this rule
&(*pt)[0] --> &(*((*pt)+(0))) --> ((*p)+(0)) --> *p
The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another.
Hence, this statement
p = &(*pt)[0];
is same as this statement
p = *pt;
Question 3: Am I correct thinking that I am incrementing each element here?
Answer of question 3:
Yes.p
is a pointer pointing to first element of array of 4
integer and its type is int *
i.e. it can point to an object which is an int
. When you are doing *p++
, this will first dereference p
and get the value at the address it is pointing to then the p
will be incremented and pointing to next element of array.
The in-memory view of 2D
myArr
array would be something like this:
myArr
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
myArr[1] | 5 | 99 |102 |200 |
---------------------
myArr[2] | 12 | 20 | 25 |600 |
---------------------
myArr[3] | 65 | 66 |999 |1000|
---------------------
Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?
Answer of question 1:
int (*pt)[4]
pt
is pointer to an array of 4
integer. This statement
pt = myArr;
makes the pt
pointing to first 1D
array of myArr
2D
array. It is similar to:
pt = &myArr[0];
The impact of both the statement will be like this:
pt--------|
|/
---------------------
myArr[0] | 12 | 16 | 19 | 20 |
---------------------
When you increment a pointer, it gets incremented in steps of the object size that the pointer can point to. Here
printMyArr(pt++);
first the pt
pointer value passed to printMyArr()
and then pt
will be incremented and since its type is int (*)[4]
that means it can point to an object which is an array of 4
integers, so after increment the pt
will point to the address (which is address pointing to
+ size of array of 4 int
) i.e. to myArr[1]
address.
Note that this:
for(counter=0; counter<4; counter++)
printMyArr(pt++);
is same as this:
for(counter=0; counter<4; counter++)
printMyArr(&myArr[counter]);
^^^^^^^^^^^^^^^
Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?
Answer of question 2:
Here
p = (int *)pt; // pt is pointer to an array of `4` integer
if you remove the (int *)
cast, you will find that the compiler is giving a warning message on this statement. The reason is p
and pt
are not the compatible pointer types. The type of p
is int *
whereas the type of pt
is int (*)[4]
. This incompatible pointer assignment is working because the address of an array and address of first element of an array is numerically same though their type is different. Instead, you should do
p = &(*pt)[0];
From C Standards#6.5.2.1
The definition of the subscript operator is that E1[E2] is identical to (*((E1)+(E2)))
by this rule
&(*pt)[0] --> &(*((*pt)+(0))) --> ((*p)+(0)) --> *p
The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another.
Hence, this statement
p = &(*pt)[0];
is same as this statement
p = *pt;
Question 3: Am I correct thinking that I am incrementing each element here?
Answer of question 3:
Yes.p
is a pointer pointing to first element of array of 4
integer and its type is int *
i.e. it can point to an object which is an int
. When you are doing *p++
, this will first dereference p
and get the value at the address it is pointing to then the p
will be incremented and pointing to next element of array.
edited Jan 3 at 14:28
answered Jan 2 at 22:19
H.S.H.S.
5,6291420
5,6291420
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54012242%2fprecedence-parentheses-pointers-with-iterative-array-functions%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
It's awesome to see such a thoroughly considered and well written question. Nicely done.
– Daniel Farrell
Jan 2 at 19:45
1
Understand, on access
int myArr[3][5]
the first level of indirection (e.g. the first[..]
) is converted to a pointer to the first element in the array. With a 2D array the first element is a pointer to the first row (array). So it is converted(*myArr)[5]
which is a pointer-to-array ofint [5]
. You can't just use*myArr[5]
as[ ]
binds tighter than'*'
from a precedence standpoint which would result in an array-of-pointers toint
(5 pointers). With(*myArr)[5]
the pointer advances by 20-bytes (5-int) per-increment, with*myArr[5]
the pointer advances bysizeof a_pointer
.– David C. Rankin
Jan 2 at 19:51
2
The reference in the standard is C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) (note the exceptions when it is NOT converted to a pointer)
– David C. Rankin
Jan 2 at 19:53