Plz explain me the following code

R

Richard Tobin

Phil Carmody said:
I'm not sure how common an incomplete FILE type is. I wish it were
more common. I suspect there's never been a good need to expose its
innards.

I have seen (and written) several programs that made good use of
fields in the FILE struct. They were not portable to all C
implementations of course.

Of course, making the struct incomplete in stdio.h doesn't preclude
this.

-- Richard
 
M

Morris Keesan

Morris Keesan said:
Phil Carmody wrote:
[...]
And, thinking a little more about it, some UB doesn't even involve
the
host. For example, fclose() on an invalid FILE*, or free() with a
pointer not from malloc() and friends. (Yes, the host may get
involved if the pointer itself is not valid, but what happens with a
valid pointer but just not pointing to what is expected?)
FILE* fp=fopen("foo", "r");
FILE* fp2=malloc(sizeof(*fp2));
memcpy(fp2, fp, sizeof(*fp2));
fclose(fp2);
fp2 of course does point to *what* was expected, it's just not
*where*
it was expected.

Which means it may not work. (I'm not sure if it's UB, however.)

7.19.3p6

"The address of the FILE object used to control a stream may be
significant; a copy of a FILE object need not serve in place of the
original."

But note that in Phil Carmody's code, no FILE object is being copied.
He's copying a (FILE *) from fp into fp2, not a FILE.

I think you've miss-read it. To copy a FILE * all you need is:

fp2 = fp;

The memcpy copies the thing pointed to by fp (well, the sizeof *fp2
bytes pointed to by fp).

Oops. Yes, you're right. My apologies.
My eyes saw memcpy(fp2, fp, sizeof(*fp2));
but my brain somehow this into memcpy(&fp2, &fp, sizeof(fp2));

I retract my previous post.
 
K

Keith Thompson

Phil Carmody said:
I'm not sure how common an incomplete FILE type is. I wish it were
more common. I suspect there's never been a good need to expose its
innards.

C99 7.19.1p2 requires FILE to be an object type. I believe C90 has
the same requirement.

I don't think making FILE an incomplete type would cause any real harm
(other than breaking conformance).
 
O

Old Wolf

Perhaps replacing UB with something like "anything left undefined will, on
hosted implementations, behave in a manner consistent with the host"? So,
dereferencing a NULL pointer on Unix can't launch nuclear missiles, since
Unix says it should SEGV.

This might be unnecessarily restrictive; e.g. we
already had an example in this thread of a processor
that could be deadlocked by this code. Perhaps the
nuclear missiles are set up to launch automatically
if they do not receive a periodic signal from this
processor.
 
P

Phil Carmody

Keith Thompson said:
C99 7.19.1p2 requires FILE to be an object type. I believe C90 has
the same requirement.

I don't think making FILE an incomplete type would cause any real harm
(other than breaking conformance).

Good catch, Keith. Thanks.

Phil
 
H

Herbert Rosenau

a = b() + c();
b and c can occur in parallel because I know they won't interfere with
each other. In C you cannot express that level of freedom.

Chapter and verse please.

In C the order of evaluation b() + c() is unspecified. The only what
is specified is that both b() and f() must be executed to get +
executed. That includes that b() and c() can be executed in parallel
when the CPU can do so. Still tricky because C says nothing about
multithreading, it does neither allow nor disallow executing multiple
statements or whole functions in parallel.

So it is still the environment the program is runnung under that says
that c() gets executed before b() or b() before c() or b() and c() in
parallel.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
N

Nobody

Chapter and verse please.

In C the order of evaluation b() + c() is unspecified. The only what
is specified is that both b() and f() must be executed to get +
executed. That includes that b() and c() can be executed in parallel
when the CPU can do so.

I don't think so. The compiler can evaluate b() then c(), or c() then b(),
but it can't evaluate them concurrently.

Consider:

#include <stdio.h>
static int i = 0;

static int b(void) { int t = i; t++; i = t; return i; }
static int c(void) { int t = i; t++; i = t; return i; }

int main(void) {
int x = b() + c();
printf("%d %d\n", x, i);
return 0;
}

The output is guaranteed to be:

3 2

This is true even if b() and c() are moved into separate compilation
units so that their definitions aren't visible when compiling main().

If the compiler executed them in parallel, race conditions could result in
an output of:

2 1

due to each function reading i before the other has had chance to update
it.
 
R

Richard Bos

Herbert Rosenau said:
Chapter and verse please.

