C, really portable?

P

P.J. Plauger

Thats nice, but not the question OP was asking. Please crack open a
dictionary: Availability != Portability.

No, but it's part of a complete breakfast. Portability is a
measure of the relative cost of moving software between
platforms vs. rewriting it; it's not a Boolean. Availability
is thus an important factor in improving portability.
[...] and many of them score nearly perfect on two or more
nontrivial validation suites. Put another way, I've sold C code
intended to be portable also for several decades and I've *never*
had to worry about whether that code will compile, and execute
correctly, on a multitude of platforms. (With C++, I *always*
worry.)

Before C came along, I was doing similar things with Fortran,
and with reasonable success.

Well yeah, and you could do the same thing with Visual Basic, and the
various Basic interpretors available for UNIXs, and so on.

Please don't translate my qualitative measure into a Boolean.
Turn your contrast knob down a bit. My point was that you could
achieve rather high portability using the Pfort subset of Fortran.
(See Kernighan & Plauger, "Software Tools".) You could do not
quite as well with Pascal, even though that language was allegedly
more portable than Fortran. (See Kernighan & Plauger, "Software
Tools in Pascal".) But you can write *way* more powerful code
that's portable in C.
If you push
the entire job of portability up to the actual developer of the code,
well then in fact *MOST* languages are portable.

Your contrast knob is set too high again. The developer always
has *some* responsibility in writing portable code; the question
is what reward you get for your effort. I maintain that Standard
C has a pretty high reward for remarkably low effort, particularly
given that C is such a powerful (read: low level) language. But
it's never a question of putting all the responsibility either
on the programmer or on the language. So to say that most
languages are portable is to once again treat portability as a
Boolean, when it's not.
If fact, did you know
its fact possible to be portable *BETWEEN* many languages? When you
put the onus onto the programmer, you can claim all sorts of
capabilities for your language.

No, you can claim all sorts of capabilities for the programmer.
But if you're rewriting the code, you've left the above
definition of portability in the dust.
There is a subtle difference between a language begin portable, and
software which has been painstakingly ported.

Only if you think in black and white. We informally say that
a language is portable if it lowers the cost of writing
programs that are portable (cheaper to move than to completely
rewrite). If you take too much pain in porting the code,
somewhere along the line the cost of a complete rewrite
proves to be lower and the code is "not portable". (You
sometimes find that out too late.)
[...] And I've used about half a dozen
other popular languages with lesser success. So, IM(extensive)E
C portability is far from meaningless to me. YM(obviously)V.
In c.l.c we often see 'not portable' comments, but I wonder just how
portable C apps really are.

They're not. Amongst languages in common use today, C is just like
Visual Basic in that there just really isn't any real expectation of
portability on any real world application code. Nearly every other
language in common use today is far more portable than C.

Does your planet have an oxygen atomsphere? Just curious.

Well my planet has Lua, Java, Python, Perl, TCL, and bizarre new
languages like Haskel, Scheme, etc. They are all portable.

I wonder what language their compilers were written in. I'm
sure *some* of them were written in languages other than C.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
M

Mark McIntyre

Uhh ... no, they have *other* basic interpretors and compilers.

True, but irrelevant. Egregious misdirection won't help you in CLC
,the pedants are too pedantic. In this instance I refer you to your
own remark "C is just like Visual Basic" and a later one "Visual Basic
is more portable" you made in the same thread.
 
J

jacob navia

Is a program just using printf portable?
For instance this one:

#include <stdio.h>
int main(void)
{
int r=printf("hello world\n");
}

Is not portable.

Why?

The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.

The standard makes NO error analysis, not even a summary
error analysis where it could have said some ranges of
values for specific problems, and indicate some common
behavior in the case of an error. For instance an input
output error (disk full, device not ready, whatever)
could have been a single value, specified by the standard
but it isn't.

MANY things in the standard (specially error handling) are
handled in such a sloppy manner that any reasonable
usage of them is impossible and I do not just mean
gets()...

"Portability" is like "code reuse", or "good design principles".
Things everyone will tell you "Of course I want it"
but when you look underneath the covers you see that the
practice is completely different.

Yes, C is very portable and encourages code reuse, but
lisp is as portable as C, and fortran is quite portable too.

You have to limit yourself to the language subset that
will run in several platforms, that's all.
 
M

Malcolm

jacob navia said:
#include <stdio.h>
int main(void)
{
int r=printf("hello world\n");
}

Is not portable.

Why?

The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.

The standard makes NO error analysis, not even a summary
error analysis where it could have said some ranges of
values for specific problems, and indicate some common
behavior in the case of an error. For instance an input
output error (disk full, device not ready, whatever)
could have been a single value, specified by the standard
but it isn't.

MANY things in the standard (specially error handling) are
handled in such a sloppy manner that any reasonable
usage of them is impossible and I do not just mean
gets()...

"Portability" is like "code reuse", or "good design principles".
Things everyone will tell you "Of course I want it"
but when you look underneath the covers you see that the
practice is completely different.

Yes, C is very portable and encourages code reuse, but
lisp is as portable as C, and fortran is quite portable too.

You have to limit yourself to the language subset that
will run in several platforms, that's all.
But the reality is that printf() hardly ever fails, and if it does fail
getting your program's standardoutput is probably not going to be very high
on the user's list of priorities.

A worse problem is that many C installations don't have a stdout.
 
C

Chuck F.

P.J. Plauger said:
.... snip ...

Please don't translate my qualitative measure into a Boolean.
Turn your contrast knob down a bit. My point was that you could
achieve rather high portability using the Pfort subset of Fortran.
(See Kernighan & Plauger, "Software Tools".) You could do not
quite as well with Pascal, even though that language was allegedly
more portable than Fortran. (See Kernighan & Plauger, "Software
Tools in Pascal".) But you can write *way* more powerful code
that's portable in C.

The problem there was that most compiler systems of the time did
not adhere to the standard, whether that standard was J & W, or the
later ISO. Borland and UCSD were notably non-compliant. However C
had the great advantage of more or less universal compliance with
the C90 standard, or the earlier drafts.
 
K

Keith Thompson

jacob navia said:
Is a program just using printf portable?
For instance this one:

#include <stdio.h>
int main(void)
{
int r=printf("hello world\n");
}

Is not portable.

Why?

Um, because it doesn't return a value from the main program? (That's
valid for C99, but not for C90.) Adding a "return 0;" would fix that.
But I don't think that's what you had in mind.
The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.

No, it just means you can tell that an error occurred if r<0.

You can't portably tell what error occurred (if any). But since the
program doesn't attempt to do so, in what sense is the program itself
non-portable?

(Did you intend to do something with the value of r? Some compilers
would complain about it being set but not used.)

[...]
You have to limit yourself to the language subset that
will run in several platforms, that's all.

And that "subset" is defined by the standard.
 
E

Eric Sosman

jacob said:
Is a program just using printf portable?
For instance this one:

#include <stdio.h>
int main(void)
{
int r=printf("hello world\n");
}

Is not portable.

Perfectly portable to any C99-conforming system.
(Under C90 rules it's erroneous, hence not portable.)
Why?

The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.

Nonsense. <stdio.h> defines a macro named EOF, and
the expansion of that macro is the negative value you
mention. You can portably compare `r' to EOF and make
decisions based on equality or inequality. In this case
you can even forego EOF altogether and just test `r<0'
to see whether an error has occurred.
The standard makes NO error analysis, not even a summary
error analysis where it could have said some ranges of
values for specific problems, and indicate some common
behavior in the case of an error. For instance an input
output error (disk full, device not ready, whatever)
could have been a single value, specified by the standard
but it isn't.

"Analysis" is a peculiar word to use here, so I'm not
entirely sure I know what Jacob is talking about. However,
the Standard certainly does prescribe specific behaviors
for some abuses of some functions. For example, acos(42.0)
and strtod("foo", NULL) are required to detect the erroneous
inputs and react in specific ways. True, some functions are
not so tightly specified; the behavior of free("beer") is
undefined. And for other functions the Standard requires
failures to be reported in a specific way, but does not try
to enumerate all the possible causes of failure. For example,
malloc(1) is required to return NULL if it fails, but the
Standard doesn't try to list all the possible failure modes
of all the possible malloc() implementations in the Universe.

The second sentence is simply nonsense. Jacob complains
that the Standard could have used a single value to report
I/O errors but does not -- well, what does he think EOF is?
(I refuse to be fazed by the fact that some functions return
NULL instead of EOF to report an error: Each function has a
known and predictable way of reporting errors, which means
the programmer has a portable way of detecting them.)
MANY things in the standard (specially error handling) are
handled in such a sloppy manner that any reasonable
usage of them is impossible and I do not just mean
gets()...

Reasonable error handling may be beyond Jacob's powers,
but other programmers have found it tractable.
> [...]
You have to limit yourself to the language subset that
will run in several platforms, that's all.

In particular, this means you must not use Jacob's
Private Language, the one he claims is C but so clearly is
no such thing. (Perhaps Jacob's opinion of C's portability
stems from his mistaken belief that JPL is C. Since JPL is
not portable, Jacob concludes that C is not portable -- but
really, that's only speculation on my part. More likely,
he's just trolling again.)
 
M

Mark McIntyre

Is a program just using printf portable?
For instance this one:

#include <stdio.h>
int main(void)
{
int r=printf("hello world\n");
}

Is not portable.

You're wrong, and your reasoning is flawed. The programme is 100%
portable, it will work on any platform.
The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.

Nonsense. You yourself note the error analysis you can do - negative
values indicate an error. This is fully portable, and very useful.
MANY things in the standard (specially error handling) are
handled in such a sloppy manner that any reasonable
usage of them is impossible

Perhaps, just perhaps, the people on the committee know a little bit
more than you do? Perhaps there;s a slim chance theres a good reason
why error handling isn't specified as you;d like? Maybe something to
do with different platforms supporting different types of errors, or
not reporting some errors, or not allowing some to occur at all? Or do
you think its more likely that your knowledge is greater than theirs?
Given your apparent exposure to exactly one platform?
"Portability" is like "code reuse", or "good design principles".
Things everyone will tell you "Of course I want it"
but when you look underneath the covers you see that the
practice is completely different.

YMMV but in my experience that view is quite incorrect. I've said this
before, but you seem to have had a very very sheltered exposure to
real world programming.
 
J

jacob navia

Keith Thompson a écrit :
Um, because it doesn't return a value from the main program? (That's
valid for C99, but not for C90.) Adding a "return 0;" would fix that.
But I don't think that's what you had in mind.

Correct. I am using standard C, not some old standard
no longer valid.
No, it just means you can tell that an error occurred if r<0.

WHAT error? That is my point!

You can't portably tell what error occurred (if any).

That is what I was saying!
> But since the
program doesn't attempt to do so, in what sense is the program itself
non-portable?

I didn't write that part because it is not portable.
If there is an i/o error, a sensible value *could* be
EOF, but not even that is specified.
(Did you intend to do something with the value of r? Some compilers
would complain about it being set but not used.)

This is just polemic. My message was clear: the error analysis of
a printf call is not portable.

printf ("%07L\n",23.78);

how do I detect the format error in my program without
tying me to a specific printf implementation???
 
K

Keith Thompson

Eric Sosman said:
jacob navia wrote: [...]
The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.

Nonsense. <stdio.h> defines a macro named EOF, and
the expansion of that macro is the negative value you
mention. You can portably compare `r' to EOF and make
decisions based on equality or inequality. In this case
you can even forego EOF altogether and just test `r<0'
to see whether an error has occurred.

No, the standard says:

The fprintf function returns the number of characters transmitted,
or a negative value if an output or encoding error occurred.

There's no implication that the negative value is the same as EOF.

If EOF happens to be -1 (which is common), and printf() happens to
return -1 on error (which is probably also common), then testing
against EOF might happen to work, but the only think you can depend on
is that the result is less than 0 on error.

An implementation could use the return value to indicate what kind of
error occurs, but again, any program depending on this is
non-portable.
 
J

jacob navia

Mark McIntyre a écrit :
You're wrong, and your reasoning is flawed. The programme is 100%
portable, it will work on any platform.




Nonsense. You yourself note the error analysis you can do - negative
values indicate an error. This is fully portable, and very useful.

"There was an error"

If you are satisfied with such an error analysis OK.
It *could* be that you need to know MORE isn't it?

WHAT type of error?

Input output error? (disk full, i/o whatever)
Format error? (incorrect specifications of the
arguments to printf, illegal format specs, missing argument)
Memory error? (printf attempted to allocate memory for some
internal buffers and failed due to low memory conditions)
Perhaps, just perhaps, the people on the committee know a little bit
more than you do? Perhaps there;s a slim chance theres a good reason
why error handling isn't specified as you;d like? Maybe something to
do with different platforms supporting different types of errors, or
not reporting some errors, or not allowing some to occur at all? Or do
you think its more likely that your knowledge is greater than theirs?
Given your apparent exposure to exactly one platform?
I will ignore your sarcastic tone, since I do not care
a lot about your opinion of me. Staying at the level
of a discussion about C, it is obvious that some
care could have produced a more detailed specification of
the error report of printf isn't it?

Specifying a series of error range values could have been done
I do not see why a spec like this would not be feasible:

EOF: i/o error. Device full, device not ready, etc
-100 <= error <=-10 Format error. Incorrectly specified format string
-1000 <= error <= -101 Internal printf error
-1001 > error Non standard specified error type.
etc.

This would have allowed to make portable programs
that test for the return value of printf and can do a more
reasonable error analysis than

AN ERROR HAPPENED...
YMMV but in my experience that view is quite incorrect. I've said this
before, but you seem to have had a very very sheltered exposure to
real world programming.

Basically that sentence says:

"I do not like you."

You have NO idea who am I, what do I do, etc.

But you know that I have a "sheltered" ???
exposure to real world programming.

Well, OK. You are correct. I do not care.
 
J

jacob navia

Keith Thompson a écrit :
An implementation could use the return value to indicate what kind of
error occurs, but again, any program depending on this is
non-portable.

This is my point. The error analysis of printf is not portable.
And this is a pity, since that function is extremely portable
and with just a bit of effort the error analysis *could*
have been better specified. For instance:

1) EOF: i/o error. Device full, device not ready, etc
2) -100 <= error <=-10 Format error. Incorrectly specified format string
3) -1000 <= error <= -101 Internal printf error: memory low for internal
buffers, synchronization problems in a multi-threaded
context, whatever.
4) -1001 > error Non standard specified error type.

