I'd like to make an object global but my linker is playing hard to
get.
Here's a stripped down example:
obj.c ===============
struct object_t
{
int id;
char * name;
};
object
new_object()
{
object this;
this = calloc(1, sizeof(struct object_t));
/* [etc ..] */
return this;
}
obj.h ===============
#ifndef __object_h
#define __object_h
typedef struct object *object;
object new_object();
/* [etc...] */
#endif/*__object_h*/
main.c ===============
include <object.h>
int
main(int argc, char *argv[])
{
object obj = new_object();
/* [etc ...] */
return 0;
}
setup.h ===============
extern object obj;
sock.c ===============
sock
new_socket()
{
int thing = object_get_something(obj); /* compiles but doesn't link
*/
}
I get the following linking error:
sock.c:69: undefined reference to `obj'
If this is obvious, I apologize. I've been spending a lot of time in
php and my C has gotten rusty.
Cheers,
Jeff
> I'd like to make an object global but my linker is playing hard to
> get.
> Here's a stripped down example:
> obj.c ===============
> struct object_t
> {
> int id;
> char * name;
> };
> object
> new_object()
> {
> object this;
> this = calloc(1, sizeof(struct object_t));
> /* [etc ..] */
> return this;
> }
I guess you have stripped too much. This will already trip up
the compiler since 'object' is not declared, defined or typedef'ed
here. So aleady the line
object new_object()
should make the compiler complain unless you have snipped
something like
#include "obj.h"
> obj.h ===============
> #ifndef __object_h
> #define __object_h
> typedef struct object *object;
> object new_object();
> /* [etc...] */
> #endif/*__object_h*/
In C empty parentheses in a function declaration do not mean
that the function does not take arguments but that you just don't
want to tell the compiler. And the the compiler must assume that
the function could take any number of arguments and thus can't
warn you if you pass it the wrong ones. So better make that
object new_object( void );
Also a lot of people (including me) aren't very happy with
tyoedef'ing pointers. I would recommend that at a maximum
you just do
typedef struct object object;
object * new_object( );
That makes it immediately clear that what the function
returns is a pointer (and thus has to be treated as one)
and not a simple variable. (And then some people are even
more or less vehemently against typedef'ing structures...)
> main.c ===============
> include <object.h>
> int
> main(int argc, char *argv[])
> {
> object obj = new_object();
> /* [etc ...] */
> return 0;
> }
> setup.h ===============
> extern object obj;
> sock.c ===============
> sock
> new_socket()
> {
> int thing = object_get_something(obj); /* compiles but doesn't link
> */
> }
> I get the following linking error:
> sock.c:69: undefined reference to `obj'
Again, this already should have gotten the compiler angry at
you since 'obj' is nowhere defined or declared in sock.c.
Also 'sock' is unknown.
> If this is obvious, I apologize. I've been spending a lot of time in
> php and my C has gotten rusty.
I guess you better try again with a compilable (but not nece-
sarrily linkable) program, because yours is obviously so
stripped down that it's impossible to say for sure what the
linker complains about in the real program. It might just be
a forgotten '#include setup.h' in sock.c but that's pure guess-
work and could be completely wrong.
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de
That's not necessarily a disastrous decision. Nevertheless, I would
suggest you think twice about it, or perhaps three or four times.
> but my linker is playing hard to
> get.
>
> Here's a stripped down example:
>
> obj.c ===============
>
<snip>
> obj.h ===============
> #ifndef __object_h
Almost all identifiers with leading underscores are reserved for the
implementation. The (slightly over-restrictive, but very easy to
remember) rule of thumb is: don't use 'em.
If you must have underscore decorations, use trailers, not leaders:
#ifndef object_h__
#define object_h__
> #define __object_h
> typedef struct object *object;
It's generally a bad idea to hide pointeriness behind a typedef. Not
illegal, just generally a bad idea. People find pointers hard enough as
it is, even without the disguise!
> object new_object();
>
> /* [etc...] */
>
> #endif/*__object_h*/
>
>
> main.c ===============
>
> include <object.h>
object obj; /* need a definition somewhere at file scope (see below) */
>
> int
> main(int argc, char *argv[])
> {
> object obj = new_object();
obj = new_object(); /* definition needs to be at file scope, not
block scope, if it's to be visible from other translation units */
> /* [etc ...] */
> return 0;
> }
>
> setup.h ===============
>
> extern object obj;
This is a declaration (which is fine, and indeed necessary for
"exporting" the symbol), but it is not a definition (see above).
>
> sock.c ===============
#include "setup.h" /* you need to show the compiler the obj type */
>
> sock
> new_socket()
> {
> int thing = object_get_something(obj); /* compiles but doesn't link
> */
> }
>
> I get the following linking error:
> sock.c:69: undefined reference to `obj'
>
> If this is obvious, I apologize. I've been spending a lot of time in
> php and my C has gotten rusty.
It /is/ obvious, but only to people to whom it's obvious. To everyone
else, it's rather obscure.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
I have a stripped down working example here:
ftp://ftp.joedog.org/pub/example.tar.gz
=== Makefile ===
all:
gcc -I. -Wall -w -g -o haha main.c object.c sock.c
clean:
rm haha
=== setup.h ===
#ifndef setup_h
#define setup_h
#include <object.h>
extern object obj;
#endif/*setup_h*/
=== main.c ===
#include <setup.h>
#include <object.h>
#include <sock.h>
int
main(int argc, char *argv[])
{
object obj = new_object();
sock sck = new_socket();
return 0;
}
=== object.c ===
#include <object.h>
#include <string.h>
struct object_t
{
int id;
char * name;
};
object
new_object(void)
{
object this;
this = calloc(1, sizeof(struct object_t));
this->id = 1;
this->name = strdup("haha");
return this;
}
char *
object_get_name(object this)
{
return this->name;
}
=== object.h ===
#ifndef object_h
#define object_h
typedef struct object_t *object;
object new_object(void);
char * object_get_name(object this);
#endif/*__object_h*/
=== sock.c ===
#include <setup.h>
#include <object.h>
#include <sock.h>
struct sock_t
{
int id;
char * host;
int port;
};
sock
new_socket(void)
{
sock this;
this = calloc(1, sizeof(struct sock_t));
printf("NAME: %s\n", object_get_name(obj));
return this;
}
=== sock.h ===
#ifndef sock_h
#define sock_h
typedef struct sock_t *sock;
sock new_socket(void);
#endif/*sock_h*/
Here's my error:
$ make
gcc -I. -Wall -w -g -o haha main.c object.c sock.c
/tmp/ccGQHBQO.o: In function `new_socket':
/home/jdfulmer/src/example/sock.c:18: undefined reference to `obj'
collect2: ld returned 1 exit status
make: *** [all] Error 1
I have a stripped down working example here:
ftp://ftp.joedog.org/pub/example.tar.gz
=== Makefile ===
all:
gcc -I. -Wall -w -g -o haha main.c object.c sock.c
clean:
rm haha
=== setup.h ===
#ifndef setup_h
#define setup_h
#include <object.h>
extern object obj;
#endif/*setup_h*/
=== main.c ===
#include <setup.h>
#include <object.h>
#include <sock.h>
int
main(int argc, char *argv[])
{
object obj = new_object();
sock sck = new_socket();
return 0;
}
=== object.c ===
#include <object.h>
#include <string.h>
struct object_t
{
int id;
char * name;
};
object
new_object(void)
{
object this;
this = calloc(1, sizeof(struct object_t));
This variable can never be seen outside main(), because it was
declared inside a block.
> sock.c ===============
>
> sock
> new_socket()
> {
> int thing = object_get_something(obj); /* compiles but doesn't link
> */
> }
Obviously, sock.c must include setup.h. :)
Anyway, the problem here is that the "obj" variable is declared inside main(),
and an extern ... declaration won't find a local variable, only a variable
declared outside any functions and with external linkage. ("External linkage"
is a fancy way of saying "not declared static"; it's the default behavior.)
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
Well, I'd like to apologize for wasting everyone's time (including my
own)
Thanks,
Jeff
Yes, how dare you ask a question about C to which the answer is topical!
I don't think it's a "waste" of time to talk about C here. People make
mistakes, whether or not they're very experienced, and even if you think
it should have been "obvious" to you, well, this is one more chance for
someone who doesn't know that much about C yet to find it when searching.
:)
So where would you place 'object obj = new_object();'? Inside
new_socket()?
If 'obj' is meant to be a global variable it can be defined in
any of the source files (as long as it's in just one of them).
For that it may not be within a function (otherwise it wouldn't
be global). But then a line like
object obj = new_object();
can't be used since the initialization value for a global variable
must be a compile time constant - and a call to a function can only
be done at run time. So you put the definition of the variable with-
out that initialization outside of all functions in one of the source
files and do the initialization e.g. in main() or just before 'obj'
is used for the first time (you could do the initialization anytime
between the start of main() and the first use of obj' but doing it
either at the very start or when it's needed would look most natural
to me, but YMMV...)
yes it is true; you find the bug without see all the code
I have a stripped down working example here:
ftp://ftp.joedog.org/pub/example.tar.gz
= this io_x
=i see your msg, try compile with the compiler
=that say me not find "obj" [that is in no file] called in
=some place in file sock.obj
="Turbo Incremental Link 5.95 Copyright (c) 1997-2008 CodeGear
= Error: Unresolved external '_obj' referenced from C: \SOCK.OBJ"
=than i try to find "obj" in your code
=it is in setup.h and in main.c .
=Do you know if you have
=int f(int a)
={int name[200];
= return name;
=}
=than the space pointed from the name "name" not exist after the f exit
=it could be exist if something of this kind
=char* g(int v){return malloc(v);}
= than seems to me it is beeter to use <> for standard header
= and "" for home made header in the same directory of the .exe
=
= could be ok if rewrite main.c and compile it in this way:
= bcc32 -v sock.c
= bcc32 -v object.c
= bcc32 -v main.c object.obj sock.obj
= for this origin
-----------------------
// === sock.h ===
#ifndef sock_h
#define sock_h
typedef struct sock_t *sock;
sock new_socket(void);
#endif
/*end sock_h*/
-------------------------
// === main.c ===
#include "setup.h"
#include "object.h"
#include "sock.h"
object obj; // i change this
int main(int argc, char *argv[])
{
sock sck;
obj = new_object();
sck = new_socket();
return 0;
}
// end main
--------------------------
// === object.c ===
#include "object.h"
#include <string.h>
// here i add the line for the malloc area functions
// hope calloc is in stdlib
#include <stdlib.h>
struct object_t
{
int id;
char * name;
};
object new_object(void)
{ object this;
this = calloc(1, sizeof(struct object_t));
this->id = 1;
this->name = strdup("haha");
return this;
}
char* object_get_name(object this){return this->name;}
-------------------
// === object.h ===
#ifndef object_h
#define object_h
// here i add the line for the malloc area functions
// hope calloc is in stdlib
#include <stdlib.h>
typedef struct object_t *object;
object new_object(void);
char * object_get_name(object this);
#endif
/*end __object_h*/
--------------------
// sock.c
#include "setup.h"
#include "object.h"
#include "sock.h"
#include <stdio.h>
struct sock_t
{
int id;
char * host;
int port;
};
sock
new_socket(void)
{
sock this;
this = calloc(1, sizeof(struct sock_t));
printf("NAME: %s\n", object_get_name(obj));
return this;
}
-------------------------
= i forget to say: why use all these files?
= why not use only one big file for c
= + one couple of .h files?
= than why use
typedef struct object_t *object;
= ?
I've meant to ask about this one before. I've picked up a (probably
bad) habit of doing as above, from an employer where that was
"standard". Do these count as identifiers in the restricted space,
even though they're macros?
They are not reserved by C, but they are reserved by C++. From
C++98:
17.4.3.1.2 Global names [lib.global.names]
1 Certain sets of names and function signatures are always
reserved to the implementation:
- Each name that contains a double underscore (__) or begins
with an underscore followed by an upper- case letter
(2.11) is reserved to the implementation for any use.
It's up to you whether to care about that, of course.
--
"It would be a much better example of undefined behavior
if the behavior were undefined."
--Michael Rubenstein
No, I can't say I care about the restrictions in C++. I was just
concerned about 7.1.3 Reserved identifiers, including "All identifiers
that begin with an underscore and either an uppercase letter or
another underscore are always reserved for any use." This would
include the above usage if they count as identifiers. Now I look at
6.10.3 Macro replacement, item 2 "An identifier currently defined as a
macro...", and it looks more conclusive. Macros count as identifiers,
and identifiers such as __object_h are reserved. Am I missing
something else? It wouldn't be the first time I'd misinterpreted part
of the Standard.
> On May 18, 1:49 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> BruceS <bruce...@hotmail.com> writes:
>> > On May 18, 6:41 am, Richard Heathfield <r...@see.sig.invalid> wrote:
>> >> Jeff wrote:
>> >> If you must have underscore decorations, use trailers, not leaders:
>>
>> >> #ifndef object_h__
>> >> #define object_h__
>>
>> > I've meant to ask about this one before. I've picked up a (probably
>> > bad) habit of doing as above, from an employer where that was
>> > "standard". Do these count as identifiers in the restricted space,
>> > even though they're macros?
>>
>> They are not reserved by C, but they are reserved by C++. From
>> C++98:
>> [...]
>> It's up to you whether to care about that, of course.
>
> No, I can't say I care about the restrictions in C++. I was just
> concerned about 7.1.3 Reserved identifiers, including "All identifiers
> that begin with an underscore and either an uppercase letter or
> another underscore are always reserved for any use." This would
> include the above usage if they count as identifiers.
No, this clause in 7.1.3 doesn't reserve object_h__, because
object_h__ does not begin with an underscore.
> Now I look at 6.10.3 Macro replacement, item 2 "An identifier
> currently defined as a macro...", and it looks more conclusive.
> Macros count as identifiers, and identifiers such as __object_h
> are reserved. Am I missing something else? It wouldn't be the
> first time I'd misinterpreted part of the Standard.
__object_h is reserved because it begins with two underscores.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
No, you're not missing anything.
In C, all identifiers starting with either a double underscore or an
underscore followed by an uppercase letter are reserved for all purposes
(that includes macros). You should never declare such an identifier
yourself. For example, the implementation might have declared it as a
macro. Redefining it as a macro might break the implementation;
defining it as anything else might break your declaration. You're very
likely to get away with it in most cases (if your identifier doesn't
happen to collide with one used by the implementation), but you
shouldn't try. __FOO might work just fine today, but break with the
next release of your compiler.
Identifers starting with an underscore followed by something other than
a second underscore or an uppercase letter are reserved in fewer
contexts, but you should still avoid them (it's simpler to remember to
avoid leading underscores than to remember the odd cases that are
permitted).
(C++ additionally reserves identifiers with double underscores; this
does not apply to C, but if you want to avoid double underscores
anyway I certainly won't criticize you for it.)
Trailing underscores are harmless. (In C++, single trailing underscores
are harmless.) And they're not commonly used, which makes for a handy
convention for specialized purposes.
So this:
#ifdef object_h_
#define object_h_
/* ... */
#endif
is ok. Another convention I've seen is to use an uppercase name with a
leading H_:
#ifdef H_OBJECT
#define H_OBJECT
/* ... */
#endif
The H_ prefix avoids accidentally using an identifier starting with 'E'.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Thanks, Ben. Sorry for the confusion; I was referring to the original
version, from Jeff (__object_h), not the corrected version from
Richard. I think there was some snippage of context in there.
Thanks, Keith, that confirms it nicely. It looks like that was indeed
a bad practice, and I'll amend it. I think I'll go with the
myheader_h_ approach. That seems extremely unlikely to collide with
any other identifiers, and is every bit as clear as __myheader_h.