473,385 Members | 1,912 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Watcom vs. gcc/icl/cl difference

I've just been trying out the Watcom compiler from
http://www.openwatcom.org, and almost immediately compiled some working
source that errored.

The code is

char buffer[1000];

...

if(opt & out_std)
{
fputs(&buffer, stdout);
}

Note that &buffer should [ideally] have been either &buffer[0] or just plain
buffer.

However, the same code compiles cleanly using gcc (ecven when
using -pedantic), icl, and MS's cl compilers.

In the c99 std it has the following:
6.5.3.2 Address and indirection operators

Constraints

1 The operand of the unary & operator shall be either a function designator,
the result of a

[] or unary * operator, or an lvalue that designates an object that is not a
bit-field and is

not declared with the register storage-class specifier.

I'm interpreting the beginning of this as saying that the follow are valid:

char array[1];

int n;

int * p;

&array[0];

&n;

&*p;

However, I can't find anything that says that [say] puts(&buffer) is valid.

So, any comments?


Nov 15 '05 #1
8 4416
"pemo" <us************@gmail.com> wrote in message
news:di**********@news.ox.ac.uk...
I've just been trying out the Watcom compiler from
http://www.openwatcom.org, and almost immediately compiled some working
source that errored.

The code is

char buffer[1000];

...

if(opt & out_std)
{
fputs(&buffer, stdout);
}

Note that &buffer should [ideally] have been either &buffer[0] or just plain buffer.


fputs() takes pointer to a char, not pointer to a buffer, hence either
buffer
or
&buffer[0]
is what you must pass to fputs().

&buffer has a different type, a pointer to a buffer of 1000 chars,
(*)[1000].

Correct example:
{
char b[100];
char (*p1)[100] = &b;
char* p2 = b;
}
Incorrect example:
{
char b[100];
char (*p1)[100] = b;
char* p2 = &b;
}

Alex
Nov 15 '05 #2
pemo wrote:
I've just been trying out the Watcom compiler from
http://www.openwatcom.org, and almost immediately compiled some working
source that errored.

The code is

char buffer[1000];

...

if(opt & out_std)
{
fputs(&buffer, stdout);
}

Note that &buffer should [ideally] have been either &buffer[0] or just plain
buffer.

However, the same code compiles cleanly using gcc (ecven when
using -pedantic), icl, and MS's cl compilers.

<snip>

gcc --version

