reply the answer

A

Army1987

Eric Sosman said:
Here's a program that doesn't fulfill the requirements,
but that outputs a hint about one way to satisfy them:
/* hint.c
* Compile in whatever way your system demands,
* then execute with the command-line arguments
* firstname lastname wants a hint
* substituting your own first and last names
* for `firstname' and `lastname'.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argv, char **argc)
{
if (argv != strlen("guthena" + 1)
My last name has a blank space in it. So I won't be able to use it
unless I use CamelCase, underscores, or similar.
|| strcmp(argc[3], "wants")
|| strcmp("hint", argc[5])
|| *argc[4]++-*++argc[3]
|| *argc[4]) {
fputs ("No hints for people who can't "
"follow simple directions!\n", stderr);
return EXIT_FAILURE;
}
printf ("This hint is for the sole use of %s ", *++argc);
printf ("%s: %d.", *++argc, argv--);
printf ("%.1f\n", argv * 21 / 10.0);
return EXIT_SUCCESS;
}
The OP asked for a C program printing "HELLOWORLD !".
Who said that his compiler/preprocessor is written in C?
 
A

Army1987

guthena said:
Can we write a C programe with out a semicolon ? printing HELLOWORLD !

The answer depends on wheter by "programe" you only mean the .c
file(s) you feed the compiler, or also the .h files #included.

In the former case, do this:

/* Begin foo.h */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
if (puts("HELLOWORLD !") < 0)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}
/* End foo.h */

/* Begin foo.c */
#include "foo.h"
/* End foo.c */

