historical question, C unary operators

M

mathog

C has a very small number of unary operators that change the value of
the variable they operate on. (What is the technical name for unary
operators that do this?) These are:

i++, ++i, i--, --i

Most unary operators in C do not change the value of the variable, like:

result = 1 + -var;
if(!var){

Anyway, does anybody know historically why they went with ++ for
increment instead of using a more general and extensible form like

<variable><unary indicator><operator> postfix form
<operator><unary indicator><variable> prefix form

where if "@" had indicated unary operators of this type, then "postfix
increment" would have been:

i@+

???

This came up in the context of a discussion on C99 bool, where the
expected "in place" unary operator "!!" is not available because

!!var

already has a meaning in C (and one that does not change the value of
var), leaving no space for an "in place" unary variant that would have
negated the value of var. Had the language employed an extensible form
then when C99 came along with the bool type it would have been simple to
add:

!@var;

equivalent to

var != var;

Thanks,

David Mathog
 
S

Stefan Ram

mathog said:
!!var
!@var

»@« means having to add meaningless garbage in 99 % of the cases
just to save a single characters in 1 % of the cases
(»!!@v« instead of
»v=!!v«).

In some languages there really is an »@«. It's call »apply«, e.g.:

APPLY f,x
 
T

Thomas Richter

C has a very small number of unary operators that change the value of
the variable they operate on. (What is the technical name for unary
operators that do this?) These are:

i++, ++i, i--, --i
Anyway, does anybody know historically why they went with ++ for
increment instead of using a more general and extensible form

To my very knowledge, the reason why ++ and -- were added to the
language was mostly because these operations were supported by the
hardware platform (IIRC, a PDP) C was first written for. So for example,
an expression like "*p++ = j" translates directly to one single
instruction on a PDP to my knowledge. (For the 68K, this would be a
"move.x dx,(ax)+", simply). There is no hardware shortcut for anything
else, i.e. not for !!, ^^, ** or //, so the operators did not became
part of C. The syntax pretty much expressed the "high level assembly"
approach C took.

Probably others may comment whether my speculations are correct.

So long,
Thomas
 
K

Kaz Kylheku

C has a very small number of unary operators that change the value of
the variable they operate on. (What is the technical name for unary
operators that do this?)

"munary": mutating unary.

Just kidding.
i++, ++i, i--, --i

Only in ++i and --i are the operators called unary. In i-- and i++,
the operator is called a postfix operator, not unary. Postfix + and -
do not exist: i+; and i-; are syntax errors.
Anyway, does anybody know historically why they went with ++ for
increment instead of using a more general and extensible form like

<variable><unary indicator><operator> postfix form
<operator><unary indicator><variable> prefix form

I think you might mean "destructive indicator". (You wouldn't rewrite the unary
minus -x as -@x right? Only --x as -@x, surely.)
where if "@" had indicated unary operators of this type, then "postfix
increment" would have been:

i@+

As an aside, the @ character does not occur in C; which is why Objective C is
able to use it to denote extensions without breaking compatibility with C.

In early versions of C (B, NB?) ++ was separate tokens, so it was possible
to write i + +.

Floating point + was written #+. So there was some of this kind of prefixing
going on; the trend obviously was to remove it.

It was not in their taste to have that kind of thing going on.
This came up in the context of a discussion on C99 bool, where the
expected "in place" unary operator "!!" is not available because

Expected? By whom? Never occured to me, for one.

Flipping a value is rare compared to incrementing.

Do you expect x to be flipped to its reciprocal by //x?

According to this pattern, --x should flip x to its additive inverse,
rather than decrement it. That is what would relate the meaning of
--x to the unary -x. And of course ++x should do nothing because +x does nothing.

So the idea that !!x toggles x is not consistent with --x or ++x in any way
other than the very weak idea that a double-character operator modifes the
operand in some way which is related to what the single-character unary
operator does.

Basically, Ritchie assigned the doubled-up tokens in ways that were
semantically sensible rather than playing up to some "extensible" lexical
consistencies. He didn't think too much, which is why he gave & a high
precedence and && a low precedence.

The C language is not extensible. You can't write your own operators without
hacking the compiler.

If you want really extensible operators, playing little games with characters
in the tokens isn't a good way to achieve it.
 
E

Eric Sosman

C has a very small number of unary operators that change the value of
the variable they operate on. (What is the technical name for unary
operators that do this?) These are:

i++, ++i, i--, --i

Most unary operators in C do not change the value of the variable, like:

result = 1 + -var;
if(!var){

Furthermore, most binary operators do not change the value of
any operand, the exceptions being = and op=.

Still more furthermore more, most ternary operators do not
change the value of any operand.

Summarizing: "Most operators leave their operands alone, but a
few may alter them." Are you uncomfortable with that?
Anyway, does anybody know historically why they went with ++ for
increment instead of using a more general and extensible form like

<variable><unary indicator><operator> postfix form
<operator><unary indicator><variable> prefix form

where if "@" had indicated unary operators of this type, then "postfix
increment" would have been:

i@+

Okay, what should @% do?

For ++ and -- there are fairly natural ideas about what the
implied missing operand could be. In English we even have special
words for these ideas: "next" and "previous," or "successor" and
"predecessor." What's the corresponding natural notion for %?

Ooh, even better: What should @* do as a *prefix* operator?
The prefix * means "my operand is a pointer; follow it to the
pointee," so @* ought to mean "...and then assign the pointee's
value to my operand." But you can't assign a T value to a T*
variable, so @*ptr would have to mean "issue a diagnostic."
Which, in fact, it already does -- so your wish is granted!
 
E

Eric Sosman

[...]
To my very knowledge, the reason why ++ and -- were added to the
language was mostly because these operations were supported by the
hardware platform (IIRC, a PDP) C was first written for. [...]

Somebody with the initials DMR disagrees with you. He's not in
a position to contradict you at this moment, but you can find out for
yourself that he has already done so. Search for an article called
"The Development of the C Language" and within that article look for
the text string "PDP-11". GIYF.
 
M

mathog

Eric said:
Summarizing: "Most operators leave their operands alone, but a
few may alter them." Are you uncomfortable with that?

Sure.

All languages have at least one assignment operator, why did C need
more? C already had a way to write "increment" using only one instance
of the variable:

i+=1;

so why invent

i++;

which saves a grand total of one character?

Letting ++ and -- change the value of its operand was not purely a
blessing, it made it relatively easy to write indeterminate code, as in:

i=i++;

and these used to be a real plague before the compilers became smart
enough to catch code like that.

Did K or R ever explain what the problem was they were addressing that
led them to add to the languge ++ and -- not just as unary
increment/decrement, but also changing the operand's value? The one
thing I can think of that might have induced them to do so was that it
made it possible to use while() and do/while() in instances where
otherwise for() would have been needed, like:

while(*ptr++){

instead of

for(; *ptr; ptr+=1){

The first form is more compact, but of course they do the same thing.

Regards,

David Mathog
 
R

Richard Damon

Sure.

All languages have at least one assignment operator, why did C need
more? C already had a way to write "increment" using only one instance
of the variable:

i+=1;

so why invent

i++;

which saves a grand total of one character?

Letting ++ and -- change the value of its operand was not purely a
blessing, it made it relatively easy to write indeterminate code, as in:

i=i++;

and these used to be a real plague before the compilers became smart
enough to catch code like that.

Did K or R ever explain what the problem was they were addressing that
led them to add to the languge ++ and -- not just as unary
increment/decrement, but also changing the operand's value? The one
thing I can think of that might have induced them to do so was that it
made it possible to use while() and do/while() in instances where
otherwise for() would have been needed, like:

while(*ptr++){

instead of

for(; *ptr; ptr+=1){

The first form is more compact, but of course they do the same thing.

Regards,

David Mathog

i+=1 and i++ are NOT equivalent if you are using the value of to expression.

A common use if this would be something like

*(ptr++) = chr;

which puts the character into the current location in the buffer and
then increments the index. This may be more efficient than

*ptr = chr;
ptr += i;

in that the first give the compiler the hint that it might want to use
an automatic post increment instruction, while the second requires the
compiler to figure this out itself (early compilers did not always do a
great job of optimizing).

You could not use

*(ptr += 1) = chr;

as that stores chr in the wrong place.

If the original code was *++ptr = chr; then you could do this, but that
requires (typically) initializing ptr to one place before the beginning
of your buffer, which was not promised to be creatable as a pointer.
 
B

Ben Pfaff

mathog said:
All languages have at least one assignment operator, why did C need
more? C already had a way to write "increment" using only one instance
of the variable:

i+=1;

so why invent

i++;

which saves a grand total of one character?

i+=1 and i++ have different values. This can be significant when
one of them is incorporated into a larger expression.

On the other hand, I can't think of many significant difference
between i+=1 and ++i. Spelling is one. Precedence is another:
in some contexts, i+=1 would require parentheses but i++ would
not.

Many coding styles put spaces around binary operators, so that
i++ saves three characters over "i += 1".
 
S

Stefan Ram

mathog said:
so why invent
i++;
which saves a grand total of one character?

»++i« is easier to comprehend (more readable), because it
confirms with the two word sentence »increment i«. More
words require more brain spaces and thus less fits in.
Read:

http://en.wikipedia.org/wiki/Working_memory#Capacity
http://en.wikipedia.org/wiki/Chunking_(psychology)
http://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two

»Remember: programming languages exist for humans to
read and understand easier, not for machines.«

http://blog.jovan-s.com/2009/07/23/there-are-no-reasons-to-not-follow-coding-standards/

»Code is for humans. Code is written once, read many times.«

http://idldoc.idldev.com/attachment/wiki/DeveloperInfo/styleguide.pdf?format=raw

»[A] program is a paper in a formal language written /for
humans/ to read.«

http://cs.wellesley.edu/~cs249/Resources/coding-standard.html

»Write the code /for humans/ to read and understand easily.«

http://particletree.com/features/successful-strategies-for-commenting-code/
 
B

Ben Bacarisse

Scott Fluhrer said:
Eric Sosman said:
[...] But you can't assign a T value to a T*
variable, so @*ptr would have to mean "issue a diagnostic."
/* From the Nits-R-Us department */
int main(void) {
void (*var)(void) = 0;

var = *var; /* Hey! No diagnostics! */
return 0;
}
/* Admittedly, that line, while legal, wasn't that useful... :) */

From the under-janitor in that department...

var = *var

does not attempt to assign a T value to a T* variable :)
 
E

Eric Sosman

Sure.

All languages have at least one assignment operator, why did C need
more? C already had a way to write "increment" using only one instance
of the variable:

i+=1;

If you're comfortable with the escalation from = as the only
assignment operator to a C with seven such operators (=, +=, -=,
*=, /=, %=, <<=, >>=), it seems strange that adding four more
(++, --, ++, --) would cause discomfort. (Besides, these four
are not "assignment" operators.)

Also, didn't you suggest that something like @op would have
been a better choice, allowing the introduction of even more
"assignment" operators?
so why invent

i++;

which saves a grand total of one character?

For one thing, the effect of `x = i++' and `x = i += 1' is
noticeably different. To get the effect of the former, you'd need to
write something like `x = i, i += 1' and the "grand total" comes
up short.

For another, consider expressions with multiple operators, where
precedence comes into play (I'll stick with prefix versions to avoid
the point already raised):

x = ++i * r;
x = i += 1 * r;

To fix the second, you'd need to add a set of parentheses:

x = (i += 1) * r;

.... and again, the "grand total" understates the actuality.
Letting ++ and -- change the value of its operand was not purely a
blessing, it made it relatively easy to write indeterminate code, as in:

i=i++;

and these used to be a real plague before the compilers became smart
enough to catch code like that.

Have you considered `i = i = i = i'? No increments or decrements
or anything of the kind, yet the behavior is nonetheless undefined.
I don't think you can blame U.B. on auto-increment and auto-decrement.
Did K or R ever explain what the problem was they were addressing that
led them to add to the languge ++ and -- not just as unary
increment/decrement, but also changing the operand's value?

It was T, actually. The paper has been cited elsethread, but
it doesn't say much about motivation. K&R describe the operators
as "more concise and often more efficient;" the efficiency claim is
now badly dated, but conciseness remains.
The one
thing I can think of that might have induced them to do so was that it
made it possible to use while() and do/while() in instances where
otherwise for() would have been needed, like:

while(*ptr++){

instead of

for(; *ptr; ptr+=1){

The first form is more compact, but of course they do the same thing.

They do *not* do the same thing. Is it time to reacquaint
yourself with your C textbook?
 
E

Eric Sosman

Sure.

All languages have at least one assignment operator, why did C need
more? C already had a way to write "increment" using only one instance
of the variable:

i+=1;

If you're comfortable with the escalation from = as the only
assignment operator to a C with seven such operators (=, +=, -=,
*=, /=, %=, <<=, >>=), it seems strange that adding four more
(++, --, ++, --) would cause discomfort.[...]

Sorry: I overlooked &=, |=, and ^=. To restate: If expansion
from one assignment operator to TEN doesn't disturb you, it seems
strange that adding four more makes you suddenly uncomfortable.
 
E

Eric Sosman

Eric Sosman said:
If you're comfortable with the escalation from = as the only
assignment operator to a C with seven such operators (=, +=, -=,
*=, /=, %=,<<=,>>=), it seems strange that adding four more
(++, --, ++, --) would cause discomfort.[...]

Sorry: I overlooked&=, |=, and ^=. To restate: If expansion
from one assignment operator to TEN doesn't disturb you, it seems
strange that adding four more makes you suddenly uncomfortable.

Actually, you might want to count them again; =, +=, -=, *=, /=, %=,<<=,

(Sigh.)

"The square root of six is three, for suitable values of three."
 

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,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top