gcc (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is
NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

foo.c:
#include <stdio.h>

void foo() {
char buffer[1000];

fputs(&buffer, stdout);
}

gcc -c test.c

foo.c: In function `foo':
foo.c:6: warning: passing arg 1 of `fputs' from incompatible pointer type

What version of gcc are you using? This isn't what I call "compiling
cleanly".

S.
Nov 15 '05 #3
Skarmander wrote:
<snip>
gcc -c test.c

foo.c: In function `foo':


Heh. I know I should have attached a screendump!

S.
Nov 15 '05 #4


pemo wrote On 10/07/05 13:18,:
I've just been trying out the Watcom compiler from
http://www.openwatcom.org, and almost immediately compiled some working
source that errored.

The code is

char buffer[1000];

...

if(opt & out_std)
{
fputs(&buffer, stdout);
}

Note that &buffer should [ideally] have been either &buffer[0] or just plain
buffer.

However, the same code compiles cleanly using gcc (ecven when
using -pedantic), icl, and MS's cl compilers.


If a correct prototype for fputs() is in scope, a
diagnostic is required. Since the code uses `stdout'
as an identifier, it is 99.44% likely that <stdio.h>
has been included (and 0.56% likely that the code is
utterly, hopelessly bogus). If <stdio.h> was included,
a correct prototype for fputs() should be in scope.
Therefore, it is 99.44% likely that all the compilers
(or the headers) are broken.

... or is it just faintly possible that the code you
show isn't the code you fed to the compilers? Since what
you've shown won't compile on any C compiler I have access
to or have ever heard of, we cannot rule out that faint
possibility, can we? Would you consider posting *real*
code instead of a half-baked hacked-up paraphrase?

--
Er*********@sun.com

Nov 15 '05 #5
> gcc (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

foo.c:
#include <stdio.h>

void foo() {
char buffer[1000];

fputs(&buffer, stdout);
}

gcc -c test.c

foo.c: In function `foo':
foo.c:6: warning: passing arg 1 of `fputs' from incompatible pointer type

What version of gcc are you using? This isn't what I call "compiling
cleanly".


Interesting! I'm using Dev-C++ and, according to a gcc -v in \dev-cpp\bin
it's also 3.4.2.

Ahhhhh - very red faced!

In an attempt to show a clean example, I [um] edited out a cast!

fputs((const char *)&buffer, echoFP);

Ok lesson learned - like I can now see why that wasn't such a great idea!

However - I say to myself "well, in that case, that line of code was surely
never executed!". So, I took out the newly inserted [0], and put it back to
its original and inserted an extra puts():

puts("yup");
fputs((const char *)&buffer, echoFP);

The code runs fine.

Here's the whole function [probably going to regret this; although it's not
my code!] - used as a kind of printf/fprint etc.
/* Used to output stuff to the console and, optionally, to a file.
*/
static void out(int opt, const char * format, ...)
{
/* Potential for buffer overrun here: but *unlikely*. Maybe work a
decent malloc in here in the future though!
*/
auto char buffer[1000];

auto va_list ap;

va_start(ap, format);
/* Output to buffer according to what's passed in format and ap (no
matter what).
*/
vsprintf(&buffer[0], format, ap);

/* stdout output.
*/
if(opt & out_std)
{
puts("here");
fputs((const char *)&buffer, stdout);
}

/* File output if fp points to something.
*/
if(opt & out_fle)
{
if(echoFP != NULL)
{
fputs(&buffer[0], echoFP);
fflush(echoFP);
}
else
{
out(out_err, "function 'out' called with out_fle, but file
pointer is invalid!");
}
}

/* stderr output.
*/
if(opt & out_err)
{
fputs((const char *)&buffer[0], stderr);
}

/* Invalid flags given? This is not a totally exhaustive test as
opt_??? are
static const int out_std = 1;
static const int out_err = 2;
static const int out_fle = 4;
static const int out_reg = out_std | out_fle;
static const int opt_all = out_err | out_std | out_fle;
*/
if(opt < 1 || opt > opt_all)
{
/* Better report this!
*/
out(out_err, "function 'out' called using opt of %d: which is
invalid", opt);
}

fflush(stdout);
fflush(stderr);

va_end(ap);
}

Nov 15 '05 #6

"Eric Sosman" <er*********@sun.com> wrote in message
news:di**********@news1brm.Central.Sun.COM...


pemo wrote On 10/07/05 13:18,:
I've just been trying out the Watcom compiler from
http://www.openwatcom.org, and almost immediately compiled some working
source that errored.

The code is

char buffer[1000];

...

if(opt & out_std)
{
fputs(&buffer, stdout);
}

Note that &buffer should [ideally] have been either &buffer[0] or just
plain
buffer.

However, the same code compiles cleanly using gcc (ecven when
using -pedantic), icl, and MS's cl compilers.
If a correct prototype for fputs() is in scope, a
diagnostic is required. Since the code uses `stdout'
as an identifier, it is 99.44% likely that <stdio.h>
has been included (and 0.56% likely that the code is
utterly, hopelessly bogus). If <stdio.h> was included,
a correct prototype for fputs() should be in scope.
Therefore, it is 99.44% likely that all the compilers
(or the headers) are broken.

... or is it just faintly possible that the code you
show isn't the code you fed to the compilers? Since what
you've shown won't compile on any C compiler I have access
to or have ever heard of, we cannot rule out that faint
possibility, can we? Would you consider posting *real*
code instead of a half-baked hacked-up paraphrase?


stdio in scope -
Would you consider posting *real*
code instead


full function code shown in other post
Nov 15 '05 #7
pemo wrote:
gcc (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

foo.c:
#include <stdio.h>

void foo() {
char buffer[1000];

fputs(&buffer, stdout);
}

gcc -c test.c

foo.c: In function `foo':
foo.c:6: warning: passing arg 1 of `fputs' from incompatible pointer type

What version of gcc are you using? This isn't what I call "compiling
cleanly".

Interesting! I'm using Dev-C++ and, according to a gcc -v in \dev-cpp\bin
it's also 3.4.2.

Ahhhhh - very red faced!

In an attempt to show a clean example, I [um] edited out a cast!

fputs((const char *)&buffer, echoFP);

*rolls eyes*
Ok lesson learned - like I can now see why that wasn't such a great idea!

However - I say to myself "well, in that case, that line of code was surely
never executed!". So, I took out the newly inserted [0], and put it back to
its original and inserted an extra puts():

puts("yup");
fputs((const char *)&buffer, echoFP);

The code runs fine.
Does it now? Is (opt & out_fle) true when the function is called? What
file is being written to? Open it and see if it contains what you expect
or garbage.

My money's on the latter.

&buffer points to valid memory. It just doesn't point to what it should
point: the contents of buffer. Instead it points to the variable buffer
itself, which is probably somewhere on the stack. fputs() will try to
interpret this as a string, which has a good chance of succeeding, since
the stack will probably contain a NUL somewhere and end the output
before things can get too bad.
Here's the whole function [probably going to regret this; although it's not
my code!] - used as a kind of printf/fprint etc.
/* Used to output stuff to the console and, optionally, to a file.
*/
static void out(int opt, const char * format, ...)
{
/* Potential for buffer overrun here: but *unlikely*. Maybe work a
decent malloc in here in the future though!
*/
auto char buffer[1000];
auto? Now there's something you don't see every day. The comment is, of
course, lame. "In the future" means "never", or "when disaster has
struck". :-)
auto va_list ap;

va_start(ap, format);

/* Output to buffer according to what's passed in format and ap (no
matter what).
*/
vsprintf(&buffer[0], format, ap);
Should be
vsnprintf(buffer, sizeof buffer, format, ap);
to prevent overflow.

va_end should go here. See later.
/* stdout output.
*/
if(opt & out_std)
{
puts("here");
fputs((const char *)&buffer, stdout);
Wrong. Bad. Evil. Should indeed be buffer or &buffer[0] if you insist.
Since this was done right not a few lines ago I have no clue why this
was messed up. Sounds like a case of "compiler complains, let me insert
a cast rather than looking at the solution".
}

/* File output if fp points to something.
*/
if(opt & out_fle)
{
if(echoFP != NULL)
{
fputs(&buffer[0], echoFP);
fflush(echoFP);
}
else
{
out(out_err, "function 'out' called with out_fle, but file
pointer is invalid!");
Function calls itself which is mildly dangerous. If ever a mistake is
made in invoking the function for reporting an error in the function,
the recursion will never end. This is not as far-fetched as it sounds.

Function should be split up. More maintainable and more versatile.
}
}

/* stderr output.
*/
if(opt & out_err)
{
fputs((const char *)&buffer[0], stderr);
Cast should be removed.
}

/* Invalid flags given? This is not a totally exhaustive test as
opt_??? are
static const int out_std = 1;
static const int out_err = 2;
static const int out_fle = 4;
static const int out_reg = out_std | out_fle;
static const int opt_all = out_err | out_std | out_fle;
*/
if(opt < 1 || opt > opt_all)
{
/* Better report this!
*/
out(out_err, "function 'out' called using opt of %d: which is
invalid", opt);
}

fflush(stdout);
fflush(stderr);
Silly. Why is the file flushed in the if-branch in case of (opt &
out_file), but not stdout and stderr? Lines should be moved to the
relevant places.
va_end(ap);


va_end should appear as near to va_start as possible, to prevent
mistakes. There's no need to defer it to the end of the function.

S.
Nov 15 '05 #8
"pemo" <us************@gmail.com> writes:
gcc (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

foo.c:
#include <stdio.h>

void foo() {
char buffer[1000];

fputs(&buffer, stdout);
}

gcc -c test.c

foo.c: In function `foo':
foo.c:6: warning: passing arg 1 of `fputs' from incompatible pointer type

What version of gcc are you using? This isn't what I call "compiling
cleanly".


Interesting! I'm using Dev-C++ and, according to a gcc -v in \dev-cpp\bin
it's also 3.4.2.

Ahhhhh - very red faced!

In an attempt to show a clean example, I [um] edited out a cast!

fputs((const char *)&buffer, echoFP);

Ok lesson learned - like I can now see why that wasn't such a great idea!


Yes, that was a bad idea -- but let's look into why it seems to work.
(You might already know this.)

The expression "buffer" (without the quotes, of course) is an array
name, which is automatically converted to a pointer to the array's
first element. In this case, it's of type char*, which is exactly
what you need for the first argument to fputs. So what you really
want is
fputs(buffer, stdout);
or
fputs(buffer, echoFP);

An array name is *not* converted to a pointer to its first element
if it's the operand of a unary "&" or "sizeof" operator. So &buffer
is a pointer to the array, not to its first element; the type is
char(*)[1000], or pointer-to-array-of-1000-char. You then cast
this pointer to "const char *", which almost certainly gives you
a pointer to the first element of the array. The expressions
"buffer" and "&buffer" are of different types (pointer-to-char
vs. pointer-to-array), but they both (loosely speaking) have the same
value, the address of the first byte of the object "buffer".

Incidentally, the "const" is superfluous; the formal parameter is
declared const, but the actual argument doesn't need to be.

There might be cases where the conversion from pointer-to-array
to pointer-to-char might not give you the value you want. I'm too
lazy to analyze the wording of the standard to determine just what's
guaranteed and what isn't -- and you probably should be as well.
Just use "buffer"; it's both simpler and safer.

Also, the first argument to fputs is expected to be a pointer to
a string (i.e., it needs to be terminated with a '\0' character).
I'm too lazy to go through the code you posted to confirm that buffer
will always be properly terminated -- but you shouldn't be.

One more thing: the "auto" keyword is a relic of ancient C history.
There never any need to use it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Philipp Claßen | last post by:
Hallo! Do you think the open watcom compiler will offer fully support of the C++ STL in near future? Thanks, Phil
18
by: Agent Mulder | last post by:
Hi group, I am looking for the BEST C++ compiler that holds the 3f criterium: * free * flat * fast Free means that I am free to sell the software I write with it. Flat means that...
1
by: Spike | last post by:
Can Watcom 1.2 compile it's source to ELF and if so how? TIA!! //SPike
0
by: Basat | last post by:
I need to purchase Watcom c/c++ version 10.5 compiler. If you have a used copy, just email me the price. I need license and the old cd or disk etc. regards Basat Khalifa...
1
by: just4me | last post by:
I would like to access the bios flash using watcom c. To start, I would like to be able to read the entire bios and back it up into a file. I can do everything except reading the bios flash. Any...
1
by: bine | last post by:
Sorry, I found a lot of old stuff, even kind of flamewars about good+bad style whatsoever.. I simply want any hint that works! I try to migrate older stuff from NT and newer stuff from...
3
by: Vincent | last post by:
Hello, I'm sorry if this is a little OT, but I've posted this on the Open Watcom user group but still haven't gotten any replies. It is like they are ignoring me. Maybe there is Open Watcom...
5
by: Nickolai Leschov | last post by:
Hello, I want to tried to use Open Watcom for programming my i188, and I have a couple of questions. How do I make simple project compile? I created a project with DOS target ( " DOS - 16 bit...
7
by: Nickolai Leschov | last post by:
Does anyone at all use Open Watcom? I have a couple of issues I have to iron out before I can get to work. The newsgroup seems to be long dead (server doesn't respond) Nickolai
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.