LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-07-2013, 08:21 PM   #1
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Rep: Reputation: Disabled
confused pointer arithmatic


Trying to learn C, and having problem with pointer arithmatic which I hope someone can help explain.
I’ve provided some textbook code, and a variation thereof (note remmed line “pointer = &num”). I don’t understand why this code line has the effect that it does in the second version, and hope that someone can explain it in simple terms that I hope to understand. Thanks in advance for any help you can provide.

>>>>>>>>>>>>>>>>>>>>>Code
Code:
int main(void){

int num = 20;
int *pointer;

pointer = #

printf("*pointer = %d\n", *pointer);
printf("pointer = %p\n", pointer);

pointer = #

*pointer = *pointer++;
printf("*pointer++ = %d\n", *pointer);
printf("pointer = %p\n", pointer);

//pointer = #
*pointer = *pointer++;
printf("(*pointer)++ = %d\n", *pointer);
printf("pointer = %p\n", pointer);

return 0;

}
>>>>>>>>>>>>>>>>>>>>>>>
Yields
: *pointer = 20
pointer = 0xbf98812c

*pointer++ = 20
pointer = 0xbf988130

(*pointer)++ = 20
pointer = 0xbf988134
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
where all pointer addresses are incremented, as expected
>>>>>>>>>>>>>>>>>>>>>>>>While this code variation
Code:
int main(void){

int num = 20;
int *pointer;

pointer = #

printf("*pointer = %d\n", *pointer);
printf("pointer = %p\n", pointer);
printf("\n_________________________\n");

pointer = #

*pointer = *pointer++;
printf("*pointer++ = %d\n", *pointer);
printf("pointer = %p\n", pointer);
pointer = #
*pointer = *pointer++;
printf("(*pointer)++ = %d\n", *pointer);
printf("pointer = %p\n", pointer);

return 0;

}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>yields
*pointer = 20
pointer = 0xbf898e6c

*pointer++ = 20
pointer = 0xbf898e70

(*pointer)++ = 20
pointer = 0xbf898e70
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
where this final pointer address is not incremented.
 
Old 06-07-2013, 08:27 PM   #2
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
I believe
*pointer = *pointer++;
has undefined behavior.

The use of pointer on the left may be before or after the increment on the right.

But the detail you are asking about seems simpler.
Each time you include the instruction
pointer = #
that sets the value back to pointing at num, so when you increment it again it is obviously only incremented to one position past num.

Last edited by johnsfine; 06-07-2013 at 08:36 PM.
 
1 members found this post helpful.
Old 06-07-2013, 09:28 PM   #3
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by johnsfine View Post
I believe
*pointer = *pointer++;
has undefined behavior.

The use of pointer on the left may be before or after the increment on the right.

But the detail you are asking about seems simpler.
Each time you include the instruction
pointer = #
that sets the value back to pointing at num, so when you increment it again it is obviously only incremented to one position past num.
Actually, the code line in the text was simply *pointer++;, which did not compile in clang, with errmsg "expression result unused". At least the code compiled with what you identify as my code with undefined behavior. Perhaps that is why program output is not making sense to me. I guess that my question really relates to whether when a pointer to a variable is incremented, does the variable itself move to the new incremented address? (Does this question make sense?)
 
Old 06-07-2013, 11:07 PM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
*pointer++ in itself is equivalent with pointer++, but that isn't an error, only a warning

When in doubt, use brackets or simpler expressions:

Code:
#1 n= (*p)++;
#3 n= *p; (*p)=(*p)+1; 
#3 n= *(p++);
#4 n= *p; p= p+1;
Here #3 and #4 are equivalent (also #1 and #2), but the latter is easier to understand.

Last edited by NevemTeve; 06-07-2013 at 11:36 PM.
 
1 members found this post helpful.
Old 06-08-2013, 03:22 AM   #5
psionl0
Member
 
Registered: Jan 2011
Distribution: slackware_64 14.1
Posts: 722
Blog Entries: 2

Rep: Reputation: 124Reputation: 124
Quote:
Originally Posted by johnsfine View Post
I believe
*pointer = *pointer++;
has undefined behavior.
From the output it appears that the statement has the following effect:
1. Get contents from location pointed to by pointer
2. Increment pointer
3. Store contents at location pointed to by new value of pointer.

Steps 2 and 3 might easily have been reversed depending on the nature of the compiler in which case, the second and third printings of *pointer would have been indeterminate.
 
1 members found this post helpful.
Old 06-08-2013, 05:08 AM   #6
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by atlantis43 View Post
my question really relates to whether when a pointer to a variable is incremented, does the variable itself move to the new incremented address? (Does this question make sense?)
The variable does not move. The address of the variable is unchanged.

The incremented pointer points to memory right after the variable. In a more complicated program, that memory would typically contain some other variable. For the apparent interpretation of *pointer=*pointer++; that would clobber the value of that other variable.

