Why multiplication not allowed?

  • Thread starter Vijay Kumar R Zanvar
  • Start date
S

Sean Kenwrick

Joona I Palaste said:
Are you testing our knowledge? The C tokeniser thinks of the /* as the
start of a comment, so it ends up being:
*k = *k
which is a syntax error because the lack of a terminating semicolon.
Were you thinking of using it in some way like this?
*k = *k/*j; /* make sure the value of *k stays in bounds */
+0; /* this is just a dummy */

Yeah you got it. By dividing *k by *j (without spaces) you get a syntax
error.

*k=*k/*j;

you get a syntax error because the /* starts a comment. I was given this
as a question in an interview for a job when I was a student (and I didn't
get the question right (or the job!)).

But I think the reason I didn't get the job was because one of the other
questions the interviewer asked me was to tell him what was wrong with the
following statement:

i=+i;

I said that there was nothing wrong with it, but the interviewer claimed
that it was an ambiguous statement because it could mean adding i to itselt
or setting i to +i. I got into an argument with him saying that he must
be confused with i+=i; but he was adament he was right and got annoyed that
I was disagreeing wih him.

Afterwards I wondered whether this might have been some kind of syntax left
over from a very early incarnation of C which was subsequently dropped.
Perhaps the members of this group could enlighten me about this since I
think that this guy was just a complete idiot.

The last question he asked was for me to declare a pointer to a funtion that
returned a pointer to a function that returned a pointer to a char.
Needless to say, without my K&R book to hand I messed that up as well (but
by now I got the feeling that this guy was just being mean).

In the end they gave the job to a female friend of mine who by her own
admission was not a great programmer (she got me to do all her programming
assignments in return for her doing all my essay assignments).

Sean
 
J

Joona I Palaste

Sean Kenwrick said:
But I think the reason I didn't get the job was because one of the other
questions the interviewer asked me was to tell him what was wrong with the
following statement:

I said that there was nothing wrong with it, but the interviewer claimed
that it was an ambiguous statement because it could mean adding i to itselt
or setting i to +i. I got into an argument with him saying that he must
be confused with i+=i; but he was adament he was right and got annoyed that
I was disagreeing wih him.
Afterwards I wondered whether this might have been some kind of syntax left
over from a very early incarnation of C which was subsequently dropped.
Perhaps the members of this group could enlighten me about this since I
think that this guy was just a complete idiot.

Yes, this is an obsolete feature of C. =+ and =- originally meant the
same as += and -=. Whoever designed them that way must have been
drinking something really strong. AFAIK they were dropped when ISO
standardised C.
That the interviewer still clung to the obsolete meanings of those
operators makes me feel that he wasn't the proper person to interview
you about C.

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"Parthenogenetic procreation in humans will result in the founding of a new
religion."
- John Nordberg
 
L

Lew Pitcher

Sean Kenwrick wrote:
[snip]
But I think the reason I didn't get the job was because one of the other
questions the interviewer asked me was to tell him what was wrong with the
following statement:

i=+i;

I said that there was nothing wrong with it, but the interviewer claimed
that it was an ambiguous statement because it could mean adding i to itselt
or setting i to +i. I got into an argument with him saying that he must
be confused with i+=i; but he was adament he was right and got annoyed that
I was disagreeing wih him.

Afterwards I wondered whether this might have been some kind of syntax left
over from a very early incarnation of C which was subsequently dropped.
Perhaps the members of this group could enlighten me about this since I
think that this guy was just a complete idiot.

ISTR an article by one of the original C developers (Dennis Ritchie or
perhap PJ Plauger) commenting on the /very/ early syntax of C. Specifically,
the article said that the syntax

i =+ j;

had been considered as a way to express

i = i + j;

but was ultimately rejected because it was ambigious, and could be confused with

i = j;

If I read http://cm.bell-labs.com/cm/cs/who/dmr/chist.html correctly, it
looks like this ambigious syntax was adopted from B into the earliest of C
compilers, but later dropped (in 1976) before the adoption of "K&R C".

[snip]
 
R

Richard Heathfield

Sean Kenwrick wrote:

the interviewer asked me was to tell him what was wrong with the
following statement:

i=+i;

I said that there was nothing wrong with it, but the interviewer claimed
that it was an ambiguous statement because it could mean adding i to
itselt
or setting i to +i. I got into an argument with him saying that he must
be confused with i+=i; but he was adament he was right and got annoyed
that I was disagreeing wih him.

Getting into an argument is unwise. Personally, even if I hadn't known about
this particular gotcha, I'd possibly have weaseled my way through it,
because the first complaint I'd have made would have been about the absence
of whitespace. I then would have explained why whitespace is important.
Afterwards I wondered whether this might have been some kind of syntax
left over from a very early incarnation of C which was subsequently
dropped.

Precisely so. =+ is the old way of writing +=
The last question he asked was for me to declare a pointer to a funtion
that returned a pointer to a function that returned a pointer to a char.

Build up logically. We need a return value that is a pointer to a function
that returns a pointer to a char:

typedef char * (*pfrc)();

With that typedef, the solution becomes easy:

pfrc (*solution)();
 
A

August Derleth

Joona said:
Yes, this is an obsolete feature of C. =+ and =- originally meant the
same as += and -=.

And =* meant the same as *=, which made expressions like
x=*p;
needlessly ambiguous. splint, the lint-like program I use for laughs,
still complains about things stemming from that wart.
Whoever designed them that way must have been
drinking something really strong.

Indeed.
 
A

Alan Balmer

The way I reason is like this: If I take i and assign an address to it
(that is, I make it a pointer), i is the name of a block of memory that
holds a certain string of bits or trits or decimal digits that compose
that address. At this layer of abstraction, it's no different from an
int or a float. Since I can multiply two ints and stand a good chance at
getting a meaningful result, why not two pointers? Or an int and a pointer?

You didn't answer the question. What meaning would you ascribe to the
result of the operation?
 
C

Clark Cox

While I've never felt an urge to multiply pointers, there
is a situation where adding them is quite legitimate:
char *rcopy, *q, *r;
. . .
strcpy(rcopy, r);
q = index(r, '*');
. . .
/* Now point to the '*' in the copy */
foobar(rcopy + q - r);
(Please don't write in to tell me I forgot to allocate space for rcopy, etc.
This is just a minimal illustration of the point.)

