Searching \ for '[EE] A pointer subtraction problem' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: massmind.org/techref/index.htm?key=pointer+subtraction
Search entire site for: 'A pointer subtraction problem'.

Exact match. Not showing close matches.
PICList Thread
'[EE] A pointer subtraction problem'
2008\04\18@171553 by James Salisbury

flavicon
face
Hi,

Does anyone have a good page and some exercises on the use of pointers?
I am trying to find out why the code below won't compile line 244 I get
invalid operand and failed to generate expression.

Thanks


char get_credit (void)
{
char test_string[]="Your balance is £4.38.";
//char *CUSD = "AT+CUSD=1,*#10#";
char *pnd_point;
char *dec_point;
int length;
char cb [5];
//char pnd='£';
//char dec='.';
int credit_pnd;
int credit_pence;
//puts ("AT+CUSD=1,*#10#");
//gsm_gets (rx_array);
strcpy (rx_array,test_string);
pnd_point =strchr (rx_array,'£');
dec_point =strchr (rx_array,0x2E);
length =(pnd_point - dec_point); // line 244
strncpy (cb,(pnd_point+1),(length));
credit_pnd = atoi (cb);
strncpy (cb,(dec_point+1),2);
credit_pence = atoi (cb);

if (credit_pnd >5)
{
portb.0 = 1;
portb.1 = 0;
}
else
{
portb.0 = 0;
portb.1 = 1;
}
}


2008\04\18@173929 by sergio masci

flavicon
face

try changing

> length =(pnd_point - dec_point); // line 244

to

length = ((int)pnd_point - (int)dec_point); // line 244

and if that doesn't work, try

length = ((int)(void *)pnd_point - (int)(void *)dec_point); // line 244

regards
Sergio

2008\04\18@174906 by Rikard Bosnjakovic

picon face
On 18/04/2008, James Salisbury <spam_OUTpiclistTakeThisOuTspamjsalisbury.clara.co.uk> wrote:

> Hi,
>
>  Does anyone have a good page and some exercises on the use of pointers?
>  I am trying to find out why the code below won't compile line 244 I get
>  invalid operand and failed to generate expression.
>
>  Thanks

I'm a bit tipsy at the moment, but I will try to do my best in explaining.

The reason you can't do that is because pointers can't, shouldn't and
musn't be treated as integers. This is heavily pointed out(!) in K&R.
Say, for example, pnd_point points at something in page 1 and
dec_point points to something in page 42, subtracting them both would
return something completely uncomprehendible. For your case this isn't
the situation, as you get the address of two particular characters in
the string, but the compiler doesn't know about this.

The solution for your problem is a loop where you compare your
strchr()-pointer to the string-pointer, subtract a variable until they
match to get the amount of bytes. And the same for the other pointer.
Then you will have two integers, which you can substract.

Something like thids:

char *p_tmp
int substraction;
for (i = 0, p_tmp = pnd_point; p_tmp-- != rx_array; i++) {}
for (j = 0, p_tmp = dec_point; p_tmp-- != rx_array; j++) {}
substraction = i - j;

Untested, but hopefully you will get the idea.

The important part is that you have to unlearn(?) the fact that you
cannot add or substract different pointers, only increment/decrement
the pointers themselves.


--
- Rikard - http://bos.hack.org/cv/

2008\04\18@181943 by peter green

flavicon
face

> char *p_tmp
> int substraction;
> for (i = 0, p_tmp = pnd_point; p_tmp-- != rx_array; i++) {}
> for (j = 0, p_tmp = dec_point; p_tmp-- != rx_array; j++) {}
> substraction = i - j;
>
>  
That seems horriblly inefficiant.

A much faster way is to typcast to an appropriate sized integer.

I thought pointer subtraction was allowed by the C standard and a quick
google seems to agree with me. Of course PIC C compilers tend not to
follow the standandards too closely in my experiance.

2008\04\18@215958 by John Chung

picon face
I would like to add that pointers can only
add/subtract the number of element from it's type

example:
int *pint=[0,2,5,3];

pint = pint + 2;//would now point to element [5]

John Chung



--- Rikard Bosnjakovic <.....rikard.bosnjakovicKILLspamspam@spam@gmail.com>
wrote:

{Quote hidden}

> --

2008\04\18@231607 by William \Chops\ Westfield

face picon face

On Apr 18, 2008, at 6:59 PM, John Chung wrote:
> I would like to add that pointers can only
> add/subtract the number of element from it's type

Hmm.  I too am pretty sure that you are allowed to subtract one  
pointer from another, as long as they're the same type, and you'll  
get an int.  After all, you can add an int to a pointer, and it  
certainly ought to be true that:

       (ptr + i) - (ptr) == i;

This college class page supports this (see "pointer subtaction"):

http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/BitOp/pointer.html

BillW

2008\04\19@073922 by Gerhard Fiedler

picon face
James Salisbury wrote:

> Does anyone have a good page and some exercises on the use of pointers? I
> am trying to find out why the code below won't compile line 244 I get
> invalid operand and failed to generate expression.

I think this is because of a non-standard restriction of your compiler.
This looks like perfectly valid C.


peter green wrote:

> A much faster way is to typcast to an appropriate sized integer.

Not necessary.

> I thought pointer subtraction was allowed by the C standard and a quick
> google seems to agree with me. Of course PIC C compilers tend not to
> follow the standandards too closely in my experiance.

It is allowed. Some PIC C compilers are better in that regard than
others...

Below I copied what the C89 standard has to say about subtraction of
pointers and other types. (Even though there's a newer standard C99, even
fewer PIC C compilers support it.)

Gerhard