So, for the two most likely problems that occur, we
could now write portable programs that could
do a reasonable error analysis!

Error when output to the device (disk or
terminal), and format spec error.

Specially the second, would be nice to have since if
you write:

printf("%07L\n", 2776.8);

there is now no way to know what happened and why
it doesn't work!

Please understand that I am NOT arguing against portability
but pointing to the fact that even in the most simple
programs, standard C leaves an essential part of
software construction: error analysis, completely out
of the picture!

jacob
 
J

jacob navia

Malcolm a écrit :
But the reality is that printf() hardly ever fails,

Never had a "Disk full" report?

fprintf can well fail...

And the error analysis there is the same...
 
J

jacob navia

Mark McIntyre a écrit :
Excuse me but maybe you know that VB 6 is no longer
supported by Microsoft and you are supposed to rewrite
your software into VB .NET now.

This has been a catastrophe for many small software
companies that bet on VB and now find themselves
forced to rewrite thousands of lines of complicated
applications in VB .Net...

Happily this is not going to happen with C. It is not
owned by a single company.
 
N

Netocrat

]
printf ("%07L\n",23.78);

how do I detect the format error in my program without
tying me to a specific printf implementation???

By using a compiler or other tool that warns about it. Why use a runtime
check for something that can be checked prior?
 