Quote:
Originally Posted by atlantis43 View Post
Actually, the code line in the text was simply *pointer++;
What did you intend that code line to mean?

It means read the value pointed to by pointer and also increment the pointer. But it doesn't do anything with the value it read (so the compiler gives you a warning).

Last edited by johnsfine; 06-08-2013 at 05:11 AM.
 
Old 06-08-2013, 05:15 AM   #7
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
*pointer++ in itself is equivalent with pointer++, but that isn't an error, only a warning

When in doubt, use brackets or simpler expressions:

Code:
#1 n= (*p)++;
#3 n= *p; (*p)=(*p)+1; 
#3 n= *(p++);
#4 n= *p; p= p+1;
Here #3 and #4 are equivalent (also #1 and #2), but the latter is easier to understand.
Will try applying the above mentioned threads to see if that improves my understanding.
Though only a "warning", my terminal (VMWare Player with clang compiler) considers it an error, and will not run code:
a1.c:18:1: error: expression result unused [-Werror,-Wunused-value]
*(pointer++);
^~~~~~~~~~~~
1 error generated.
make: *** [a1] Error 1
jharvard@appliance (~/trial): ./a1
bash: ./a1: No such file or directory

One further question would be: How would var n be declared; as int n or as int *n?

Last edited by atlantis43; 06-08-2013 at 05:37 AM.
 
Old 06-08-2013, 05:27 AM   #8
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by johnsfine View Post
The variable does not move. The address of the variable is unchanged.

The incremented pointer points to memory right after the variable. In a more complicated program, that memory would typically contain some other variable. For the apparent interpretation of *pointer=*pointer++; that would clobber the value of that other variable.



What did you intend that code line to mean?

It means read the value pointed to by pointer and also increment the pointer. But it doesn't do anything with the value it read (so the compiler gives you a warning).
As just mentioned in response to Nevem Teve, my compiler takes this as error, not warning, and won't compile. The original code was commented with:
/*
increments pointer
then obtains the value at
the new memory address
*/
*pointer++;
so this made no sense for my learning process. Hopefully, all the info provided in this thread will help me understand what should be going on with pointer math.
 
Old 06-08-2013, 06:38 AM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by atlantis43 View Post
The original code was commented with:
/*
increments pointer
then obtains the value at
the new memory address
*/
*pointer++;
That is an incorrect comment. That code increments the pointer and obtains the value at the old address.

If you wanted to increment the pointer and obtain the value at the new address, it would be
*++pointer;

Quote:
Originally Posted by atlantis43 View Post
my compiler takes this as error, not warning, and won't compile.
Compilers often have options to treat certain warnings (or all warnings) as errors.

You might want to change the options to allow this to be just a warning rather than an error. Sorry I don't have detailed instructions for you to do that. Look at the command line you are using to run the compiler and read the documentation for the compiler.

But instead, you might want to fix the code causing those warnings/errors.

What is the point of "obtaining" a value if you aren't using it?

Quote:
understand what should be going on with pointer math.
The design of the C language creates a close connection between pointers and arrays. It is best to start out thinking of a pointer as being the address of an element of an array:
Code:
int data[12];
int* pointer = &(data[0]);
Having done the above
pointer[0] is the same as *pointer and same as data[0]
pointer[1] is the same as *(pointer+1) and same as data[1]
etc.
If you then executed
pointer++;
then
pointer[0] is the same as *pointer and same as data[1]
pointer[1] is the same as *(pointer+1) and same as data[2]
etc.

If you did pointer++ too many times, or you used to large a value of N in pointer[N] or *(pointer+N) then you are going past the end of the array.

Once you understand the basic meaning of a C pointer as the address of an element of an array, you can understand the exception case:
Code:
int n;
int* pointer = &n;
Here pointer is the address of a scalar, not the address of an element of an array. But nothing about the pointer or the address indicate it is a scalar. All the pointer operations pointer++ or pointer[7] etc. that are based on the idea that pointer is the address of an element of an array still operate on that basis. Since you assigned the address of a scalar to pointer, all of those operations generate or access addresses with undefined contents.

You are treating a scalar kind of like a one element array. As soon as you increment to an address past the only element, you are making the same mistake as incrementing past the capacity of a real array.

Last edited by johnsfine; 06-08-2013 at 06:57 AM.
 
1 members found this post helpful.
Old 06-08-2013, 06:41 AM   #10
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by johnsfine View Post
That is an incorrect comment. That code increments the pointer and obtains the value at the old address.

If you wanted to increment the pointer and obtain the value at the new address, it would be
*++pointer;
Thanks. That really helps clarify what was so confusing. Some texts obviously need better proofreading.
One further question this brings up is preferential order of operations with unary operators. Since * has R->L priority, and ++ has L-R priority, how does the compiler know which operation to do first?