In the latter case, probably you can't. In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments. But you need either a return statement, which
requires a semicolon, or the declaration of exit() (which does not
return int), which requires a semicolon. In C99, you don't strictly
need a return statement, but you need a declaration for any
function you use. So, if you are using an implementation where
either stdio.h or stdlib.h contain at least a semicolon (they could
also use some form of magic, and they don't even need to be files,
but on the implementations I've seen they do use semicolons), then
you can't.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Army1987 said:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.

You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no prototype is in
scope that says it is okay to pass an argument of type char * when the
function accepts const char * (any pointer to any character type or void)
but it only applies to functions whose /definition/ also doesn't include a
prototype. Whether the definition of puts includes a prototype is not
specified by the C standard.
 
C

CBFalconer

Harald said:
Army1987 said:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.

You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no
prototype is in scope that says it is okay to pass an argument
of type char * when the function accepts const char * (any
pointer to any character type or void) but it only applies to
functions whose /definition/ also doesn't include a prototype.
Whether the definition of puts includes a prototype is not
specified by the C standard.

Bushwah. There is no need to supply a const parameter to puts.
All the 'const' in the function prototype says is that the function
will not alter the passed parameter. I suspect you are thinking
C++, which is different.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

CBFalconer said:
Harald said:
Army1987 said:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.

You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no
prototype is in scope that says it is okay to pass an argument
of type char * when the function accepts const char * (any
pointer to any character type or void) but it only applies to
functions whose /definition/ also doesn't include a prototype.
Whether the definition of puts includes a prototype is not
specified by the C standard.

Bushwah. There is no need to supply a const parameter to puts.
All the 'const' in the function prototype says is that the function
will not alter the passed parameter. I suspect you are thinking
C++, which is different.

I am not thinking of C++, I am thinking of C. I'm quoting from n1124; I
don't believe C90 was any different in this regard. Calls to functions
without a prototype in scope are described in 6.5.2.2p6, which contains

"If the function is defined with a type that includes a prototype, and [...]
the types of the arguments after promotion are not compatible with the
types of the parameters, the behavior is undefined."

Since puts is allowed to be defined with a type that includes a prototype
(the standard never says otherwise), and const char * is not compatible
with char *, the behaviour is undefined. What part of that is "bushwah"?
 
J

Joe Wright

Harald said:
CBFalconer said:
Harald said:
Army1987 wrote:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.
You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no
prototype is in scope that says it is okay to pass an argument
of type char * when the function accepts const char * (any
pointer to any character type or void) but it only applies to
functions whose /definition/ also doesn't include a prototype.
Whether the definition of puts includes a prototype is not
specified by the C standard.
Bushwah. There is no need to supply a const parameter to puts.
All the 'const' in the function prototype says is that the function
will not alter the passed parameter. I suspect you are thinking
C++, which is different.

I am not thinking of C++, I am thinking of C. I'm quoting from n1124; I
don't believe C90 was any different in this regard. Calls to functions
without a prototype in scope are described in 6.5.2.2p6, which contains

"If the function is defined with a type that includes a prototype, and [...]
the types of the arguments after promotion are not compatible with the
types of the parameters, the behavior is undefined."

Since puts is allowed to be defined with a type that includes a prototype
(the standard never says otherwise), and const char * is not compatible
with char *, the behaviour is undefined. What part of that is "bushwah"?

I have puts() prototyped in stdio.h like..

int puts(const char *s);

...and defined something like..

#include <stdio.h>

int puts(const char *s)
{
int c;
while ((c = *s++))
putchar(c);
return putchar('\n');
}

You will note that const does not apply to s but to *s. It's a promise
to the compiler that puts() will not write to its input string, not that
it won't change s.

Given that 'puts(argv[1])' is incompatible in your view, how would you
qualify the argument?
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Joe said:
Harald said:
CBFalconer said:
Harald van D?k wrote:
Army1987 wrote:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.
You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no
prototype is in scope that says it is okay to pass an argument
of type char * when the function accepts const char * (any
pointer to any character type or void) but it only applies to
functions whose /definition/ also doesn't include a prototype.
Whether the definition of puts includes a prototype is not
specified by the C standard.
Bushwah. There is no need to supply a const parameter to puts.
All the 'const' in the function prototype says is that the function
will not alter the passed parameter. I suspect you are thinking
C++, which is different.

I am not thinking of C++, I am thinking of C. I'm quoting from n1124; I
don't believe C90 was any different in this regard. Calls to functions
without a prototype in scope are described in 6.5.2.2p6, which contains

"If the function is defined with a type that includes a prototype, and
[...] the types of the arguments after promotion are not compatible with
the types of the parameters, the behavior is undefined."

Since puts is allowed to be defined with a type that includes a prototype
(the standard never says otherwise), and const char * is not compatible
with char *, the behaviour is undefined. What part of that is "bushwah"?

I have puts() prototyped in stdio.h like..

int puts(const char *s);

..and defined something like..

#include <stdio.h>

int puts(const char *s)
{
int c;
while ((c = *s++))
putchar(c);
return putchar('\n');
}

You will note that const does not apply to s but to *s. It's a promise
to the compiler that puts() will not write to its input string,

Functions are allowed to cast away constness and modify the target of any
pointers they receive. This program is strictly conforming:

void f(const int *i) {
*(int *) i = 0;
}

int main(void) {
int i = 1;
f(&i);
return i;
}

Compilers are not allowed to assume that functions accepting
pointer-to-const arguments will not modify the pointed-to objects. puts is
not allowed to write to its input string because and only because this is
not part of its function description.
not that
it won't change s.

Of course. And even if it did mean that, the as-if rule would still allow it
to modify s, because the modifications would not be visible after puts
returns.
Given that 'puts(argv[1])' is incompatible in your view, how would you
qualify the argument?

I would include <stdio.h>, and let the compiler perform the implicit
conversion from char * to const char *.

If I had a good reason to avoid including <stdio.h>, I would provide a
prototyped declaration, and let the compiler perform the implicit
conversion from char * to const char *.

If I had a good reason to not provide a prototyped declaration, then I would
cast the argument from char * to const char * to match the parameter's type
(if the argument isn't const char * already), as I have done in my reply to
Army1987.
 
C

CBFalconer

Harald said:
CBFalconer said:
Harald said:
Army1987 wrote:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.

You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no
prototype is in scope that says it is okay to pass an argument
of type char * when the function accepts const char * (any
pointer to any character type or void) but it only applies to
functions whose /definition/ also doesn't include a prototype.
Whether the definition of puts includes a prototype is not
specified by the C standard.

Bushwah. There is no need to supply a const parameter to puts.
All the 'const' in the function prototype says is that the function
will not alter the passed parameter. I suspect you are thinking
C++, which is different.

I am not thinking of C++, I am thinking of C. I'm quoting from
n1124; I don't believe C90 was any different in this regard.
Calls to functions without a prototype in scope are described in
6.5.2.2p6, which contains

"If the function is defined with a type that includes a prototype,
and [...] the types of the arguments after promotion are not
compatible with the types of the parameters, the behavior is
undefined."

There are other provisions. I can't find them just now, but I
believe the following is indicative:

[#10] EXAMPLE 3 The function parameter declarations

void h(int n, int * const restrict p,
int * const q, int * const r)
{
int i;
for (i = 0; i < n; i++)
p = q + r;
}

show how const can be used in conjunction with restrict.
The const qualifiers imply, without the need to examine the
body of h, that q and r cannot become based on p. The fact
that p is restrict-qualified therefore implies that an
object accessed through p is never accessed through either
of q or r. This is the precise assertion required to
optimize the loop. Note that a call of the form h(100, a,
b, b) has defined behavior, which would not be true if all
three of p, q, and r were restrict-qualified.

Basically the "const" is not an integral part of the parameter
definition, it simply constrains the usage (as does "restrict").
It promises that the function will not modify the argument, and
places no restriction on the original object. Restrictions are
placed on removing a const qualifier, not on adding one (apart from
the usage).

Maybe others are better at finding the appropriate provision and
supplying the section/paragraph number.
 
K

Keith Thompson

Harald van Dijk said:
Compilers are not allowed to assume that functions accepting
pointer-to-const arguments will not modify the pointed-to objects. puts is
not allowed to write to its input string because and only because this is
not part of its function description.
[...]

I believe compilers are allowed to make that assumption. Yes, the
function itself can cast away the const qualification, but any attempt
to modify a const-qualified object invokes undefined behavior.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

CBFalconer said:
Harald said:
CBFalconer said:
Harald van D?k wrote:
Army1987 wrote:
[...]
if (puts("HELLOWORLD !") < 0)
[...]
In C90, you don't strictly
need a prototype for puts() because it returns int and has no
"strange" arguments.

You do, however, need to make sure you pass an argument of type
const char *, not char *.

if (puts((const char *) "HELLOWORLD !") < 0)

There is a special exception for function calls where no
prototype is in scope that says it is okay to pass an argument
of type char * when the function accepts const char * (any
pointer to any character type or void) but it only applies to
functions whose /definition/ also doesn't include a prototype.
Whether the definition of puts includes a prototype is not
specified by the C standard.

Bushwah. There is no need to supply a const parameter to puts.
All the 'const' in the function prototype says is that the function
will not alter the passed parameter. I suspect you are thinking
C++, which is different.

I am not thinking of C++, I am thinking of C. I'm quoting from
n1124; I don't believe C90 was any different in this regard.
Calls to functions without a prototype in scope are described in
6.5.2.2p6, which contains

"If the function is defined with a type that includes a prototype,
and [...] the types of the arguments after promotion are not
compatible with the types of the parameters, the behavior is
undefined."

There are other provisions. I can't find them just now, but I
believe the following is indicative:

It is not. "Compatible type" is defined in 6.2.7. char * is not compatible
with const char *. If you have a concrete claim that it is, or that the
fact that the standard explicitly states the behaviour is undefined does
not mean the behaviour really is undefined, please share.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Keith said:
Harald van Dijk said:
Compilers are not allowed to assume that functions accepting
pointer-to-const arguments will not modify the pointed-to objects. puts
is not allowed to write to its input string because and only because this
is not part of its function description.
[...]

I believe compilers are allowed to make that assumption. Yes, the
function itself can cast away the const qualification, but any attempt
to modify a const-qualified object invokes undefined behavior.

The object was not const-qualified.

void f(const int *i) {
  *(int *) i = 0;
}

int main(void) {
  int i = 1;
  f(&i);
  return i;
}

The object is defined at "int i = 1;". The type of the pointer does not
change this. The relevant citation is 6.7.3p5: "If an attempt is made to
modify an object defined with a const-qualified type through use of an
lvalue with non-const-qualified type, the behavior is undefined." The types
that matter are the type of the object (int), and the type of the lvalue
(int), not types of intermediate pointers.

I would not at all mind if this changed so that the program becomes invalid,
though.
 
K

Keith Thompson

Harald van Dijk said:
Keith said:
Harald van Dijk said:
Compilers are not allowed to assume that functions accepting
pointer-to-const arguments will not modify the pointed-to objects. puts
is not allowed to write to its input string because and only because this
is not part of its function description.
[...]

I believe compilers are allowed to make that assumption. Yes, the
function itself can cast away the const qualification, but any attempt
to modify a const-qualified object invokes undefined behavior.

The object was not const-qualified.

void f(const int *i) {
  *(int *) i = 0;
}

int main(void) {
  int i = 1;
  f(&i);
  return i;
}

The object is defined at "int i = 1;". The type of the pointer does not
change this. The relevant citation is 6.7.3p5: "If an attempt is made to
modify an object defined with a const-qualified type through use of an
lvalue with non-const-qualified type, the behavior is undefined." The types
that matter are the type of the object (int), and the type of the lvalue
(int), not types of intermediate pointers.

I think you're right.
I would not at all mind if this changed so that the program becomes invalid,
though.

Agreed.
 
R

Richard Bos

Chris Hills said:
The calendar has NEVER been based on the Christian faith.
BTW Ask many Christians and they will tell you that JC was born on
varying dates from -10 to + 30 so you Richard are self delusional.
There are precious few historical facts that wil support your
assertations

Since to deal with the multitude of misconceptions, half-understandings,
and plain errors in your post would indeed be grossly off-topic, I'll
just correct your main mistake, which is that I never claimed that the
fact that it is 2007 today has anything to do with the real birthdate of
any Jesus ben Josef in whose existence you may or may not believe, but
only with the faith _based upon_ that (supposed) life; specifically,
with the (erroneous!) calculations of an early-mediaeval monk concerning
that birth date, which he, at least, believed to be literally true.

Richard
 
P

Peter 'Shaggy' Haywood

Groovy hepcat Richard Tobin was jivin' on 29 Jun 2007 14:17:43 GMT in
comp.lang.c.
Re: reply the answer's a cool scene! Dig it!
No, and it's nothing to do with C99's main() exception.

C90 says:

If a return statement without an expression is executed, and the value
of the function call is used by the caller, the behavior is undefined.
Reaching the } that terminates a function is equivalent to executing a
return statement without an expression.

Since the return value of main() is presumably used (to return the
value to the operating system), it would be undefined behaviour to
not have a return in main *if you reached the end of the function*.
But if you call exit() instead, the question does not arise.

Yes, I think you're right. I was confusing what C90 says about
non-void functions without a return statement (basically, the above)
with what C99 says (that it's not allowed). The code in question was
C90 conforming after all, I guess. And I stand, once again, corrected.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
K

Keith Thompson

Yes, I think you're right. I was confusing what C90 says about
non-void functions without a return statement (basically, the above)
with what C99 says (that it's not allowed). The code in question was
C90 conforming after all, I guess. And I stand, once again, corrected.

Where does C99 say that a non-void function without a return statement
is not allowed? The closest thing I can find is C99 6.9.1p12:

If the } that terminates a function is reached, and the value of
the function call is used by the caller, the behavior is
undefined.

Note that the behavior is undefined only if the caller actually
attempts to uses the result.

Also, C99 6.8.6.4 says:

A return statement with an expression shall not appear in a
function whose return type is void. A return statement without an
expression shall only appear in a function whose return type is
void.

That's a constraint, but it says nothing about missing return
statements.
 
M

Mark McIntyre

Where does C99 say that a non-void function without a return statement
is not allowed? The closest thing I can find is C99 6.9.1p12:

If the } that terminates a function is reached, and the value of
the function call is used by the caller, the behavior is
undefined.

This does the trick though, when you think about it. To reach the
closing } you must have encountered no return statements.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
K

Keith Thompson

Mark McIntyre said:
This does the trick though, when you think about it. To reach the
closing } you must have encountered no return statements.