Although the intermediate expression (rcopy + q) has the illegal form
of (ptr + ptr) the net expression is OK.

If the intermediate expression is illegal, then the whole expression is
illegal. Period.
I was disappointed when gcc rejected my construction like this, depending
on how I parenthesized it. It seems like it shouldn't be hard to support.

Yes, yes; the better parenthesization would also make the program more
readable. Well nevermind ....

Adding pointers is still meaningless. What you're trying to do in
this situation is get the difference of two pointers, and add that
difference to another pointer. What you want is:

rcopy + (q - r)

Which is not ptr + ptr, it is ptr + ptrdiff. The better parenthesized
version is not just "more readable", it is legal.
 
C

CBFalconer

Sean said:
.... snip ...

But I think the reason I didn't get the job was because one of the
other questions the interviewer asked me was to tell him what was
wrong with the following statement:

i=+i;

I said that there was nothing wrong with it, but the interviewer
claimed that it was an ambiguous statement because it could mean
adding i to itselt or setting i to +i. I got into an argument
with him saying that he must be confused with i+=i; but he was
adament he was right and got annoyed that I was disagreeing wih him.

Afterwards I wondered whether this might have been some kind of
syntax left over from a very early incarnation of C which was
subsequently dropped. Perhaps the members of this group could
enlighten me about this since I think that this guy was just a
complete idiot.

You've got it. He had just been around from pre-standardization
days. Note that proper civilized use of blanks untangles
everything.
 
M

Martin Dickopp