J

jacob navia

Netocrat a écrit :
]
printf ("%07L\n",23.78);

how do I detect the format error in my program without
tying me to a specific printf implementation???


By using a compiler or other tool that warns about it. Why use a runtime
check for something that can be checked prior?

Lcc-win32 does that kind of analysis but this is not the
point, since the format string could be an argument
or a variable passed from another function, etc.
 
K

Keith Thompson

jacob navia said:
Keith Thompson a écrit :

Correct. I am using standard C, not some old standard
no longer valid.

Fine, but you should be aware that there are still plenty of
implementations that don't (yet) support the current standard.
If you're concerned about portability, you have to take that into
account. Adding a "return 0;" at the end of main() is harmless in
any case.
WHAT error? That is my point!

You can't portably tell what error occurred; I grant you that.
That is what I was saying!
Ok.


I didn't write that part because it is not portable.
If there is an i/o error, a sensible value *could* be
EOF, but not even that is specified.

You claimed that the program you posted is non-portable. In fact,
it's quite portable. The part of it you didn't write might be
non-portable, but we're not mind-readers. If you want to make a
point, I suggest you post code that actually illustrates the point
you're trying to make.

There are things you can do portably in C. There are other things you
can't do portably in C. Is that your point? It's true of any
language.
This is just polemic. My message was clear: the error analysis of
a printf call is not portable.

