char*

R

Russell Shaw

Hi,

If i have: char *str = "test" in one .c file, is it guaranteed
that str == "test" in any other .c file after linking?
(ie: there isn't multiple "test" strings stored in the final object)
 
E

Eric Sosman

Russell said:
Hi,

If i have: char *str = "test" in one .c file, is it guaranteed
that str == "test" in any other .c file after linking?
(ie: there isn't multiple "test" strings stored in the final object)

There is no such guarantee, not even within just
one file:

char *p = "test";
char *q = "test";
assert (p == q); /* can fail */

However, some compilers (perhaps even "many") will
recognize this case and collapse both literals into just
one anonymous char[] array used as the target for both
pointers. Some will go even further:

char *p = "test";
char *q = "smartest";
assert (p == q + 4); /* can succeed */

Off-hand I don't know of an implementation that will
do this sort of thing across module boundaries. It'd
certainly be possible and there may be an implementation
that does it, but I haven't run into one (or rather, if
I have run into one I haven't noticed the fact).
 
C

Christian Kandeler

Russell said:
If i have: char *str = "test" in one .c file, is it guaranteed
that str == "test" in any other .c file after linking?
(ie: there isn't multiple "test" strings stored in the final object)

No. Don't ever write that in a program, because this kind of bug can be
really hard to spot: It may very well work perfectly for a long time, until
one day you upgrade your compiler or linker or just change the optimization
level.


Christian
 
J

Jonathan Bartlett

Russell said:
Hi,

If i have: char *str = "test" in one .c file, is it guaranteed
that str == "test" in any other .c file after linking?
(ie: there isn't multiple "test" strings stored in the final object)

The better way to do this is with "interned" strings. With such
strings, you are guaranteed that all matching interned strings will have
the same address.

Basically, you do something like:

char *str = intern("test");
char *str2 = intern("test");
/* note -- you have to define "intern" */

Now, str and str2 are guaranteed to have the same pointer.

A similar thing is done in glib (part of Gtk+) using what are called
Quarks. Instead of giving a pointer, it gives you a unique integer (my
guess is that it really is giving you the pointer, but the unique
integer is for portability). You can read more about it here:

http://developer.gnome.org/doc/API/2.0/glib/glib-Quarks.html

Jon
 
P

pete

Jonathan said:
The better way to do this is with "interned" strings. With such
strings,
you are guaranteed that all matching interned strings will have
the same address.

Basically, you do something like:

char *str = intern("test");
char *str2 = intern("test");
/* note -- you have to define "intern" */

Now, str and str2 are guaranteed to have the same pointer.

char *str2 = str;
seems simpler to me.

How would you define intern?
 
J

Jonathan Bartlett

char *str2 = str;
seems simpler to me.

But you would have to know that "str" contained the original defintion
of the string.
How would you define intern?

It would basically be a list of strings (sorted, hashed, binary treed,
or otherwise for performance). intern() would search the list for the
string, and, if found, return the address. Otherwise, it would add the
string to the list and return the new pointer.

Jon
 
R

Russell Shaw

Jonathan said:
But you would have to know that "str" contained the original defintion
of the string.


It would basically be a list of strings (sorted, hashed, binary treed,
or otherwise for performance). intern() would search the list for the
string, and, if found, return the address. Otherwise, it would add the
string to the list and return the new pointer.

A statically allocated hash table.

I've been figuring out how to make run-time checks of casts of pointers
to certain object types. Each object (a C struct) has its own file.
I'll try this:

widget.h:

extern char* widgetclass;

#define WIDGET(widget) (assert(((Widget*)widget)->magic == widgetclass), (Widget*)(widget))

typedef struct {
...
char *class;
} Widget;


widget.c:

char* widgetclass = "Widget"

static void
constructor(Widget *widget)
{
...
widget->class = widgetclass;
}

main.c:

int
main(int argc, char *argv[])
{
...
/* An assertion will happen if someobject->class != widgetclass. */
Widget *widget = WIDGET(someobject);
...
}
 
P

pete

Jonathan said:
But you would have to know that "str" contained the original defintion
of the string.


It would basically be a list of strings (sorted, hashed, binary treed,
or otherwise for performance). intern() would search the list for the
string, and, if found, return the address.
Otherwise, it would add the
string to the list and return the new pointer.

Thank you.
 

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
474,161
Messages
2,570,892
Members
47,432
Latest member
GTRNorbert

Latest Threads

Top