Richard Heathfield said:
Build up logically. We need a return value that is a pointer to a function
that returns a pointer to a char:

typedef char * (*pfrc)();

With that typedef, the solution becomes easy:

pfrc (*solution)();

It's also easy without a helper type if you read (or build up) the
declaration "from inside to outside" instead of from left to right:

p The identifier `p'...
*p ...is a pointer...
(*p) () ...to a function...
*(*p) () ...which returns a pointer...
(*(*p) ()) () ...to a function...
*(*(*p) ()) () ...which returns a pointer...
char *(*(*p) ()) (); ...to `char'.

Martin
 
K

Kevin Goodsell

August said:
The way I reason is like this: If I take i and assign an address to it
(that is, I make it a pointer), i is the name of a block of memory that
holds a certain string of bits or trits or decimal digits that compose
that address. At this layer of abstraction, it's no different from an
int or a float. Since I can multiply two ints and stand a good chance at
getting a meaningful result, why not two pointers? Or an int and a pointer?

Because the result is *not* meaningful for pointers.
My response to this is that the compiler shouldn't hold my hand that
much. As Kernighan said, "If you want PL/I, you know where to get it."
In Forth, for example, a pointer is simply a bunch of bits on the stack,
and you can do unto a pointer the same as you can do unto an int or
anything else. The only extra feature is that, if you dereference it,
you stand a good chance of getting something meaningful.

I suppose if I want Forth, I know where to find it.

All I can say to this is that I'm glad you didn't design C.

