Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Compiling a simple C++ program doesn't work

80 views
Skip to first unread message

Alan

unread,
Jan 17, 2001, 7:56:41 AM1/17/01
to
Hello
I'm trying to write a C++ program that uses basename
to get the name of its self

*********** test.cpp ************
#include <iostream.h>
#include <string.h>

int main(int argc, char **argv)
{
cout << basename(argv[0]) << endl;

return 0;
}
*****************************

though when I try and compile it using g++ it tells me
test.cpp: In function `int main(int, char **)':
test.cpp:6: warning: implicit declaration of function `int basename(...)'
when it's defined in <string.h>. If I include
extern "C" char *basename __P ((__const char *__filename));
at the top of the program it works fine, why?
Whats going on that should cause this, is there
a reason behind it???

One other thing, I've used DJGPP and that's how I decided
to start writing code for Linux. There were two functions
available in <dir.h> called 'fnsplit' and 'fnmerge' that split/merged
a path name to/from drive, path, file, ext components. I thought
DJGPP was supposed to be a DOS port of gcc etc..? All I need
that function for is to chop of the ext part and add a new one.
Are there any similar functions available under Linux,
I'm using Slackware 7.0

Thanks for your help
Alan

Mark Zeilenga

unread,
Jan 17, 2001, 9:03:36 AM1/17/01
to
My experience with the first error might be that your main function should
look like this:

int main(int argc, char *argv[])


Mark Zeilenga
RH7


Chris

unread,
Jan 17, 2001, 9:10:29 AM1/17/01
to
Alan wrote:
>
> Hello
> I'm trying to write a C++ program that uses basename
> to get the name of its self
>
> *********** test.cpp ************
> #include <iostream.h>
> #include <string.h>
>
> int main(int argc, char **argv)
> {
> cout << basename(argv[0]) << endl;
>
> return 0;
> }
> *****************************
>
> though when I try and compile it using g++ it tells me
> test.cpp: In function `int main(int, char **)':
> test.cpp:6: warning: implicit declaration of function `int basename(...)'
> when it's defined in <string.h>. If I include
> extern "C" char *basename __P ((__const char *__filename));
> at the top of the program it works fine, why?
> Whats going on that should cause this, is there
> a reason behind it???

It looks like you need to have defined __USE_GNU
to get this function. It seems that basename is
a GNU extension; you should write your own version
of the function if you want your program to be
portable.

> One other thing, I've used DJGPP and that's how I decided
> to start writing code for Linux. There were two functions
> available in <dir.h> called 'fnsplit' and 'fnmerge' that split/merged
> a path name to/from drive, path, file, ext components. I thought
> DJGPP was supposed to be a DOS port of gcc etc..? All I need
> that function for is to chop of the ext part and add a new one.
> Are there any similar functions available under Linux,

Not really, but Unix file specifications are simpler
than DOS ones. You should be able to get away with
using the <string.h> functions to manipulate them.

There are no drive letters in Unix, and file extensions
or suffices are simply a convention -- they do not have
any of the special meanings they have in DOS or Windows.

--
Chris Lightfoot -- http://www.ex-parrot.com/~chris/
ignore From: line; try "chris at ex hyphen parrot dot com"
The ship sank, the South lost and the sled got tossed in the fire.
Get over it.

Mark Greatrix

unread,
Jan 17, 2001, 10:02:58 AM1/17/01
to
> extern "C" char *basename __P ((__const char *__filename));
> at the top of the program it works fine, why?

It looks as though it's being 'ifndeffed' out, from string.h..

# ifndef basename
/* Return the file name within directory of FILENAME. We don't
declare the function if the `basename' macro is available (defined
in <libgen.h>) which makes the XPG version of this function
available. */
extern char *basename __P ((__const char *__filename));
# endif

It may be something to do with your compiler options, but as a test try
'#undef basename' before '#include <string.h>' in your code and give it
a try.

MG
--

The mind is not a vessel to be filled, but a fire to be kindled.
-Plutarch

Chris

unread,
Jan 17, 2001, 10:42:49 AM1/17/01
to
Mark Greatrix wrote:
>
> > extern "C" char *basename __P ((__const char *__filename));
> > at the top of the program it works fine, why?
>
> It looks as though it's being 'ifndeffed' out, from string.h..

Yes.