But there are ways to leave a function without encountering either a
return statement or the closing }. Or you avoid the issue by not
calling the function.

The statement at issue, from upthread, posted by Peter 'Shaggy' Haywood, was:

Yes, I think you're right. I was confusing what C90 says about
non-void functions without a return statement (basically, the
above) with what C99 says (that it's not allowed). The code in
question was C90 conforming after all, I guess. And I stand, once
again, corrected.

I took that to mean that he thought that C99 requires every non-void
function to have a return statement somewhere in its definition, and
that a non-void function without a return statement would be a
constraint violation. There is no such requirement in C99 (though
some languages do have such a requirement).
 
M

Mark McIntyre

But there are ways to leave a function without encountering either a
return statement or the closing }.

Care to post some examples? If you jump out of the function via a
signal (lets exclude radical methods such as invoking a bus error)
then you are definitionally leaving its scope which is probably what
is meant.
Or you avoid the issue by not
calling the function.

Ok, but in that case the compiler can optimise it out and there's no
issue.
that a non-void function without a return statement would be a
constraint violation.

I think you're right that its not a constraint violation.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
K

Keith Thompson

Mark McIntyre said:
Care to post some examples? If you jump out of the function via a
signal (lets exclude radical methods such as invoking a bus error)
then you are definitionally leaving its scope which is probably what
is meant.

longjmp(), exit(), _Exit(), abort().

Or you can *not* leave the function:

int foo(void)
{
while (1) {
}
}
Ok, but in that case the compiler can optimise it out and there's no
issue.

Sure there is. If a return statement were required, a non-void
function without a return statement would have to be diagnosed whether
it's called or not. The possibility of optimization doesn't affect
legality.
 
M

Mark McIntyre

longjmp(), exit(), _Exit(), abort().

Fair enough. In all these cases, the return value isn't used and I
guess you haven't reached the closing }

So are we saying that there is /nothing/ that requires a function to
return a matching type, provided the return is guaranteed never used?
Or you can *not* leave the function:

Fair point! Though why on earth one would define such a function as
returning /anything/ is beyond me...
Sure there is. If a return statement were required, a non-void
function without a return statement would have to be diagnosed whether
it's called or not. The possibility of optimization doesn't affect
legality.

Not so sure about this. The compiler can apply the "as if" rule and
simply remove the code entirely, irrespective of any optimisation.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 

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
473,774
Messages
2,569,596
Members
45,137
Latest member
NoelAshwor
Top