printf ("%07L\n",23.78);

how do I detect the format error in my program without
tying me to a specific printf implementation???

You can't.

The error analysis is merely limited to determining whether or not an
error occurred. I fail to see what that has to do with the
portability of the language.
 
J

jacob navia

Keith Thompson a écrit :
You can't.

The error analysis is merely limited to determining whether or not an
error occurred. I fail to see what that has to do with the
portability of the language.

Well, of course the language is very portable. But when you
dig a bit deeper you find that things like error failure modes
and error analysis is completely left out of the picture or
treated as an afterthought. ("An error occured")

My point is that this is a flaw that hinders the portability
of C, even in small programs like the example I gave.

Is this code snippet portable?

int a,b,c;
....
a = b+c;

No, it is not, since the overflow behavior is not specified...

(See the discussion we had a few days ago)

In general C programs port well, but serious improvements to
the portability of the language could be done if the
far too numerous "dark zones" (UB) would be correctly
specified.
 
M

Mark McIntyre

If you are satisfied with such an error analysis OK.
It *could* be that you need to know MORE isn't it?

WHAT type of error?

And how could such error analysis be portable?
Input output error? (disk full, i/o whatever)

Lets go on: Which sort of IO error? What caused it? Who was running
the programme at the time? How much memory was in use? How many
diskdrives were busy? Which horse running in the 3:30 at Kempton? You
see my point?