> # ifndef basename
> /* Return the file name within directory of FILENAME. We don't
> declare the function if the `basename' macro is available (defined
> in <libgen.h>) which makes the XPG version of this function
> available. */
> extern char *basename __P ((__const char *__filename));
> # endif
>
> It may be something to do with your compiler options, but as a test try
> '#undef basename' before '#include <string.h>' in your code and give it
> a try.

No, there is another #ifdef which encloses it:
__USE_GNU.

By default, it turns out this is on for C on
my machine, but not for C++. This could well
be true on the original poster's machine too.

--
Chris Lightfoot -- chris at ex dash parrot dot com --
www.ex-parrot.com/~chris/
"Life is like a sewer. What you get out of it
depends on what you put in to it." (Tom Lehrer)

Eric P. McCoy

unread,
Jan 17, 2001, 12:19:07 PM1/17/01
to
"Mark Zeilenga" <zeile...@cs.com> writes:

> My experience with the first error might be that your main function should
> look like this:
> int main(int argc, char *argv[])

On all the compilers I've used, it doesn't matter. That's not to say
that you're wrong, necessarily; using `char **' instead might actually
be undefined. But `char **' will work, at least, and is not the cause
of his problem.

--
Eric McCoy <emc...@hamilton.edu>
"Knowing that a lot of people across the world with Geocities sites
absolutely despise me is about the only thing that can add a positive
spin to this situation." - Something Awful, 1/11/2001

Erik Max Francis

unread,
Jan 17, 2001, 12:28:58 PM1/17/01
to
"Eric P. McCoy" wrote:

> On all the compilers I've used, it doesn't matter. That's not to say
> that you're wrong, necessarily; using `char **' instead might actually
> be undefined. But `char **' will work, at least, and is not the cause
> of his problem.

Actually, it's perfectly legal. In an argument of a function
declaration (which main most assuredly is), an array of T is treated
identically to a pointer to T -- if you use an array, the compiler
really sees a pointer. This is the only situation in which pointers and
arrays are truly equivalent, and it's because in this one case the
declaration of an array is transmogrified into a declaration of a
pointer.

int main(int argc, char *argv[]);

and

int main(int argc, char **argv);

are in every way equivalent.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ Will I disappoint my future / If I stay
\__/ Sade
Computer science / http://www.alcyone.com/max/reference/compsci/
A computer science reference.

Joe Pfeiffer

unread,
Jan 17, 2001, 3:10:24 PM1/17/01
to
Erik Max Francis <m...@alcyone.com> writes:
>
> int main(int argc, char *argv[]);
>
> and
>
> int main(int argc, char **argv);
>
> are in every way equivalent.

Minor quibble: if you use **argv, you can do things like

argv[3] = 7;

and the compiler will let you get away with it, even though it's
messing up the arg list. Unless you definitely know you want to do
something weird to the arg list, it's safer to say *argv[] (which
still leaves plenty of ways for you to screw things up by accident,
but at least one less than before!).
--
Joseph J. Pfeiffer, Jr., Ph.D. Phone -- (505) 646-1605
Department of Computer Science FAX -- (505) 646-1002
New Mexico State University http://www.cs.nmsu.edu/~pfeiffer
VL 2000 Homepage: http://www.cs.orst.edu/~burnett/vl2000/

Kaz Kylheku

unread,
Jan 17, 2001, 3:25:36 PM1/17/01
to
On 17 Jan 2001 13:10:24 -0700, Joe Pfeiffer <pfei...@cs.nmsu.edu> wrote:
>Erik Max Francis <m...@alcyone.com> writes:
>>
>> int main(int argc, char *argv[]);
>>
>> and
>>
>> int main(int argc, char **argv);
>>
>> are in every way equivalent.
>
>Minor quibble: if you use **argv, you can do things like
>
>argv[3] = 7;

I don't know where you got this impression. If you declare it as char
*argv[], you can also write argv[3]. The two are equivalent; both
declare a pointer to an object that may be the first element of an
array of unknown size.

Kaz Kylheku

unread,
Jan 17, 2001, 3:26:28 PM1/17/01
to
On 17 Jan 2001 13:10:24 -0700, Joe Pfeiffer <pfei...@cs.nmsu.edu> wrote:
>> int main(int argc, char **argv);
>>
>> are in every way equivalent.
>
>Minor quibble: if you use **argv, you can do things like
>
>argv[3] = 7;

By the way, you most certainly cannot do this, since argv[3] is a
pointer. Assigning the value 7 to a pointer is a constraint violation.

Grant Edwards

unread,
Jan 17, 2001, 3:54:52 PM1/17/01
to
In article <1br922y...@viper.cs.nmsu.edu>, Joe Pfeiffer wrote:
>Erik Max Francis <m...@alcyone.com> writes:
>>
>> int main(int argc, char *argv[]);
>>
>> and
>>
>> int main(int argc, char **argv);
>>
>> are in every way equivalent.
>
>Minor quibble: if you use **argv, you can do things like
>
>argv[3] = 7;
>
>and the compiler will let you get away with it, even though it's
>messing up the arg list. Unless you definitely know you want to do
>something weird to the arg list, it's safer to say *argv[] (which
>still leaves plenty of ways for you to screw things up by accident,
>but at least one less than before!).

The C++ semantics must differ from the C semantics, since
declaring an argument as

foo(char arg[])

used to be defined to be semantically identical to

foo(char *arg)

--
Grant Edwards grante Yow! My vaseline is
at RUNNING...
visi.com

Joe Pfeiffer

unread,
Jan 17, 2001, 6:58:20 PM1/17/01
to
k...@ashi.footprints.net (Kaz Kylheku) writes:

Oops. You're right, I'm wrong.

Erik Max Francis

unread,
Jan 17, 2001, 10:47:48 PM1/17/01
to
Joe Pfeiffer wrote:

> Minor quibble: if you use **argv, you can do things like
>
> argv[3] = 7;
>
> and the compiler will let you get away with it, even though it's
> messing up the arg list.

This isn't correct. If argv is a char **, then argv[3] is of type char
*, so assigning an int to it is an error.

> Unless you definitely know you want to do
> something weird to the arg list, it's safer to say *argv[] (which
> still leaves plenty of ways for you to screw things up by accident,
> but at least one less than before!).

As I said, in a function declaration, the compiler translates any array
notation to a pointer. So any error that gets past the compiler will be
because it's seeing a pointer, not an array!

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Every path has its puddle.
\__/ (an English proverb)
Esperanto reference / http://mirror/alcyone/max/lang/esperanto/
An Esperanto reference for English speakers.

D. Stimits

unread,
Jan 18, 2001, 12:17:02 AM1/18/01
to
There have been a lot of answers here, but something that might simplify
a few things is that you should
#include <iostream> // not iostream.h
#include <string> // not string.h

You'll find these are in /usr/include/g++-2/ (or g++-3), and that you
don't need to name g++-2 since g++ understands this as a standard search
location for C++. There is only one iostream.h which it can find, but
you are probably running into a failure when it finds the C version of
string.h, rather than the C++ version. Always try to use the version
that wraps things without the ".h" if they exist.

Alan

unread,
Jan 18, 2001, 5:42:40 AM1/18/01
to
Chris <ch...@x.invalid> wrote:
> > It may be something to do with your compiler options, but as a test try
> > '#undef basename' before '#include <string.h>' in your code and give it
> > a try.
>
> No, there is another #ifdef which encloses it:
> __USE_GNU.
>
> By default, it turns out this is on for C on
> my machine, but not for C++. This could well
> be true on the original poster's machine too.
True, but you can't define __USE_GNU as each header includes
a file called <features.h> which turns off all of these.
I had to define _GNU_SOURCE for it to work.

Alan

Chris

unread,
Jan 18, 2001, 9:58:43 AM1/18/01
to
Alan wrote:
>
> Chris <ch...@x.invalid> wrote:
> > > It may be something to do with your compiler options, but as a test try
> > > '#undef basename' before '#include <string.h>' in your code and give it
> > > a try.
> >
> > No, there is another #ifdef which encloses it:
> > __USE_GNU.
> >
> > By default, it turns out this is on for C on
> > my machine, but not for C++. This could well
> > be true on the original poster's machine too.
> True, but you can't define __USE_GNU as each header includes
> a file called <features.h> which turns off all of these.
> I had to define _GNU_SOURCE for it to work.

Ah, yes, that sounds right. Mea culpa.

That said, do you _want_ the GNU extensions? I
would have thought that the answer is probably
"no".

--
Chris Lightfoot -- chris at ex dash parrot dot com --
www.ex-parrot.com/~chris/

"Smile," someone said. "It could be worse." So I did, and it was.

0 new messages