Last edited by atlantis43; 06-08-2013 at 06:48 AM.
 
Old 06-08-2013, 07:01 AM   #11
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by atlantis43 View Post
One further question this brings up is preferential order of operations with unary operators. Since * has R->L priority, and ++ has L-R priority, how does the compiler know which operation to do first?
Google "C operator precedence chart" and click on one of the links you find.

That will tell you all the rules of which operations are done before which others.

You can see on any of those charts that ++ is done before unary *.

BTW, I find the idea of L/R associativity of unary operators meaningless. When two unary operators are on the same side of an operand, the one that is closer has to bind first, neither precedence nor associativity can affect that.
When unary operators are on the opposite side of an operand, they are different operators, with different precedence, so associativity doesn't matter.
L/R associativity is only meaningful for binary operators. Example:
A = B = C;
is the same as
A = ( B = C );
Not the same as
( A = B ) = C;
But
A / B / C
is the same as
( A / B ) / C
That shows / and = have opposite LR associativity in C.

Quote:
Originally Posted by atlantis43 View Post
Thanks. That really helps clarify what was so confusing. Some texts obviously need better proofreading.
I don't know exactly what the original said, but I suspect the code was subtly wrong rather than the comment wrong. In the following the comment is correct (but the printf text misleading).
Code:
/*
increments pointer
then obtains the value at
the new memory address
*/
pointer++;
printf("*pointer++ = %d\n", *pointer);
Add one redundant * that (except for your picky compiler) doesn't change the meaning of the code, and now the comment is also misleading:
Code:
/*
increments pointer
then obtains the value at
the new memory address
*/
*pointer++;
printf("*pointer++ = %d\n", *pointer);
If you didn't want it misleading at all, that needs my earlier suggestion:
Code:
/*
increments pointer
then obtains the value at
the new memory address
*/
printf("*++pointer = %d\n", *++pointer);

Last edited by johnsfine; 06-08-2013 at 07:20 AM.
 
1 members found this post helpful.
Old 06-08-2013, 07:29 AM   #12
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Thanks to all your help, finally beginning to make sense. When converting code to:
Code:
pointer++;
printf("*pointer++ = %d\n", *pointer);
printf("pointer = %p\n", pointer);
I get terminal output of:
*pointer = 20
pointer = 0xbfa1015c
pointer++ = 0 //which is the incidental value of that memory position
pointer = 0xbfa10160 //at this address, with val of num not even present.
(*pointer)++ = 21
pointer = 0xbfa1015c

Another item to assist my understanding: What would the parsing be if I wanted to assign a value to this new pointer address?

(Also, sorry for the picky compiler----didn't know there was such a thing.)

Last edited by atlantis43; 06-08-2013 at 08:00 AM.
 
Old 06-08-2013, 10:36 AM   #13
psionl0
Member
 
Registered: Jan 2011
Distribution: slackware_64 14.1
Posts: 722
Blog Entries: 2

Rep: Reputation: 124Reputation: 124
Quote:
Originally Posted by atlantis43 View Post
Another item to assist my understanding: What would the parsing be if I wanted to assign a value to this new pointer address?
pointer = ... assigns a new address to the pointer
*pointer = ... assigns a new value to the integer pointed to by pointer
pointer++ or ++pointer advances the pointer to point to the next address where an integer is stored (it is the programmer's responsibility to ensure that the memory being pointed is a valid address for integer storage).
(*pointer)++ or ++(*pointer)increments the integer pointed to by pointer.

It is best not to have complicated increment operations within an expression if you don't fully understand the order of the operations.

If you want a function to assign a new value to a pointer, you could call it by newPointerValue(&pointer, address);
and write the procedure as:
void newPointerValue(int **p, int *a) {
*p = a;
}
 
1 members found this post helpful.
Old 06-08-2013, 10:40 AM   #14
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by atlantis43 View Post
What would the parsing be if I wanted to assign a value to this new pointer address?
Here is an example in which it is valid (defined behavior) to assign a value to the new address. The part in red is the answer to your question. The rest is there to show the valid meaning.

Code:
int data[] = {7,8};
int* pointer = &(data[0]);
printf("data[] = {%d,%d}  *pointer=%d\n", data[0], data[1], *pointer);
pointer++;
*pointer = 4;
printf("data[] = {%d,%d}  *pointer=%d\n", data[0], data[1], *pointer);

Last edited by johnsfine; 06-08-2013 at 10:45 AM.
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Arithmatic calculation in shell script shivaa Linux - Newbie 14 10-21-2012 06:30 PM
Bash for loop and arithmatic scub@ Programming 1 11-25-2009 02:27 AM
How to do arithmatic operation on floating number by using expr ??? raman.kumar Linux - Newbie 2 05-18-2009 07:02 AM
returning data to main() via a pointer to a pointer. slzckboy Programming 3 05-30-2005 01:20 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:50 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration