Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pointer arithmetic error?

0 views
Skip to first unread message

Bill Cunningham

unread,
Dec 4, 2009, 3:40:03 PM12/4/09
to
I am creating a dice game that returns ints up to the number specified
by argv[1]. Simple enough. But I am also wanting to add a switch, "-a" to be
able to run a routine that adds two numbers and returns the result. So I
want the program to accept "-a" or "a" or "a-" as the switch. Which would be
*(argv[1]) *(argv[1]+1) or *(argv[1]+2) that I would need C to examine. Or
argv[1][0] argv[1][1] argv[1][2].

But I was going to try it through pointer arithmetic.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

int main(int argc, char *argv[])
{
if (argc > 4 || argc == 0) {
fprintf(stderr, "dice usage error\n");
exit(EXIT_FAILURE);
}
int c, d, x, y;
char **ptr = &argv[1];
x = strtol(argv[2], NULL, 10);
y = strtol(argv[3], NULL, 10);
if (*(ptr) || *(ptr + 1) == 'a') {
printf("%i\n", x + y);
exit(0);
}

di.c: In function `main':
di.c:16: warning: comparison between pointer and integer
di.c:19: error: syntax error at end of input

Errors from running gcc -c di.c

Bill


---
In C there should be no or little need for casts

--Rihard Heathfield


Lew Pitcher

unread,
Dec 4, 2009, 3:54:52 PM12/4/09
to
On December 4, 2009 15:40, in comp.lang.c, Bill Cunningham
(nos...@nspam.invalid) wrote:

> I am creating a dice game that returns ints up to the number specified
> by argv[1]. Simple enough. But I am also wanting to add a switch, "-a" to
> be able to run a routine that adds two numbers and returns the result. So
> I want the program to accept "-a" or "a" or "a-" as the switch. Which
> would be *(argv[1]) *(argv[1]+1) or *(argv[1]+2) that I would need C to
> examine. Or
> argv[1][0] argv[1][1] argv[1][2].
>
> But I was going to try it through pointer arithmetic.
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <ctype.h>
> #include <time.h>
>
> int main(int argc, char *argv[])
> {
> if (argc > 4 || argc == 0) {
> fprintf(stderr, "dice usage error\n");
> exit(EXIT_FAILURE);
> }
> int c, d, x, y;
> char **ptr = &argv[1];
> x = strtol(argv[2], NULL, 10);
> y = strtol(argv[3], NULL, 10);
> if (*(ptr) || *(ptr + 1) == 'a') {

OK, Bill. Above is line 16, the origin of the "comparison between pointer
and integer" warning.

Do we agree that <ptr> is a pointer to a pointer to char? Yes?
So <*(ptr)> is a pointer to char, right? We dereference a pointer to
pointer, to get a pointer.

And < *(ptr + 1) > is also a pointer to char, right? We add 1 to <ptr>,
getting another "pointer to a pointer to char", then dereference it to get
a "pointer to char".

But, what of <'a'>? What type of data is it? Of course, <'a'> is an integer
constant.

Now, in line 16, you compare
a pointer to char
with
an integer constant
but, of course, these two things have different types, and cannot be
compared with any meaning.

Hence the warning message.

> printf("%i\n", x + y);
> exit(0);
> }

Above is line 19. The line contains the closing brace of a compound
statement, and that brace matches the opening brace on line 16.

There is one other compound statement that is still open at this point: the
compound statement that started on line 7 (the 'body' statement of the
main() function).

Presumably, your source file ends here. Since no closing brace (to match the
opening brace on line 7) has been found by the end of the source file, the
compiler complains that you have a syntax error.



> di.c: In function `main':
> di.c:16: warning: comparison between pointer and integer
> di.c:19: error: syntax error at end of input
>
> Errors from running gcc -c di.c
>
> Bill
>
>
> ---
> In C there should be no or little need for casts
>
> --Rihard Heathfield
>
>

--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
---------- Slackware - Because I know what I'm doing. ------


Bill Cunningham

unread,
Dec 4, 2009, 9:45:19 PM12/4/09
to

"Lew Pitcher" <lpit...@teksavvy.com> wrote in message
news:cfc8a$4b19771c$cef882ed$96...@TEKSAVVY.COM-Free...

> But, what of <'a'>? What type of data is it? Of course, <'a'> is an
> integer
> constant.

[snip]

'a' is what is supposed to be in argv[1]. So I would think it would be a
char* or char**. To be more precise I want it in argv[1][1] or argv[1][0] is
acceptable. The code as you correctly noticed is a fragment. From the
command line if -a or a is entered as argv[1] I would use x and y total the
values for argv[3] and argv[4].

I'm not quite seeing where you say a is an int. I got to learn this
sometime.

Bill
---
In C there should be no or little need for casts

--Richard Heathfield


Keith Thompson

unread,
Dec 4, 2009, 10:07:18 PM12/4/09
to
"Bill Cunningham" <nos...@nspam.invalid> writes:
> "Lew Pitcher" <lpit...@teksavvy.com> wrote in message
> news:cfc8a$4b19771c$cef882ed$96...@TEKSAVVY.COM-Free...
>
>> But, what of <'a'>? What type of data is it? Of course, <'a'> is an
>> integer
>> constant.
>
> [snip]
>
> 'a' is what is supposed to be in argv[1].

No.

argv is a char**, so argv[1] is of type char*.

> So I would think it would be a
> char* or char**.

Why would you think that? How could 'a' be of type char* or char**?

I can understand thinking that 'a' is of type char. For historical
reasons, character constants such as 'a' are of type int, not of type
char. It could make sense to compare a character constant to
something of type char.

> To be more precise I want it in argv[1][1] or argv[1][0] is
> acceptable.

That's not more precise, that's just different.

argv is of type char**. argv[1] is of type char*. argv[1][1] is of
type char. Three different types, none of which are in any way
compatible with each other.

> The code as you correctly noticed is a fragment.

The only thing that kept it from being a complete program was the
closing "}" for main.

> From the
> command line if -a or a is entered as argv[1] I would use x and y total the
> values for argv[3] and argv[4].
>
> I'm not quite seeing where you say a is an int. I got to learn this
> sometime.

There's nothing in your program named a. 'a', the character constant,
is of type int. (a is an identifier; 'a' is a character constant.
This is not a trivial difference.)

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Bill Cunningham

unread,
Dec 4, 2009, 10:40:27 PM12/4/09
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnfx7qw...@nuthaus.mib.org...

> I can understand thinking that 'a' is of type char. For historical
> reasons, character constants such as 'a' are of type int, not of type
> char. It could make sense to compare a character constant to
> something of type char.
>
>> To be more precise I want it in argv[1][1] or argv[1][0]
>> is
>> acceptable.
>
> That's not more precise, that's just different.
>
> argv is of type char**. argv[1] is of type char*. argv[1][1] is of
> type char. Three different types, none of which are in any way
> compatible with each other.
>
>> The code as you correctly noticed is a fragment.
>
> The only thing that kept it from being a complete program was the
> closing "}" for main.
>
>> From the
>> command line if -a or a is entered as argv[1] I would use x and y total
>> the
>> values for argv[3] and argv[4].
>>
>> I'm not quite seeing where you say a is an int. I got to learn this
>> sometime.
>
> There's nothing in your program named a. 'a', the character constant,
> is of type int. (a is an identifier; 'a' is a character constant.
> This is not a trivial difference.)

So what should I do? I thought 'a' meant character. Cast? I don't think
that would be the right thing to do. Should I use some kind of conversion
function? I'm stumped on this one.

Ben Bacarisse

unread,
Dec 5, 2009, 6:28:15 AM12/5/09
to
"Bill Cunningham" <nos...@nspam.invalid> writes:

The fact that the types are wrong is just showing you that you have
not found the right thing to compare equal to 'a'. argv is of type
char ** and argv[1] is of type char *. When your program is called
with argv[1] pointing at "-a" then argv[1][0] == '-' and argv[1][1] ==
'a'. Alternatively you can test to see of strcmp(argv[1], "-a") == 0.

> ---

This is not a good sig separator. The accepted standard is "-- "
(note the space after the two dashes).

--
Ben.

Nick Keighley

unread,
Dec 5, 2009, 6:44:29 AM12/5/09
to
On 5 Dec, 03:40, "Bill Cunningham" <nos...@nspam.invalid> wrote:
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:lnfx7qw...@nuthaus.mib.org...

> > I can understand thinking that 'a' is of type char.  For historical
> > reasons, character constants such as 'a' are of type int, not of type
> > char.  It could make sense to compare a character constant to
> > something of type char.

note well.

> >> To be more precise I want it in argv[1][1] or argv[1][0]
> >> is acceptable.
>
> > That's not more precise, that's just different.
>
> > argv is of type char**.  argv[1] is of type char*.  argv[1][1] is of
> > type char.  Three different types, none of which are in any way
> > compatible with each other.

did you follow that?

> >>  The code as you correctly noticed is a fragment.
>
> > The only thing that kept it from being a complete program was the
> > closing "}" for main.
>
> >> From the
> >> command line if -a or a is entered as argv[1] I would use x and y total
> >> the
> >> values for argv[3] and argv[4].
>
> >>     I'm not quite seeing where you say a is an int. I got to learn this
> >> sometime.
>
> > There's nothing in your program named a.  'a', the character constant,
> > is of type int.  (a is an identifier; 'a' is a character constant.
> > This is not a trivial difference.)
>
>     So what should I do? I thought 'a' meant character.

yes 'a' is character constant (ignore for the time being that it is of
type int) and can be compared with a char.

char c;
if (c == 'a')

is perfectly ok (assuming c has a sensible value in it). You are
trying to compare a char constant with a POINTER-TO-CHAR. THis is not
valid

char *pc;
if (pc == 'a')

this is NOT ok


> Cast? I don't think
> that would be the right thing to do. Should I use some kind of conversion
> function? I'm stumped on this one.

explain what you are trying to do.

Would this do what you want?

if (argv[1][0] == 'a')


Richard

unread,
Dec 5, 2009, 12:20:11 PM12/5/09
to
Nick Keighley <nick_keigh...@hotmail.com> writes:

Why not just say 'a' is a character for God's sake?

>
> is perfectly ok (assuming c has a sensible value in it). You are
> trying to compare a char constant with a POINTER-TO-CHAR. THis is not
> valid
>
> char *pc;
> if (pc == 'a')
>
> this is NOT ok
>
>> Cast? I don't think
>> that would be the right thing to do. Should I use some kind of conversion
>> function? I'm stumped on this one.
>
> explain what you are trying to do.
>
> Would this do what you want?
>
> if (argv[1][0] == 'a')
>

The first thing to do with non-trolls is to move away from argv.

e.g char * ptrToCharArg=argv[1];

etc etc etc

--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c

Bill Cunningham

unread,
Dec 5, 2009, 12:24:08 PM12/5/09
to

"Nick Keighley" <nick_keigh...@hotmail.com> wrote in message
news:86685865-733a-408b...@l13g2000yqb.googlegroups.com...

On 5 Dec, 03:40, "Bill Cunningham" <nos...@nspam.invalid> wrote:
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:lnfx7qw...@nuthaus.mib.org...

> > I can understand thinking that 'a' is of type char. For historical
> > reasons, character constants such as 'a' are of type int, not of type
> > char. It could make sense to compare a character constant to
> > something of type char.

note well.

> >> To be more precise I want it in argv[1][1] or argv[1][0]
> >> is acceptable.
>
> > That's not more precise, that's just different.
>
> > argv is of type char**. argv[1] is of type char*. argv[1][1] is of
> > type char. Three different types, none of which are in any way
> > compatible with each other.

did you follow that?

I think.

> >> The code as you correctly noticed is a fragment.
>
> > The only thing that kept it from being a complete program was the
> > closing "}" for main.
>
> >> From the
> >> command line if -a or a is entered as argv[1] I would use x and y total
> >> the
> >> values for argv[3] and argv[4].
>
> >> I'm not quite seeing where you say a is an int. I got to learn this
> >> sometime.
>
> > There's nothing in your program named a. 'a', the character constant,
> > is of type int. (a is an identifier; 'a' is a character constant.
> > This is not a trivial difference.)
>
> So what should I do? I thought 'a' meant character.

yes 'a' is character constant (ignore for the time being that it is of
type int) and can be compared with a char.

char c;
if (c == 'a')

Ok but that wouldn't work with two characters. For example this I know
wouldn't work:

char c;
if( c=="-a")

Because it's a string. I was going to try my hand at pointer arithmetic and
look at argv[1][0] and argv[1][1].

is perfectly ok (assuming c has a sensible value in it). You are
trying to compare a char constant with a POINTER-TO-CHAR. THis is not
valid

char *pc;
if (pc == 'a')

this is NOT ok


> Cast? I don't think
> that would be the right thing to do. Should I use some kind of conversion
> function? I'm stumped on this one.

explain what you are trying to do.

Would this do what you want?

if (argv[1][0] == 'a')


The program dice.exe would be called from DOS or windows command by dice -a
4 5 and the result would be 9. Now it should also do this as a number
generator:

dice 6 //would give randoms up to 6.
dice 12 //would give randoms up to 12.

Bill

Bill Cunningham

unread,
Dec 5, 2009, 12:33:04 PM12/5/09
to

"Nick Keighley" <nick_keigh...@hotmail.com> wrote in message
news:86685865-733a-408b...@l13g2000yqb.googlegroups.com...

Would this do what you want?

if (argv[1][0] == 'a')


Yes that would work. I was trying to attempt this via this way. Maybe it
doesn't work that way.

*(argv[1]) and *(argv[1]+1) which would a pointers to argv[1][0] and
argv[1][1].

Bill

Bill Cunningham

unread,
Dec 5, 2009, 12:35:15 PM12/5/09
to

"Bill Cunningham" <nos...@nspam.invalid> wrote in message
news:4b1a9943$0$5330$bbae...@news.suddenlink.net...

>
> "Nick Keighley" <nick_keigh...@hotmail.com> wrote in message
> news:86685865-733a-408b...@l13g2000yqb.googlegroups.com...
>
> Would this do what you want?
>
> if (argv[1][0] == 'a')

Wait more what I woant come to think of it is

if (argv[1][0]=='-' && argv[1][1]=='a')

Nick Keighley

unread,
Dec 5, 2009, 12:48:45 PM12/5/09
to
On 5 Dec, 17:20, Richard <rgrd...@gmail.com> wrote:
> Nick Keighley <nick_keighley_nos...@hotmail.com> writes:

<snip>

> > Would this do what you want?
>
> >     if (argv[1][0] == 'a')
>
> The first thing to do with non-trolls is to move away from argv.
>
> e.g char * ptrToCharArg=argv[1];

I usually call it arg

char *arg = argv[1];

if (arg[0] == 'a')

Nick Keighley

unread,
Dec 5, 2009, 12:55:30 PM12/5/09
to
On 5 Dec, 17:24, "Bill Cunningham" <nos...@nspam.invalid> wrote:
> "Nick Keighley" <nick_keighley_nos...@hotmail.com> wrote in message

> news:86685865-733a-408b...@l13g2000yqb.googlegroups.com...
> On 5 Dec, 03:40, "Bill Cunningham" <nos...@nspam.invalid> wrote:
> > "Keith Thompson" <ks...@mib.org> wrote in message
> >news:lnfx7qw...@nuthaus.mib.org...

<snip>

> > >> To be more precise I want it in argv[1][1] or argv[1][0]
> > >> is acceptable.
>
> > > That's not more precise, that's just different.
>
> > > argv is of type char**. argv[1] is of type char*. argv[1][1] is of
> > > type char. Three different types, none of which are in any way
> > > compatible with each other.
>
> did you follow that?

you fucked up the quoting again.

> I think.

<snip>

> > So what should I do? I thought 'a' meant character.
>
> yes 'a' is character constant (ignore for the time being that it is of
> type int) and can be compared with a char.
>
>    char c;
>    if (c == 'a')
>
> Ok but that wouldn't work with two characters. For example this I know
> wouldn't work:
>
> char c;
> if( c=="-a")
>
> Because it's a string.

yup. Use strcmp() tocompare strings


> I was going to try my hand at pointer arithmetic and
> look at argv[1][0] and argv[1][1].

which are of what type?

<snip>

> explain what you are trying to do.

<snip>

> The program dice.exe would be called from DOS or windows command by dice -a
> 4 5 and the result would be 9. Now it should also do this as a number
> generator:
>
> dice 6  //would give randoms up to 6.
> dice 12 //would give randoms up to 12.

ok. Write a program to do that. You have the pieces

Bill Cunningham

unread,
Dec 5, 2009, 1:11:44 PM12/5/09
to

"Nick Keighley" <nick_keigh...@hotmail.com> wrote in message
news:782ce21c-6206-48d6...@19g2000vbq.googlegroups.com...

<snip>

> I think.

<snip>

<snip>

I think argv[1][0] would be char ** right?

Bill Cunningham

unread,
Dec 5, 2009, 1:12:44 PM12/5/09
to
Did I screw up again?

B


Thomas Stegen

unread,
Dec 5, 2009, 4:16:12 PM12/5/09
to
Bill Cunningham wrote:
> "Nick Keighley" <nick_keigh...@hotmail.com> wrote in message


>

>> I was going to try my hand at pointer arithmetic and
>> look at argv[1][0] and argv[1][1].
>
> which are of what type?
>
> <snip>
>
> I think argv[1][0] would be char ** right?
>

I am afraid not. Cast you mind to your original declaration of main for
context: int main(int argc, char *argv[])

So step by step I will you give you some leading questions. I'll also
give you the answers, but please try to understand why I am asking these
questions and why the answers are what they are.

What type is argv?


argv is of type char**.

So what type must *argv be?
*argv is of type char*.

Do you understand that *argv is the same as argv[0]? This is a central
part of the puzzle.

Essentially *(argv + 0) is the same as argv[0] and *(argv + 1) is the
same as argv[1].

Now, maybe take a break and digest all that. No point in moving on until
you get it :)

