Where to find the exact requirement of the operand for C operators?

L

linq936

Hi,
I just did the following test:


1:void main(void){
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp;
5: int d = p + pp;
6:}


I use GCC compiler and get the error and warning:

t2.c: In function `main':
t2.c:4: invalid operands to binary *
t2.c:5: warning: initialization makes integer from pointer without a
cast
t2.c:1: warning: return type of `main' is not `int'

You can see that operands in addition operation can be int* but not
in multiplication.

I checked my <<C programming language>>, it does not say anything on
operands. Is there any good web resource on such specification?
 
L

Lew Pitcher

Hi,
I just did the following test:

1:void main(void){
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp; [snip]
You can see that operands in addition operation can be int* but not
in multiplication.

What do you get when you multiply an address by an integer? Is the
result an address? An integer? Something else?
What does such a number represent?

Answer these questions, and you'll understand the meaning of the error
message and some of the limits of the operands of the binary
operations.

HTH
 
C

Christopher Benson-Manica

1:void main(void){
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp;
5: int d = p + pp;
6:}
t2.c: In function `main':
t2.c:4: invalid operands to binary *

n869, 6.5.5: "Each of the operands [to the multiplicative operators,
i.e. * and /] shall have arithmetic type." pp is a pointer and does
not have arithmetic type; your code exhibits a constraint violation.
t2.c:5: warning: initialization makes integer from pointer without a
cast

n869, 6.5.6: "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 integer type." Your code meets this constraint, but
the result of p+pp is a pointer, not an integer; hence the warning.
Additionally, pp+1 does not point to an object, although fortunately
for you a pointer may point one past the end of an array object, so
you are ok.
t2.c:1: warning: return type of `main' is not `int'

Do not ignore this warning.
I checked my <<C programming language>>, it does not say anything on
operands. Is there any good web resource on such specification?

Google for a copy of n869, which is a freely available draft of the
standard.
 
E

Eric Sosman

Lew Pitcher wrote On 05/07/07 14:35,:
Hi,
I just did the following test:

1:void main(void){
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp;
[snip]

You can see that operands in addition operation can be int* but not
in multiplication.


What do you get when you multiply an address by an integer? Is the
result an address? An integer? Something else?
What does such a number represent?

Answer these questions, and you'll understand the meaning of the error
message and some of the limits of the operands of the binary
operations.

For even more insight, frame your answers in terms of
a machine whose addresses look like "221B Baker Street,"
"1600 Pennsylvania Avenue," and "79 Wistful Vista."
 
M

Martin Ambuhl

Hi,
I just did the following test:


1:void main(void){
^^^^
after this inanity, nothing else matters.
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp;

What does it mean to multiply a pointer by an int? (hint: nothing
useful) Why would you store the result of pointer arithmetic in an int?
(hint: there is no reason)
5: int d = p + pp;

Why would you store the result of pointer arithmetic in an int? (hint:
there is no reason)
6:}


I use GCC compiler and get the error and warning:

t2.c: In function `main':
t2.c:4: invalid operands to binary *

Of course.
t2.c:5: warning: initialization makes integer from pointer without a
cast

Of course.
t2.c:1: warning: return type of `main' is not `int'

No kidding,
You can see that operands in addition operation can be int* but not
in multiplication.

I checked my <<C programming language>>, it does not say anything on
operands. Is there any good web resource on such specification?

Try turning your brain on.
 
R

Richard Tobin

What do you get when you multiply an address by an integer? Is the
result an address? An integer? Something else?
[/QUOTE]

Something else.

It represents the product of an address and an integer.
For even more insight, frame your answers in terms of
a machine whose addresses look like "221B Baker Street,"
"1600 Pennsylvania Avenue," and "79 Wistful Vista."

x = $221B Baker Street$ * 2
printf("half x is %p\n", x/2);

--> half x is $221B Baker Street$

-- Richard
 
K

Keith Thompson

Hi,
I just did the following test:


1:void main(void){
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp;
5: int d = p + pp;
6:}

Please don't add line numbers to code that you post here. They make
it difficult for us to copy-and-paste the code and try it ourselves.
It's not a big deal in this case, but it can be for bigger code
samples. If you need to correlate line numbers in error messages to
your code, you can indicate line numbers as comments.

The declaration "void main(void)" is incorrect. The main function
returns an int. If your textbook tells you otherwise, get a better
one. Your compiler even warned you about this, but you ignored the
warning. And since main returns an int, you should return an int;

int main(void)
{
/* ... */
return 0;
}

[...]
You can see that operands in addition operation can be int* but not
in multiplication.

I checked my <<C programming language>>, it does not say anything on
operands. Is there any good web resource on such specification?

Do you mean _The C Programming Language_ by Kernighan and Ritchie? If
so (and make sure you have the 2nd edition), I'm sure it does discuss
this. Look up "pointer arithmetic" in the index, or take a look at
the Appendix A, particularly the section on expressions.

(Incidentally, this is an excellent book -- and it *doesn't* use
"void main(void)".)

You can't multiply two pointers, or add two pointers, because it
doesn't make any sense to do so; the result wouldn't mean anything.
You can add a pointer to and integer, or vice versa; the result is a
pointer, offset from the original pointer value. See K&R2 for
details.
 
O

Old Wolf

Google for a copy of n869, which is a freely available draft of the
standard.

Also google for n1124, which is the actual standard text, with some
errata
combined in.

Interestingly, I looked at my copy of K&R, and the section 2.5 on
arithmetic operators does not say anything about operands, e.g.
it doesn't say that it is valid to add two integers. Nor does it say
that it is valid to multiply an integer and a pointer. the writers
seem to assume that the reader will know or glark the truth or
falsity of these things.

Operands are only mentioned in chapter 5 (Pointers) , where it
says that pointers and integers may be added.
 
E

Eric Sosman

Richard Tobin wrote On 05/07/07 16:54,:
Eric Sosman <[email protected]> wrote:

Actually, the >> material is by Lew Pitcher.
Something else.


It represents the product of an address and an integer.



x = $221B Baker Street$ * 2
printf("half x is %p\n", x/2);

--> half x is $221B Baker Street$

Interesting. How was `x' declared? ;-)
 
R

Richard Tobin

x = $221B Baker Street$ * 2
printf("half x is %p\n", x/2);

--> half x is $221B Baker Street$
[/QUOTE]
Interesting. How was `x' declared? ;-)

That part of the design has not been completed yet. In keeping with
C's inside-out declarations, we might have for example:

char *x/2;

indicating that x/2 is a char *.

-- Richard
 
K

Keith Thompson

Something else.

It represents the product of an address and an integer.
For even more insight, frame your answers in terms of
a machine whose addresses look like "221B Baker Street,"
"1600 Pennsylvania Avenue," and "79 Wistful Vista."

x = $221B Baker Street$ * 2
printf("half x is %p\n", x/2);

--> half x is $221B Baker Street$[/QUOTE]

Um, what language is that?

I think your point is that a C-like language could conceivably allow
addresses to be multiplied and divided by integers. You could even
compute the sine of a pointer; taking the cosine of the result would
presumably give you the original pointer value again.

The argument that (pointer * integer) is invalid because it can't
possibly make any sense is ironclad, because the language *could* have
defined such constructs.

The real answer to the OP's question is in (at least) two parts.

Q: Why is (pointer * integer) illegal?

A: Because the language standard says so (see section whatever, or any
decent textbook).

It's permissible just to stop here, but ...

Q: Why does the standard say so?

A: Because the authors of the standard decided, correctly IMHO, that
making it legal and defining its semantics would have been more
trouble than it's worth.

And for the truly stubborn (not necessarily referring to the OP) ...

Q: But I *want* to multiply a pointer by an integer; it makes sense to
me!

A: Why? Show us an example where such an operation actualy makes
sense, that can't be done more cleanly using C's existing
facilities. If you can present such an example (unlikely) and
convince the committee that supporting it is worth the burden on
all possible platforms (vanishingly unlikely), then such a feature
might be added to a future version of the standard, and you might
be able to rely on it being implemented in 10 or 20 years. Sorry,
that's just the way it is.

There's no real virtue in defining all possible operations for all
possible types. For each such operation, you have to define its
semantics in a way that can be implemented on any realistic
architecture. The C standard is deliberately designed so it's not
restricted to architectures where pointers happen to look and act
like integers; this makes things like (pointer * integer) difficult
to define in such a way that the result makes sense other than as
an operand to a later operation that reverses its effect.
 
R

Richard Heathfield

Keith Thompson said:

I think your point is that a C-like language could conceivably allow
addresses to be multiplied and divided by integers. You could even
compute the sine of a pointer; taking the cosine of the result would
presumably give you the original pointer value again.

They must do trig very differently in the USA...

<snip>
 
R

Richard Tobin

Keith Thompson said:
The argument that (pointer * integer) is invalid because it can't
possibly make any sense is ironclad, because the language *could* have
defined such constructs.

Did you mean the opposite of that?
Q: But I *want* to multiply a pointer by an integer; it makes sense to
me! [...]
There's no real virtue in defining all possible operations for all
possible types. For each such operation, you have to define its
semantics in a way that can be implemented on any realistic
architecture. The C standard is deliberately designed so it's not
restricted to architectures where pointers happen to look and act
like integers; this makes things like (pointer * integer) difficult
to define in such a way that the result makes sense other than as
an operand to a later operation that reverses its effect.

Of course I'm not seriously suggesting this, but... I don't think it
would be difficult in cases where it makes sense. Sure, adding two
pointers to different objects then dividing by two to get the average
would not work on machines where each object has an address with a
different segment part, but then that operation doesn't make sense
anyway. But doing it with two pointers into the same array *does*
make sense - it's the sort of operation used in a binary search - and
would be no harder to implement than the things that already have to
work, such as array indexing. Combining pointers to different objects
(e.g adding them then subtracting one of them off again. as a rather
poor way to switch between objects) would require the "sum of two
pointers" type to be some kind of compound object internally, but
that's what you get for using a segmented architecture.

-- Richard
 
K

Keith Thompson

Did you mean the opposite of that?

Yes, I did; I meant to write that the argument is *not* ironclad. (I
re-worded that sentence several times; I should have checked it more
carefully.)

[snip]
 
T

Thad Smith

Martin said:
^^^^
after this inanity, nothing else matters.

That is overstated. In a freestanding environment for a program that
never terminates that is an acceptable and common declaration for the
program entry point. In that case void is the return type that makes
the most sense. For hosted programs, main should either return an int
or conform to an implementation-defined type.
 
R

Rudolf

Thad Smith said:
That is overstated. In a freestanding environment for a program that
never terminates that is an acceptable and common declaration for the
program entry point. In that case void is the return type that makes
the most sense. For hosted programs, main should either return an int
or conform to an implementation-defined type.

I'm curious: what about for a hosted program that never terminates?
 
J

Jack Klein

Lew Pitcher wrote On 05/07/07 14:35,:
Hi,
I just did the following test:

1:void main(void){
2: int p = 1;
3: int* pp = &p;
4: int c = p * pp;
[snip]

You can see that operands in addition operation can be int* but not
in multiplication.


What do you get when you multiply an address by an integer? Is the
result an address? An integer? Something else?
What does such a number represent?

Answer these questions, and you'll understand the meaning of the error
message and some of the limits of the operands of the binary
operations.

For even more insight, frame your answers in terms of
a machine whose addresses look like "221B Baker Street,"
"1600 Pennsylvania Avenue," and "79 Wistful Vista."

You misspelled "Wasteful" in the last address...

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
R

Richard Heathfield

Rudolf said:
I'm curious: what about for a hosted program that never terminates?

No such program has ever run to completion, so the point is moot. But in
any case, the behaviour of such a program would be undefined, whether
or not it terminates.
 
E

Eric Sosman

Keith said:
The argument that (pointer * integer) is invalid because it can't
possibly make any sense is ironclad, because the language *could* have
defined such constructs. [...]

("Is ironclad" corrected to "is not ironclad" elsethread.)

It's not hard to imagine a formal underpinning for pointers
that would allow multiplication by an integer, or even by a
floating-point number. By thinking of a pointer as a vector --
and really now, what could be more natural? -- we can even get
multiplication of two pointer operands in at least two different
ways, corresponding to dot-product and cross-product.

But C's pointers aren't vectors: they are more abstract.
There are a few hints that pointers might be "addresses" (the
unary `&' operator is referred to as "address-of") and that
addresses might have some properties of numbers (alignment is
defined in terms of "multiples" of an address), but by and large
the C language avoids nailing down the nature of a pointer any
more than it must. A wise choice, because (1) there is little
use for the inverse or for the square root of a pointer, and
(2) being unnecessarily specific risks becoming obsolete.

By declining to define "unnecessary" operations on pointers
today, C leaves open the possibility of providing definitions
for them tomorrow when more is known about what might be useful.
Someday (mark my words!) we will discover that it is handy to
think of pointers as complex numbers, or as matrices, or as
quaternions -- and when that day comes, C will be free to add
new properties to pointer arithmetic without worrying about
changing old properties and breaking old code.

Prediction: When pointers are understood as indefinite
integrals, someone will try to read them with gets().
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top