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.
> 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.
> 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.
> On 18/04/2008, James Salisbury
> <piclistKILLspamjsalisbury.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/
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"):
> 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.
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.
>> 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,
> 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.
>
> [...] 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.)