In C the order of evaluation b() + c() is unspecified. The only what
is specified is that both b() and f() must be executed to get +
executed. That includes that b() and c() can be executed in parallel
when the CPU can do so.

Yesno. Only if they have no side-effects, or if the implementation can
prove that the order of those side effects do not matter. There is a
sequence point before calling each function, and another at the end of
the terminating statement of each.
If both functions contain (to use the same example as before - which, by
the way, is a realistic one in my case at least) calls to a logging
function, then the implementation is allowed to always make the log
entries of b() come first, or always those of c(), or even sometimes
those of b() and sometimes those of c(), but because of those sequence
points, it _must not_ allow those of b() and c() to be written to the
log interspersed with one another.

Richard
 
N

Nick Keighley

Since we currently have *two* threads addressing this issue
I thought "wouldn't it be handy if there were a FAQ for this!"

And lo:-

http://c-faq.com/

FAQ 3.4 "Can I use explicit parentheses to force the order of
evaluation I want..."

Most of the rest of section would be a good read as well
 
C

Chris H

In message <[email protected]
s.com> said:
plz tell me how this code is working and what would be the the o/p
1)

{
int x=20,y=35;
x = y++ + x++;
y = ++y + ++x;
printf("%d %dn",x,y);
}


2)
{
int x=5;
printf("%d %d %dn",x,x<<2,x>>2);
}
Thankyou

The page was done many years ago and is probably well out of date
(1997) but does illustrate the problem

http://www.phaedsys.demon.co.uk/chris/sweng/swengtips3.htm

answers are on the linked page

PLEASE NOTE the code as shown runs on a bare metal 8051 with no OS hence
the void main (void) There is nothing to return to from main. The
serial init function was assembler so left off the listing.

TO run on a PC remove the
#include <REG592.H>
static void init_serial(void);
init_serial();
 
K

Keith Thompson

Chris H said:
PLEASE NOTE the code as shown runs on a bare metal 8051 with no OS hence
the void main (void) There is nothing to return to from main.
[...]

If "void main(void)" is permitted, it's not because it's running
on a bare metal 8051, it's because the particular compiler being
used permits it.
 
K

Kenny McCormack

Chris H said:
PLEASE NOTE the code as shown runs on a bare metal 8051 with no OS hence
the void main (void) There is nothing to return to from main.
[...]

If "void main(void)" is permitted, it's not because it's running
on a bare metal 8051, it's because the particular compiler being
used permits it.

The mind boggles...

(And not in a good way)
 
C

Chris H

Keith Thompson <kst- said:
Chris H said:
PLEASE NOTE the code as shown runs on a bare metal 8051 with no OS hence
the void main (void) There is nothing to return to from main.
[...]

If "void main(void)" is permitted, it's not because it's running
on a bare metal 8051, it's because the particular compiler being
used permits it.

No it is because it is self hosted (and the compiler permits it).
 
K

Keith Thompson

Chris H said:
Keith Thompson <kst- said:
Chris H said:
PLEASE NOTE the code as shown runs on a bare metal 8051 with no OS hence
the void main (void) There is nothing to return to from main.
[...]

If "void main(void)" is permitted, it's not because it's running
on a bare metal 8051, it's because the particular compiler being
used permits it.

No it is because it is self hosted (and the compiler permits it).

A self hosted compiler is one that compiles itself (gcc is an
example). I seriously doubt that a compiler targeting a bare
metal 8051 is self hosted. In any case, it's not a term used by
the standard.

I think the distinction you're looking for is between a hosted
implementation and a freestanding implementation; the latter is,
very roughly speaking, an implementation for an embedded system.

Either a hosted implementation or a freestanding implementation
may permit "void main(void)", but for different reasons. For a
hosted implementation, it's permitted by the "or in some other
implementation-defined manner" phrase in C99 5.1.2.2.1p1 (though
IMHO it's foolish for either an implementation or a program to
take advantage of this). For a freestanding implementation,
it's permitted by C99 5.1.2.1p1: "In a freestanding environment
(in which C program execution may take place without any benefit
of an operating system), the name and type of the function called
at program startup are implementation-defined."
 
H

Herbert Rosenau

Yesno. Only if they have no side-effects, or if the implementation can
prove that the order of those side effects do not matter. There is a
sequence point before calling each function, and another at the end of
the terminating statement of each.