So now that we are ready to move on, what type is **argv?
It is of type char.

Remember how *(argv + 1) is the same as argv[1]? So *(*(argv + 1) + 0)
is the same as argv[1][0]?

Notice how each steps dereferences one step so to speak.

So argv[1][0] is of what type? Hint: the answer is above.

--
Thomas.

Thomas Stegen

unread,
Dec 5, 2009, 4:17:37 PM12/5/09
to
Bill Cunningham wrote:
> "Bill Cunningham" <nos...@nspam.invalid> wrote in message
> news:4b1a9943$0$5330$bbae...@news.suddenlink.net...
>> "Nick Keighley" <nick_keigh...@hotmail.com> wrote in message
>> news:86685865-733a-408b...@l13g2000yqb.googlegroups.com...
>>
>> Would this do what you want?
>>
>> if (argv[1][0] == 'a')
>
> Wait more what I woant come to think of it is
>
> if (argv[1][0]=='-' && argv[1][1]=='a')

Come to think of it, I would think so too :)

--
Thomas.

Bill Cunningham

unread,
Dec 5, 2009, 6:57:19 PM12/5/09
to

"Thomas Stegen" <thomas...@gmail.com> wrote in message
news:KMidncjAk6o9UIfW...@giganews.com...

> So argv[1][0] is of what type? Hint: the answer is above.