it is obvious

Then perhaps you'd care to show how.
that some
care could have produced a more detailed specification of
the error report of printf isn't it?

Please produce a DR, submit it to the committee, and remember, it has
to work on all platforms supported by C. If its workable, I'm quite
sure they'll consider it. Remember, it mustn't break any existing
implementations, nor produce any meaningless errors.
Specifying a series of error range values could have been done
I do not see why a spec like this would not be feasible:

Of course its feasible, But many of them have no meaning and in fact
may even be impossible on many implementations. I mean, would you
really want to provide an "out of red ink" error code for a screen
device? Or a "please rewind the tape" error for a keyboard?
Basically that sentence says:

"I do not like you."

No. That sentence says "you write stuff here based on apparent
experience of one platform, and assume that your experience is
typical. You persist in this even when shown to be wrong by
counterexample. "
You have NO idea who am I, what do I do, etc.

I know a fair amount as it happens. I know you're probably french, I
know you write a compiler. I know you use webhosting services of the
university of Virginia. I know you have a hook-in with a German
software company based near Karlsruhe, and that the town has a
brewery.
I also know you write incorrect stuff in CLC, and I know that from
time to time you write correct stuff. If you could stick to the
latter, you'd find yourself flamed less.
I do not care.

Thats evident. And here's a thought: people who are unrepentant in the
face of their obvious errors, especially ones who are agressive in
defending those errors, often find they're unpopular with their peers.
 
M

Mark McIntyre

printf ("%07L\n",23.78);

how do I detect the format error in my program without
tying me to a specific printf implementation???

By using a compiler, or simlar tool, that warns about such errors. Why
rely on runtime checks for stuff you should be checking at compile
time.
 

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,014
Latest member
BiancaFix3

Latest Threads

Top