Yes, but that does not matter. We don't speak here about
multithrading! There are CPUs available who can execute multiple
instructions in parallel without having the ability of multiple cores
as used for multithreading. That means that the CPU uses multiple
caches and/or pipes, can execute floatinpoint and interger
instructions in parallel, a mixup of all - and a compiler that is able
to sort instructions in a way that allows to use this abilities - as
if the cpu can only execute a single instruction in a timeframe.
If both functions contain (to use the same example as before - which, by
the way, is a realistic one in my case at least) calls to a logging
function, then the implementation is allowed to always make the log
entries of b() come first, or always those of c(), or even sometimes
those of b() and sometimes those of c(), but because of those sequence
points, it _must not_ allow those of b() and c() to be written to the
log interspersed with one another.

Yes - but when b() and c() have no overlapping access to the same
variables the compiler is allowed to generate overlapping instruction
sets.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
K

Kenny McCormack

Herbert Rosenau said:
Yes, but that does not matter. We don't speak here about
multithrading! There are CPUs available who can execute multiple
instructions in parallel without having the ability of multiple cores
as used for multithreading. That means that the CPU uses multiple

Every time this guy posts, I feel like ordering another round of word
salad.

With bleu cheese dressing...
 
K

Keith Thompson

Eric Sosman said:
Herbert said:
On Fri, 25 Sep 2009 17:38:36 UTC, Flash Gordon
a = b() + c();
b and c can occur in parallel because I know they won't interfere
with each other. In C you cannot express that level of freedom.
[...]
Yes - but when b() and c() have no overlapping access to the same
variables the compiler is allowed to generate overlapping
instruction sets.

It's difficult to figure out when such an overlap is safe.

int b1 = 0, b2 = 0;
int b(void) { return ++b1 + b2++; }

int c(void) { return strlen(NULL); }

If the error in c() raises a signal and the signal is caught, the
handler must be able to observe b1 and b2 and find that both have
"stable" values, and that either both have been incremented or
neither has been. If the handler sees b1 != b2, as it might if
the signal from c() occurred between the two increments in b(),
the parallelization was invalid.

No, if strlen(NULL) either does or does not raise a signal the handler
can do anything it likes. The behavior of strlen(NULL) is undefined.
(An implementation might impose additional requirements on the behavior
of strlen(NULL).)

A call to raise() might make for a better example.

[...]
 
N

Nobody

Yes - but when b() and c() have no overlapping access to the same
variables

And how is the compiler supposed to determine that (excluding the special
case where b() and c() are defined in the same translation unit as the
caller)?
 
T

Tim Rentsch

Dik T. Winter said:
Note the last part, a compiler is even allowed not to compile the program
at all.

If the undefined behavior is run-time behavior and the
compiler is asked only to translate the program, the
compilation must complete because undefined behavior hasn't
occurred. (3.4.3p1: "upon use of a nonportable or
erroneous construct" -- no use, no undefined behavior.)

The discussion in 5.1.1.1p1 clearly indicates that
translation can occur separately from execution.
 
T

Tim Rentsch

One of the goals of modern language design (a class of which C is not a
member) is to eliminate the concept of undefined behavior. It is a
necessary evil in C and assembler (and similar), but it is never
desirable.

This is said as though it's self-evident, but it's not
even clear that it's true, let alone self-evident. There
are times when safe languages are perfectly appropriate;
there are other times when it's important to have an
unsafe language, for example for things like writing
operating systems.

One of the primary goals of, to pick two unreleated but
similar examples, the 'D' programming language and 'C#' (and CLR
languages in general) was to make it that any legal syntax has one and
only one possible meaning. I.e., in the words of the 'D' implementor,
it is either correct or it isn't - none of this "in between" stuff
that characterizes C.

Note that D is not a safe language -- it has unchecked
pointers just like C does.

Now, you may agree with this or not, but the point is that that is what
the designers of these languages set out to do.

Newer languages often are designed to be safe because
there isn't much need for another unsafe language.
Either C or C++, depending on one's druthers, fill
almost all the needs of the demand for unsafe
languages. It would be quite a different story if
C and C++ didn't exist, and operating systems were
still being written in assembly language -- then there
would be an explosion of unsafe "systems programming"
languages, as indeed there was before C came on the
scene.

It's because C is so successful as an unsafe language that
newer languages tend to be designed as safe languages.
There being a successful unsafe language is necessary so
other language designers can focus on doing the safe parts
of programming languages, ignoring the unsafe parts because
those can always be done in C.
 

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,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top