char right? I was getting confused I think because I know argv[] *can*
be the same as a pointer and can be treated like one. In other words char *.
And also there is a char * before argv[] so I was thinking char ** but I
guess it would be char when done with pointers.

Richard

unread,
Dec 6, 2009, 2:19:00 AM12/6/09
to
Nick Keighley <nick_keigh...@hotmail.com> writes:

Bad.

For something as simple as this call it what it is.

It would otherwise be like calling an integer that holds the number of
bottles of beer something like "myint".

Wouldn't numBeers be so much more readable?

Antoninus Twink

unread,
Dec 6, 2009, 5:41:14 AM12/6/09
to
On 6 Dec 2009 at 7:19, Richard wrote:
> Wouldn't numBeers be so much more readable?

Readable isn't often a word that springs to mind to describe a name in
camelcase.

Richard

unread,
Dec 6, 2009, 10:20:49 AM12/6/09
to
Antoninus Twink <nos...@nospam.invalid> writes:

Horses for (or should that be Camels) for courses. I personally find it
very readable. The nature of the upper case at word boundaries makes it
pretty obvious immediately where the names components are.

Nick Keighley

unread,
Dec 6, 2009, 6:26:37 PM12/6/09
to
On 6 Dec, 07:19, Richard <rgrd...@gmail.com> wrote:
> Nick Keighley <nick_keighley_nos...@hotmail.com> writes:
> > On 5 Dec, 17:20, Richard <rgrd...@gmail.com> wrote:
> >> Nick Keighley <nick_keighley_nos...@hotmail.com> writes:
>
> > <snip>
>
> >> > Would this do what you want?
>
> >> >     if (argv[1][0] == 'a')
>
> >> The first thing to do with non-trolls is to move away from argv.
>
> >> e.g char * ptrToCharArg=argv[1];
>
> > I usually call it arg
>
> >    char *arg = argv[1];
>
> >    if (arg[0] == 'a')
>
> Bad.
>
> For something as simple as this call it what it is.
>
> It would otherwise be like calling an integer that holds the number of
> bottles of beer something like "myint".
>
> Wouldn't numBeers be so much more readable?- Hide quoted text -

it's the current argument being processed. ptrToCharArg looks a bit
hungarian to me, I don't encode the type in the identifier.

Nick Keighley

unread,
Dec 6, 2009, 6:27:36 PM12/6/09
to

I use source bases that use both. You can get used to either.

0 new messages