upen@watarts.UUCP (Ue-Li Pen) (02/19/85)
Question:
Is it allowed & portable to use the construct:
char* foo(){
return("foobar");
}
This would hopefully return a pointer to the string "foobar"..
If it isn't.. should it be allowed? It would seem reasonable.
david@ukma.UUCP (David Herron, NPR Lover) (02/21/85)
In article <8257@watarts.UUCP> upen@watarts.UUCP (Ue-Li Pen) writes: > Is it allowed & portable to use the construct: > char* foo(){ > return("foobar"); > } > This would hopefully return a pointer to the string "foobar".. Yes it does....However it is a pointer to a STATIC data area. So it wouldn't be a good idea to change the contents of the string. -- -:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:- -:-David Herron; -:-ARPA-> "ukma!david"@ANL-MCS or david%ukma.uucp@anl-mcs.arpa -:-ARPA-> Or even anlams!ukma!david@ucbvax.arpa -:-UUCP-> {ucbvax,unmvax,boulder,research}!anlams!ukma!david -:-UUCP-> {mcvax!qtlon,vax135,mddc}!qusavx!ukma!david -:-UUCP-> {A-Large-Portion-of-The-World}!cbosgd!ukma!david
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (02/21/85)
> return("foobar");
Works just fine. (The parentheses are unnecessary and misleading.)
huisjes@ark.UUCP (Michiel B. Huisjes) (02/24/85)
In article <929@ukma.UUCP> david@ukma.UUCP (David Herron, NPR Lover) writes: >In article <8257@watarts.UUCP> upen@watarts.UUCP (Ue-Li Pen) writes: >> Is it allowed & portable to use the construct: >> char* foo(){ >> return("foobar"); >> } >> This would hopefully return a pointer to the string "foobar".. > >Yes it does....However it is a pointer to a STATIC data area. >So it wouldn't be a good idea to change the contents of the string. >-- >-:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:--:- >-:-David Herron; David Herron is right, except for the fact that you are allowed to change the contents of the string as long as you don't change the length of it! So you are allowed to say: main() { char *ptr; char *foo(); ptr = foo(); strcpy( ptr, "barfoo" ); ..... } -- Michiel Huisjes. {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes
gjerawlins@watdaisy.UUCP (Gregory J.E. Rawlins) (02/27/85)
In article <8257@watarts.UUCP> upen@watarts.UUCP (Ue-Li Pen) writes: > Is it allowed & portable to use the construct: > char* foo(){ > return("foobar");} > This would hopefully return a pointer to the string "foobar".. In article <929@ukma.UUCP> david@ukma.UUCP (David Herron, NPR Lover) writes: > Yes it does....However it is a pointer to a STATIC data area. > So it wouldn't be a good idea to change the contents of the string. In article <437@ark.UUCP> huisjes@ark.UUCP (Michiel Huisjes) writes: > David Herron is right, except for the fact that you are allowed to > change the contents of the string as long as you don't change the > length of it! (a confused hon-hacker writes...) Why would you want to keep a pointer to a constant string (or at least a constant length string)?? -- Gregory Rawlins CS Dept.,U.Waterloo,Waterloo,Ont.N2L3G1 (519)884-3852 gjerawlins%watdaisy@waterloo.csnet CSNET gjerawlins%watdaisy%waterloo.csnet@csnet-relay.arpa ARPA {allegra|clyde|linus|inhp4|decvax}!watmath!watdaisy!gjerawlins UUCP
g-frank@gumby.UUCP (03/01/85)
> (a confused hon-hacker writes...) Why would you want to keep a pointer to > a constant string (or at least a constant length string)?? > -- Well, you might not keep a pointer to it, but since strings must be passed to functions by passing their addresses, you don't have a lot of choice. In fact, these kinds of limitations (implementing pass by reference with explicit pointers) really tie the hands of compiler implementers, especially on machines that don't look like VAXen or PDP-11's. -- Dan Frank Q: What's the difference between an Apple MacIntosh and an Etch-A-Sketch? A: You don't have to shake the Mac to clear the screen.
jeff@rtech.ARPA (Jeff Lichtman) (03/01/85)
> > David Herron is right, except for the fact that you are allowed to > change the contents of the string as long as you don't change the > length of it! > So you are allowed to say: > > main() > { > char *ptr; > char *foo(); > > ptr = foo(); > strcpy( ptr, "barfoo" ); > ..... > } > -- > > Michiel Huisjes. > {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes In DEC C, string constants are read-only. They are in a special, write- protected psect. If you try to do something like the above, you will get a run-time error. -- Jeff Lichtman at rtech (Relational Technology, Inc.) aka Swazoo Koolak
mroddy@enmasse.UUCP (Mark Roddy) (03/01/85)
> > (a confused hon-hacker writes...) Why would you want to keep a pointer to > a constant string (or at least a constant length string)?? foo(n) { static char str="foobar 0x0000\n"; hexdigit(n,&str[9]); /* puts n into string */ return(str); } As to why, imagine an environment without stdio etc- i.e., as is happening more frequently, C used to implement intelligent peripheral device software. -- Mark Roddy Net working, Just reading the news. (harvard!talcott!panda!enmasse!mroddy)
ndiamond@watdaisy.UUCP (Norman Diamond) (03/04/85)
> > You are allowed to say: > > > > main() > > { > > char *ptr; > > char *foo(); > > > > ptr = foo(); > > strcpy( ptr, "barfoo" ); > > ..... > > } > > -- Michiel Huisjes. > > In DEC C, string constants are read-only. They are in a special, write- > protected psect. If you try to do something like the above, you will > get a run-time error. -- Jeff Lichtman What does the standard say about this? Can an implementation legally prevent a C program from modifying storage accessed by a valid pointer? -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
henry@utzoo.UUCP (Henry Spencer) (03/05/85)
> > In DEC C, string constants are read-only. They are in a special, write- > > protected psect. If you try to do something like the above, you will > > get a run-time error. -- Jeff Lichtman > > What does the standard say about this? Can an implementation legally prevent > a C program from modifying storage accessed by a valid pointer? The latest ANSI draft (11 Feb 1985) says that string literals are of type "const char[]" (not just "char[]") and thus it is illegal for you to alter their contents. This has both advantages and disadvantages. It will break some programs, notably ones that use mktemp() in the most simplistic way. On the other hand, it will produce widespread (if modest) improvements in efficiency, and will make life noticeably easier for people writing C code to go in ROM. [Please, let us not have a renewed debate on the merits or lack thereof of this change; we did that, at length, a few months ago.] -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
jc@mit-athena.UUCP (John Chambers) (03/05/85)
Let's see, reasons for returning pointers to constant strings...?
Several times in the past couple years I have written routines that
end with code something like:
...
fail: /* Jump here for disasters*/
errno = EGLORCH;
fprintf(stderr,"***foo() FAILED.\n");
return("???FOO???");
}
This is for a function that normally returns a pointer to a string
of characters. The idea is that if the caller doesn't notice the
failure and tries to use the return value, the program won't just
bomb inexplicably (as it might do if you return NULL); it will have
a character string that will tend to stand out wherever it pops up
later. In this case, it doesn't much matter if the caller changes
the string, since it is basically a string of garbage anyway.
Anyone got any more examples?
John Chambers
david@ukma.UUCP (David Herron, NPR Lover) (03/06/85)
>> > main() >> > { >> > char *ptr; >> > char *foo(); >> > >> > ptr = foo(); >> > strcpy( ptr, "barfoo" ); >> > ..... >> > } >> >> In DEC C, string constants are read-only. They are in a special, write- >> protected psect. If you try to do something like the above, you will >> get a run-time error. -- Jeff Lichtman > >What does the standard say about this? Can an implementation legally prevent >a C program from modifying storage accessed by a valid pointer? A string constant (like above) is a CONSTANT. You should be prevented from changing the values of CONSTANTS. The fact that you ever could is laziness (or something) on the part of the original implementors. Allowing one to change the value of constants (can, not necessarily will) create hard to find bugs. (usually in the case of careless programmers...) What I want to know is what (of the code above) would generate a run-time error? -- :------------------------------------------------------------------: :- David Herron -: :- -: :- ARPA-> "ukma!david"@ANL-MCS or david%ukma.uucp@anl-mcs.arpa -: :- ARPA-> Or even anlams!ukma!david@ucbvax.arpa -: :- -: :- UUCP-> {ucbvax,unmvax,boulder,research}!anlams!ukma!david -: :- UUCP-> {mcvax!qtlon,vax135,mddc}!qusavx!ukma!david -: :- UUCP-> {A-Large-Portion-of-The-World}!cbosgd!ukma!david -: :------------------------------------------------------------------: "The home of poly-unsaturated thinking".
gwyn@Brl-Vld.ARPA (VLD/VMB) (03/06/85)
The latest draft proposed ANSI standard for C supports a "const" type-modifier, to flag data that may not be modified. String literals are (const char) arrays and may not be modified. It is possible to initialize a non-const (char) array with a string if one wants to be able to modify it at run-time. One significant advantage of (const char) strings is that they are ROMable. Another is that storage for identical strings can be shared if the compiler/loader is sufficiently clever.
jc@mit-athena.UUCP (John Chambers) (03/12/85)
Hmmm... According to some of the advice here, the following is not
an acceptable way to declare an initialized array:
char *fup = "0123456789";
The reason is that some C compilers are likely to take the string
constant and put it into a read-only portion of memory. Instead,
if we want an initialized character array, we are supposed to say
something like:
char fup[11]; /* I hope this isn't read-only */
int i;
...
for (i=0; i<11; i++)
fup[i] = i + '0';
fup[i] = '\0';
or maybe:
char *fup;
int i;
...
fup = malloc(11);
if (fup == NULL) { /* Gotta check for failure */
fprintf(stderr,"Out of space, can't get 11 bytes\n");
perror("foo");
exit(17);
}
for (i=0; i<11; i++) /* Initialize the sucker */
fup[i] = i + '0';
fup[i] = '\0';
To this, I say "NONSENSE". Any compiler-writer that considers a
string constant to be read-only is a total and utter turkey, and
I would rather use a sensible compiler. I don't need such stuff
to make my code slower and kludgier and harder to understand; I
can do a bad enough job by myself without encouragement from the
compiler writers! (:-)
Please, writing simple, straightforward code is a hard enough job
already. One of the nice things about C is that such things as
the above example need not be kludgy and hard to read. If we are
going to change C, let's try to make it better, not worse!
John Chambers
P.S. An extension to the language to declare a symbol to be a
constant would be nice at times. It would help those who are
dealing with ROM.
ndiamond@watdaisy.UUCP (Norman Diamond) (03/13/85)
> Hmmm... According to some of the advice here, the following is not > an acceptable way to declare an initialized array: > > char *fup = "0123456789"; > > The reason is that some C compilers are likely to take the string > constant and put it into a read-only portion of memory. fup is not read-only. The string might be. > Instead, > if we want an initialized character array, we are supposed to say > something like: > > char fup[11]; /* I hope this isn't read-only */ The array fup is not read-only. > int i; > ... > for (i=0; i<11; i++) > fup[i] = i + '0'; > fup[i] = '\0'; > > or maybe: > > char *fup; > int i; Yup, this time you gotta do it. > ... > fup = malloc(11); ... proving that fup is not read-only ... > if (fup == NULL) { /* Gotta check for failure */ > fprintf(stderr,"Out of space, can't get 11 bytes\n"); > perror("foo"); > exit(17); > } > for (i=0; i<11; i++) /* Initialize the sucker */ > fup[i] = i + '0'; > fup[i] = '\0'; > > To this, I say "NONSENSE". It is nonsense, all right. Try: char fup[11] = "0123456789"; This is not the same as assigning a pointer to address a read-only item. This initializes the contents of the writable array fup. -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
guy@rlgvax.UUCP (Guy Harris) (03/13/85)
> Hmmm... According to some of the advice here, the following is not > an acceptable way to declare an initialized array: > > char *fup = "0123456789"; Damn straight. It defines an initialized *pointer* which points to a nameless array. Try char fup[] = "0123456789"; to declare an array. This *is* the sensible thing to do. If you actually plan to *modify* that array, the first example is truly lousy; if you end up putting 11 characters into it, you stomp on some strange area of memory (unless the string is put in read-only memory, in which case your program gets properly punished). If you expect up to 128 characters in the array, try char fup[128+1/*for the null terminator*/] = "0123456789"; Why should random strings get put in writable areas of your address space? Currently, there are a lot of horrible kludges to move strings, etc. into read-only sharable text space; putting strings there by default obviates the need for some of those kludges (the "const" attribute obviates the need for the others). Please learn how to construct initialized strings before blindly criticizing this language change. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy -- Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
jsdy@hadron.UUCP (Joseph S. D. Yao) (03/13/85)
> >> Is it allowed & portable to use the construct: > >> char* foo(){ > >> return("foobar"); > >> } > >> This would hopefully return a pointer to the string "foobar".. > >Yes it does....However it is a pointer to a STATIC data area. > >So it wouldn't be a good idea to change the contents of the string. > David Herron is right, except for the fact that you are allowed to > change the contents of the string as long as you don't change the > length of it! Perhaps you should remember that if you do, say, strcpy(foo(), "barfoo")), then the next call to foo() will return "barfoo". This is because the "barfoo" string is copied into the static location of the string that is returned by foo(). Another way to say this is that new instances of the string "foobar" are n o t dynamically created each time you call foo(). All of this assumes, BTW, that you are not using a DEC or ANSI C compiler. Also BTW, one response asks about the legitimacy of not being able to modify the contents of any valid pointer. In case henry's answer didn't suggest it, ANSI C introduces a new storage class "const", which is a class of data which may be assumed to remain constant, and (i guess if possible) should be placed in read-only storage. A no-write data-space psect fills this requirement. The opposite is "volatile", which means: "Even if you are optimising the heck out of this code, watch it! This variable will change when you least expect it!" This is good for data manipulated by interrupt routines, or if you feel like being perverse while adb/sdb/dbx'ing the thing. ;-) Joe Yao hadron!jsdy@seismo.{ARPA,UUCP} *BTW == By The Way, for our friends not in the States. ;-)
wjr@x.UUCP (Bill Richard) (03/14/85)
> Hmmm... According to some of the advice here, the following is not > an acceptable way to declare an initialized array: > > char *fup = "0123456789"; > > The reason is that some C compilers are likely to take the string > constant and put it into a read-only portion of memory. Instead, > if we want an initialized character array, we are supposed to say > something like: > > <2 examples of run time array initialization> > > To this, I say "NONSENSE". Any compiler-writer that considers a > string constant to be read-only is a total and utter turkey, and > I would rather use a sensible compiler. ... > John Chambers To this I say "RTFM John". K&R Section 8.6 (pg 199) says: "A final abbreviation <of initializer forms> allows a _char_ array to be initialized by a string. In this case successive characters of the string initialize the members of the array." Thus: char fup[] = "0123456789"; will give you a writable array of chars initialized to look like the string. I assume that the ANSII committee hasn't broken this feature, if they have I have a complaint. Or are you making a general objection to constants being constant? In which case you must love those Fortran compilers which allow you to dynamically change the value of a NUMERIC constant. :-) -- ---- William J. Richard @ Charles River Data Systems 983 Concord St. Framingham, MA 01701 Tel: (617) 626-1112 uucp: ...!decvax!frog!wjr
jeff@rtech.ARPA (Jeff Lichtman) (03/14/85)
> Hmmm... According to some of the advice here, the following is not > an acceptable way to declare an initialized array: > > char *fup = "0123456789"; > > The reason is that some C compilers are likely to take the string > constant and put it into a read-only portion of memory. Instead, > if we want an initialized character array, we are supposed to say > something like: > Unnecessarily complicated code here. > > or maybe: > Even more complicated code here. > > John Chambers First of all, it's fine to initialize a character pointer to point to a string constant. Just don't try to alter the constant. If you want to initialize a character pointer to point to a non-constant string, try the following: # define CONST "0123456789" char nonconst[sizeof(CONST)]; char *p = nonconst; strcpy(nonconst, CONST); There, that's not so hard, is it? I don't think it's a good programming practice to modify the value of a constant, anyway. -- Jeff Lichtman at rtech (Relational Technology, Inc.) aka Swazoo Koolak
hansen@pegasus.UUCP (Tony L. Hansen) (03/19/85)
By definition, in ANSI C (according to the latest Feb. draft) string constants are of type "const char[]". The first horrified thought that comes to the mind of many UNIX programmers is "What do I do with all of my calls to mktemp() now?" Easy! mktemp ("/tmp/fooXXXXXX"); becomes mktemp ( (char *) "/tmp/fooXXXXXX"); Since the cast is used withOUT the "const" qualifier, the compiler is forced to place the string in writable memory. Note that I am NOT casting a "char *" back into a "char *", but am instead casting a "const char *" into a "char *". Since the number of times that such idioms will be needed will be very small, this change to ANSI C will definitely be more beneficial than harmful. Tony Hansen pegasus!hansen
guy@rlgvax.UUCP (Guy Harris) (03/20/85)
> By definition, in ANSI C (according to the latest Feb. draft) string > constants are of type "const char[]". The first horrified thought that > comes to the mind of many UNIX programmers is "What do I do with all of my > calls to mktemp() now?" Easy! > > mktemp ("/tmp/fooXXXXXX"); > > becomes > > mktemp ( (char *) "/tmp/fooXXXXXX"); Even better, it becomes char tempstr[14+1]; strcpy(tempstr, "/tmp/fooXXXXXX"); mktemp(tempstr); which can, unlike mktemp("/tmp/fooXXXXXX"); be executed more than once and work every time. -- Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
kendall@talcott.UUCP (Sam Kendall) (03/22/85)
> mktemp ("/tmp/fooXXXXXX"); > > becomes > > mktemp ( (char *) "/tmp/fooXXXXXX"); > > Since the cast is used withOUT the "const" qualifier, the compiler is forced > to place the string in writable memory. Note that I am NOT casting a "char *" > back into a "char *", but am instead casting a "const char *" into a "char *". > > Tony Hansen > pegasus!hansen This won't do it. The cast makes a pointer to non-const out of a pointer to const, but the result of the cast still points to storage defined as const, so the result of any attempt to modify it (by mktemp) is undefined. See Guy Harris's note on this topic for the right way to do it. Sam Kendall Delft Consulting {allegra, ihnp4}!pyuxvv!delftcc!sam