You might also be interested in BCPL. I know almost nothing about it,
but I believe I read that it only had 1 type: the machine word. I
imagine this would give you the kind of complete freedom from
hand-holding that you seem to want. (It's also possible that the
language I'm thinking of is B, not BCPL.)

-Kevin
 
K

Kevin Goodsell

Flash said:
It's not holding your hand, it's just not providing something that makes
no sense. You can always side-step the limitation by casting the
pointers to long long and multiplying them, although there is no
guarantee that they will actually fit in to a long long.

FYI, there is a guarantee in C99 that an object pointer will fit in a
intptr_t, if that type is provided.

-Kevin
 
A

Arthur J. O'Dwyer

Because the result is *not* meaningful for pointers.

Moreover, the *operation* is not [yet] meaningful for pointers.
When August says that he can "multiply" two integers, that means: treat
the bits as a positional notation with this bit equal to 1, this bit
equal to 8, etc., and carry out multiplication in the grade-school
longhand format. When August says he can "multiply" two floats, that
means: treat this set of bits as one positional number, this set of
bits as an exponent, add a 1 to the front, add the exponents, carry
out longhand multiplication on the other bits, and store the result back
in the old format.
These are two *very* *different* operations at the machine level.
Yet at the "conceptual" level, they go by the same name.
August proposes to make a new operation on pointers, also going by
the name "multiplication," but he hasn't told us the machine-level
meaning of the new operation. What is the computer supposed to *do*
with these bits?


I'd say the compiler wasn't holding your hand at all. Maybe some
languages go to the effort of setting up a framework in which it is
possible to "multiply" pointers. C doesn't bother. If you want to
assign semantics to the expression 'p*q', you can jolly well do it
yourself, says C.

All I can say to this is that I'm glad you didn't design C.

You might also be interested in BCPL. I know almost nothing about it,
but I believe I read that it only had 1 type: the machine word. I
imagine this would give you the kind of complete freedom from
hand-holding that you seem to want. (It's also possible that the
language I'm thinking of is B, not BCPL.)

Both. BCPL came before B, but B didn't add any type-checking to the
root language as far as I know.

<Blatant plug> You can multiply "pointers" in Day-9, too; it's actually
much more similar to the BCPL described here
http://www.lysator.liu.se/c/msb-on-b.html
than I'd previously realized. I like the idea of floating-point
operators, too...
http://www.geocities.com/arthur_odwyer/day9/
</plug>

-Arthur
 
K

Keith Thompson

August Derleth said:
Kevin Goodsell wrote: [...]
The question Ben is asking is, what would you propose pointer
multiplication do? How would you define the operation? I can't think
of any way in which multiplying a pointer by any other value would
be useful or even meaningful.

The way I reason is like this: If I take i and assign an address to it
(that is, I make it a pointer), i is the name of a block of memory
that holds a certain string of bits or trits or decimal digits that
compose that address. At this layer of abstraction, it's no different
from an int or a float. Since I can multiply two ints and stand a good
chance at getting a meaningful result, why not two pointers? Or an int
and a pointer?

Because you *can't* multiply two pointers, or an int and a pointer,
and stand a chance at getting a meaningful result.

Pointers are not integers. Pointer arithmetic in C is not defined in
terms of treating the bit patterns composing the pointer values as
integers and performing integer arithmetic on them; it's defined in
terms of what object the resulting pointer value points to.

For example, if p is a pointer, the machine-level operations that are
performed to evaluate the expression (p + 4) depend on the type of p.
If p is a char*, (p + 4) points to a location 4 bytes "after" the
location pointed to by p; if p is an int*, (p + 4) points
4*sizeof(int) bytes "after" the location pointed to by p. If p is a
void*, the expression (p + 4) is illegal (though some compilers may
support it as a language extension (unwisely, IMHO)).

Another example: On Cray vector machines, a machine address points to
a 64-bit word. The C compiler implements 8-bit chars (CHAR_BIT == 8)
by "cheating" a little. (I put the word "cheating" in quotation marks
because what the C compiler does is perfectly legitimate; it just
doesn't map directly to the underlying hardware.) A char* is
implemented as a word address with a byte offset kludged into the
high-order 3 bits. (I actually don't know how much hardware support
there is for this format.) Multiplying two such pointers makes as
much sense as taking the square root of a struct.

If, for some reason, you want to treat the contents of two pointers as
if they were integers, multiply them, and store the resuting integer
bit pattern into a pointer, you can do so. I don't think a cast from
a pointer to an integer of the appropriate size, or vice versa, is
guaranteed to just copy the bits, but it probably does so on most or
all implementations. If you're concerned about that, you can use
memcpy(), which is guaranteed to copy the bits. Using explicit
conversions, you can multiply two pointers (treating the pointers' bit
patterns as integers and treating the resulting integer bit pattern as
a pointer) as easily as you can take the square root of a struct
(treating the struct's bit pattern as a double). The compiler won't
hold your hand while you do this, but it won't stop you. Of course,
you'll invoke undefined behavior, and I can't think of any possible
use for the result.
 
K

Keith Thompson

Joona I Palaste said:
Yes, this is an obsolete feature of C. =+ and =- originally meant the
same as += and -=. Whoever designed them that way must have been
drinking something really strong. AFAIK they were dropped when ISO
standardised C.
That the interviewer still clung to the obsolete meanings of those
operators makes me feel that he wasn't the proper person to interview
you about C.

The =+ syntax was dropped long before ISO C; it had vanished by the
time K&R1 was published.

Not many years ago, I used a compiler (VAXC, I think) that allowed the
old =+ syntax, but I think it at least issued a warning about it. (It
also helpfully "corrected" the unrecognized "signed" keyword to
"unsigned".) The oldest C compiler I now have access to (circa 1988)
just treats =+ as a syntax error.

What's really wrong with the statement is that it lacks whitespace and
doesn't do anything useful.
 
C

Christopher Benson-Manica

Keith Thompson said:
Because you *can't* multiply two pointers, or an int and a pointer,
and stand a chance at getting a meaningful result.

True enough. But let me suggest something, assuming I don't make a
mistake in my reasoning before doing so.

If p is a pointer pointing to a memory region of sufficient size,

(p+5)==(p+5*sizeof(*p))

right? Likewise for p-5. Then (I suggest),

(p*5)==(5*sizeof(*p))

would be sensible. Not needed, but meaningful, yes?
 
J

Jeremy Yallop

Christopher said:
True enough. But let me suggest something, assuming I don't make a
mistake in my reasoning before doing so.

If p is a pointer pointing to a memory region of sufficient size,

(p+5)==(p+5*sizeof(*p))

right?

No. However,

(char *)(p + 5) == (char *)p + 5 * sizeof *p
Likewise for p-5. Then (I suggest),

(p*5)==(5*sizeof(*p))

would be sensible. Not needed, but meaningful, yes?

It doesn't seem particularly meaningful to me and I don't see why you
think it follows from your first example. Why does `p' change into
'sizeof(*p)' as the operand of binary '*'?

Jeremy.
 
K

Kevin Goodsell

Keith said:
The =+ syntax was dropped long before ISO C; it had vanished by the
time K&R1 was published.

Yes, my copy of K&R1 has this listed near the end of the Reference
Manual (appendix A) under "Anachronisms". There is only one other thing
listed in this section: An initialization syntax that looks like this

int x 1;

instead of

int x = 1;

This is an aspect of "old C" that I've never heard mentioned anywhere else.

-Kevin
 
F

Flash Gordon

FYI, there is a guarantee in C99 that an object pointer will fit in a
intptr_t, if that type is provided.

However, if it does not mandate the provision of intptr_t then it does
not help :)
 
K

Kevin Goodsell

Flash said:
However, if it does not mandate the provision of intptr_t then it does
not help :)

I *thought* that it required intptr_t on implementations that have a
wide enough integer type, but I didn't see this requirement when I
checked the (draft) standard earlier today. I may have confused it with
the exact-width integer types, a few of which are required if and only
if the implementation has integer types of the appropriate sizes.

Optional types are of somewhat questionable usefulness. Code intended to
be strictly portable obviously can't use them. On the other hand, before
the introduction of these types implementations were already free to
choose whether or not to support things like an integer type that can
store a pointer value without loss, or an integer with exactly 32 bits.
Code which relied on things like these was already non-portable - these
types actually provide a way to make it /more/ portable (though still
not fully portable) because there's no question about which type to
choose. You /know/ that the appropriate 32-bit type is int32_t, so you
don't have to try to guess whether it will be int or long.

It also allows non-portable code to fail at compile time rather than
being broken at run-time if the implementation can't properly support it.

-Kevin
 
K

Keith Thompson

Christopher Benson-Manica said:
True enough. But let me suggest something, assuming I don't make a
mistake in my reasoning before doing so.

If p is a pointer pointing to a memory region of sufficient size,

(p+5)==(p+5*sizeof(*p))

right? Likewise for p-5. Then (I suggest),

Um, no. If I understand what you're trying to say, the "+" on the
left side indicates pointer arithmetic as defined by C, and the "+" on
the right side indicates a different kind of pointer arithmetic that
counts by bytes, not by whatever object type p points to.

Note that, if both "+" operators meant the same thing, and the
expression were treated as a mathematical equation, you could subtract
p from each side and divide by 5, yielding 1 == sizeof(*p). And in
fact your original expression is true if and only if sizeof(*p) == 1
(assuming that p+5 is a valid pointer).

The correct way to express what you're trying to say (assuming that p
is a pointer to FOO, and assuming that FOO is an object type) is
something like this:

p+5 == (FOO*)((char*)p + 5*sizeof(*p))
(p*5)==(5*sizeof(*p))

would be sensible. Not needed, but meaningful, yes?

I don't think so. It looks like you're trying to take your original
equation and replace "+" with "*", but you quietly dropped the "p+" on
the right hand side. (Or maybe I misunderstood your derivation.) In
any case, making a pointer value decay to the size of what it points
to if it's the operand of a multiplication operator (and not if it's
the operand of an addition or subtraction operator) seems
counterintuitive and not terribly useful. The language doesn't need
another way to say 5*sizeof(*p) that badly.
 

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

Forum statistics

Threads
474,137
Messages
2,570,797
Members
47,342
Latest member
eixataze

Latest Threads

Top