:: 3.3.6 Additive operators
::
:: Syntax
::
:: additive-expression: multiplicative-expression additive-expression +
:: multiplicative-expression additive-expression -  multiplicative-expression
::
::
:: Constraints
::
:: For addition, either both operands shall have arithmetic type, or one
:: operand shall be a pointer to an object type and the other shall have
:: integral type.  (Incrementing is equivalent to adding 1.)
::
:: For subtraction, one of the following shall hold:  
::
:: * both operands have arithmetic type;  
::
:: * both operands are pointers to qualified or unqualified versions of
:: compatible object types; or
::
:: * the left operand is a pointer to an object type and the right operand
:: has integral type.  (Decrementing is equivalent to subtracting 1.)
::
:: Semantics
::
:: If both operands have arithmetic type, the usual arithmetic conversions
:: are performed on them.
::
:: The result of the binary + operator is the sum of the operands.
::
:: The result of the binary - operator is the difference resulting from the
:: subtraction of the second operand from the first.
::
:: When an expression that has integral type is added to or subtracted from a
:: pointer, the integral value is first multiplied by the size of the object
:: pointed to.  The result has the type of the pointer operand.  If the
:: pointer operand points to a member of an array object, and the array
:: object is large enough, the result points to a member of the same array
:: object, appropriately offset from the original member.  Thus if P points
:: to a member of an array object, the expression P+1 points to the next
:: member of the array object.  Unless both the pointer operand and the
:: result point to a member of the same array object, or one past the last
:: member of the array object, the behavior is undefined.  Unless both the
:: pointer operand and the result point to a member of the same array object,
:: or the pointer operand points one past the last member of an array object
:: and the result points to a member of the same array object, the behavior
:: is undefined if the result is used as the operand of a unary * operator.
::
:: When two pointers to members of the same array object are subtracted, the
:: difference is divided by the size of a member.  The result represents the
:: difference of the subscripts of the two array members.  The size of the
:: result is implementation-defined, and its type (a signed integral type) is
:: ptrdiff_t defined in the <stddef.h> header.  As with any other arithmetic
:: overflow, if the result does not fit in the space provided, the behavior
:: is undefined.  If two pointers that do not point to members of the same
:: array object are subtracted, the behavior is undefined.  However, if P
:: points either to a member of an array object or one past the last member
:: of an array object, and Q points to the last member of the same array
:: object, the expression (Q+1) - P has the same value as (Q-P) + 1 , even
:: though Q+1 does not point to a member of the array object.

2008\04\19@074908 by Robert Ammerman

picon face
ORIGINAL CODE STRIPPED TO BARE MINIMUM:

char get_credit (void)
{
   char test_string[]="Your balance is £4.38.";
   char *pnd_point;
   char *dec_point;
   int length;
   strcpy (rx_array,test_string);
   pnd_point =strchr (rx_array,'£');
   dec_point =strchr (rx_array,0x2E);
   length =(pnd_point - dec_point); // line 244
}


First: It _is_ perfectly legal to subtract one pointer from another in ANSI
"C", if:

1) The two pointers are pointers to the same type, and
2) They both both into, or just beyond, the same array.

You have met both conditions.

However, I am sure you made a mistake: 'dec_point' will be greater than
'pnd_point', so when you do your subtraction you will get 'length=-2". I am
guessing that perhaps this is your issue, but I am not sure how the compiler
could tell.

Alternatively, you may have a broken compiler that just doesn't understand
pointer subtraction.

This should work, and be quite efficient

credit_pnd = 0;
credit_pence = 0;
char const *p = strchr(rx_array,'£');
while ( *p != '.' )
{
   credit_pnd *= 10;
   credit_pnd += *p - '0';
   ++p;
}
++p;
while ( *p != 0 )
{
   credit_pence *= 10;
   credit_pence += *p - '0';
   ++p;
}

Alternatively:

pnd_point =strchr (rx_array,'£');
dec_point =strchr (rx_array,0x2E);
*dec_point = 0;
credit_pnd = atoi( pnd_point+1);
credit_pence = atoi(dec_point+1);

Or even:

char *p;

p = strchr(rx_array,0x2E);
credit_pence = atoi(p+1);
*p=0;
p = strchr(rx_array,'£');
credit_pnd = atoi(p+1);

[ you can reuse the pointer variable ]
--- Bob Ammerman
RAm Systems

2008\04\19@075016 by Dario Greggio

face picon face
Gerhard Fiedler wrote:

> I think this is because of a non-standard restriction of your compiler.
> This looks like perfectly valid C.

This was my thought as well, thanks for pointing this out.

--
Ciao, Dario -- ADPM Synthesis sas -- http://www.adpm.tk

2008\04\19@075257 by peter green

flavicon
face

>> A much faster way is to typcast to an appropriate sized integer.
>>    
>
> Not necessary.
>  
Loooks like it is in this case even if it is not nessacery in standard C.

And I still think that the loop based soloution is terrible,

2008\04\19@113537 by John Chung

picon face

--- Gerhard Fiedler <.....listsKILLspamspam.....connectionbrazil.com>
wrote:

{Quote hidden}

> --

2008\04\20@093023 by Gerhard Fiedler
picon face
William "Chops" Westfield wrote:

> [...] and it certainly ought to be true that:
>
> (ptr + i) - (ptr) == i;

While in essence you're right, this argument doesn't always work -- so you
still have to know when it does and when not, and as such it doesn't
explain much (as it's the result of already knowing :).

For example you shouldn't bet anything of value that this is true:

 (doubleVal + intVal) - (doubleVal) == intVal;

(Of course, we know why that's different and why the first one works and
the second one not, but I just wanted to point out that math and
programming instructions are not the same.)

Gerhard

More... (looser matching)
- Last day of these posts
- In 2008 , 2009 only
- Today
- New search...