Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Compiler Warning

Reply
Thread Tools

Compiler Warning

 
 
srikar2097
Guest
Posts: n/a
 
      12-01-2008
I have written this small fn. to strip down whitespaces ("\n") a given
string (only leading and trailing).
The program itself might not be foolproof but that is not my concern
right now. When I compile this
I get a warning :--

"string_utils.c:96: warning: function returns address of local
variable.

I have declared the fn. as fn. pointer and this fn. returns the
address of a string array. Why does
the compiler give out this warning? Please help.

Thanks,
Srikar


PROGRAM:
--------------

char *xstrip(char *); //declaration.

char *xstrip(char *c)
{
int i=0;
char tmp_str[xstrlen(&c[0])];

while(*c != '\0')
{
if(*c==32) // if space.
{
if((*(c+1)!=32 && *(c-1)!=32))
;
else
{
c++;
continue;
}
}
tmp_str[i]=*c;
i++;
c++;
}
//Adding null char to indicate end of string. Else printf would
not know where str ends.
tmp_str[i]='\0';

return &tmp_str[0];

}
 
Reply With Quote
 
 
 
 
Bartc
Guest
Posts: n/a
 
      12-01-2008

"srikar2097" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>I have written this small fn. to strip down whitespaces ("\n") a given
> string (only leading and trailing).
> The program itself might not be foolproof but that is not my concern
> right now. When I compile this
> I get a warning :--
>
> "string_utils.c:96: warning: function returns address of local
> variable.
>
> I have declared the fn. as fn. pointer and this fn. returns the
> address of a string array. Why does
> the compiler give out this warning? Please help.


> char *xstrip(char *c)
> {
> int i=0;
> char tmp_str[xstrlen(&c[0])];

....
> return &tmp_str[0];
> }


The compiler is spot-on: you're returning the address of a local variable.

You can't do that (or at least, it's a very bad idea).

The tmp_str variable will cease to exist after returning, the address will
be meaningless.

You might try static in front it, although it looks like you want a dynamic
length for the array (not possible for static). You need a different
solution.

--
Bartc

 
Reply With Quote
 
 
 
 
vippstar@gmail.com
Guest
Posts: n/a
 
      12-01-2008
On Dec 1, 3:55 pm, srikar2097 <(E-Mail Removed)> wrote:
> I have written this small fn. to strip down whitespaces ("\n") a given
> string (only leading and trailing).
> The program itself might not be foolproof but that is not my concern
> right now. When I compile this
> I get a warning :--
>
> "string_utils.c:96: warning: function returns address of local
> variable.
>
> I have declared the fn. as fn. pointer and this fn. returns the
> address of a string array. Why does
> the compiler give out this warning? Please help.
>
> Thanks,
> Srikar
>
> PROGRAM:
> --------------
>
> char *xstrip(char *); //declaration.


Gee that's a helpful comment.

> char *xstrip(char *c)
> {
> int i=0;
> char tmp_str[xstrlen(&c[0])];


What is xstrlen? It's not provided. Does it expand to something
constant or not? Why &c[0] and not c? If it calculates the length of
the string c, then what will you do for empty strings? You can't have
0 length arrays!


> while(*c != '\0')
> {
> if(*c==32) // if space.


32 is just a value. If you want to see whether *c is a space or not,
you'll have to use: ' ', like this:

if(*c == ' ')

If you want to know whether *c belongs in the space class, you'll have
to use isspace (<ctype.h>)

if(isspace((unsigned char)*c))

> {
> if((*(c+1)!=32 && *(c-1)!=32))


Ditto. c - 1 can invoke undefined behavior, unless you plan on
invoking the function as:
char foo[N];
/* ... */
foo[0] = 0;
xstrip(&foo[1]);

Or similar.

> ;
> else
> {
> c++;
> continue;
> }
> }
> tmp_str[i]=*c;
> i++;
> c++;
> }
> //Adding null char to indicate end of string. Else printf would
> not know where str ends.
> tmp_str[i]='\0';


Assuming xstrlen served the purpose of an strlen, in case the string
doesn't contain any whitespace, you're writing past the end of
tmp_str. (it's easy to see this by taking c == "", nevermind there
can't be 0 sized arrays)

> return &tmp_str[0];


tmp_str is a local object, you can't return its address.

> }

 
Reply With Quote
 
s0suk3@gmail.com
Guest
Posts: n/a
 
      12-01-2008
On Dec 1, 8:55*am, srikar2097 <(E-Mail Removed)> wrote:
> I have written this small fn. to strip down whitespaces ("\n") a given
> string (only leading and trailing).
> The program itself might not be foolproof but that is not my concern
> right now. When I compile this
> I get a warning :--
>
> "string_utils.c:96: warning: function returns address of local
> variable.
>
> I have declared the fn. as fn. pointer and this fn. returns the
> address of a string array. Why does
> the compiler give out this warning? Please help.


Try:

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// Return value must be manually deallocated

char* xstrip(const char* str)
{
while (isspace((unsigned char) *str) && *str != '\0')
++str;

const char* end = str + strlen(str);
while ((isspace((unsigned char) *end) || *end == '\0') && end >
str)
--end;

char* buf = (char*) calloc(1, end - str + 2);
if (!buf)
return NULL;

strncpy(buf, str, end - str + 1);
return buf;
}

Or, if you want to modify the string in-place:

void xstrip(char* str)
{
char* start = str;

while (isspace((unsigned char) *start) && *start != '\0')
++start;

char* end = start + strlen(start);
while ((isspace((unsigned char) *end) || *end == '\0') && end >
start)
--end;

memmove((void*) str, (const void*) start, end - start + 1);
str[end - start + 1] = '\0';
}

Sebastian

 
Reply With Quote
 
srikar2097
Guest
Posts: n/a
 
      12-01-2008
Thanks guys, as both Bart and Vippstar have mentioned - "Since tmp_str
is a local variable. It cannot exist outside that fn. So what I have
done is not valid."

But I need to access this (modified) array outside this fn. How should
I go about it?
This is a string array and I expect it to be very big in some cases.
So I don't want to copy the entire array outside this fn. Just a
pointer??

After some thought::- Since after the fn. "xstrip()" is executed all
the space allotted to the vars in this fn. is out of scope to the ones
outside it. I get this is the problem. So what is the way?

Thanks...

PS: "xstrlen()" is nothing but a spoof (my) implementation of "strlen
()".




On Dec 1, 7:22*pm, (E-Mail Removed) wrote:
> On Dec 1, 3:55 pm, srikar2097 <(E-Mail Removed)> wrote:
>
>
>
>
>
> > I have written this small fn. to strip down whitespaces ("\n") a given
> > string (only leading and trailing).
> > The program itself might not be foolproof but that is not my concern
> > right now. When I compile this
> > I get a warning :--

>
> > "string_utils.c:96: warning: function returns address of local
> > variable.

>
> > I have declared the fn. as fn. pointer and this fn. returns the
> > address of a string array. Why does
> > the compiler give out this warning? Please help.

>
> > Thanks,
> > Srikar

>
> > PROGRAM:
> > --------------

>
> > char *xstrip(char *); //declaration.

>
> Gee that's a helpful comment.
>
> > char *xstrip(char *c)
> > {
> > * * int i=0;
> > * * char tmp_str[xstrlen(&c[0])];

>
> What is xstrlen? It's not provided. Does it expand to something
> constant or not? Why &c[0] and not c? If it calculates the length of
> the string c, then what will you do for empty strings? You can't have
> 0 length arrays!
>
> > * * while(*c != '\0')
> > * * {
> > * * * * if(*c==32) // if space.

>
> 32 is just a value. If you want to see whether *c is a space or not,
> you'll have to use: ' ', like this:
>
> if(*c == ' ')
>
> If you want to know whether *c belongs in the space class, you'll have
> to use isspace (<ctype.h>)
>
> if(isspace((unsigned char)*c))
>
> > * * * * {
> > * * * * * * if((*(c+1)!=32 && *(c-1)!=32))

>
> Ditto. c - 1 can invoke undefined behavior, unless you plan on
> invoking the function as:
> char foo[N];
> /* ... */
> foo[0] = 0;
> xstrip(&foo[1]);
>
> Or similar.
>
> > * * * * * * * * ;
> > * * * * * * else
> > * * * * * * {
> > * * * * * * * * c++;
> > * * * * * * * * continue;
> > * * * * * * }
> > * * * * }
> > * * * * tmp_str[i]=*c;
> > * * * * i++;
> > * * * * c++;
> > * * }
> > * * //Adding null char to indicate end of string. Else printf would
> > not know where str ends.
> > * * tmp_str[i]='\0';

>
> Assuming xstrlen served the purpose of an strlen, in case the string
> doesn't contain any whitespace, you're writing past the end of
> tmp_str. (it's easy to see this by taking c == "", nevermind there
> can't be 0 sized arrays)
>
> > return &tmp_str[0];

>
> tmp_str is a local object, you can't return its address.
>
> > }


 
Reply With Quote
 
Nick Keighley
Guest
Posts: n/a
 
      12-01-2008
don't top-post. That is don't post your reply before the text you
are replying to. I have re-arranged your post.

On 1 Dec, 15:35, srikar2097 <(E-Mail Removed)> wrote:>
> On Dec 1, 7:22 pm, (E-Mail Removed) wrote:
> > On Dec 1, 3:55 pm, srikar2097 <(E-Mail Removed)> wrote:

>
> > > I have written this small fn. to strip down whitespaces ("\n") a given
> > > string (only leading and trailing).
> > > The program itself might not be foolproof but that is not my concern
> > > right now.


perhaps it should be...

> > > When I compile this I get a warning :--

>
> > > "string_utils.c:96: warning: function returns address of local
> > > variable.

>
> > > I have declared the fn. as fn. pointer and this fn. returns the
> > > address of a string array. Why does
> > > the compiler give out this warning? Please help.

>
> > > Thanks,
> > > Srikar

>
> > > PROGRAM:
> > > --------------

>
> > > char *xstrip(char *); //declaration.

>
> > > char *xstrip(char *c)
> > > {
> > > int i=0;
> > > char tmp_str[xstrlen(&c[0])];
> > > while(*c != '\0')
> > > {
> > > if(*c==32) // if space.

>
> > 32 is just a value. If you want to see whether *c is a space or not,
> > you'll have to use: ' ', like this:

>
> > if(*c == ' ')

>
> > If you want to know whether *c belongs in the space class, you'll have
> > to use isspace (<ctype.h>)


that "space class" includes other whitespace characters such as <tab>
\t
and <newline> \n.

> > if(isspace((unsigned char)*c))


note this is one of the (few) cases where a cast is a good idea

> > > {
> > > if((*(c+1)!=32 && *(c-1)!=32))
> > > ;
> > > else
> > > {
> > > c++;
> > > continue;
> > > }
> > > }
> > > tmp_str[i]=*c;
> > > i++;
> > > c++;
> > > }
> > > //Adding null char to indicate end of string. Else printf would
> > > not know where str ends.


beware // comments can screw up when posted to a news group.
/* comments tend to be safer


> > > tmp_str[i]='\0';
> > >
> > > return &tmp_str[0];

>
> > tmp_str is a local object, you can't return its address.

>
> Thanks guys, as both Bart and Vippstar have mentioned - "Since tmp_str
> is a local variable. It cannot exist outside that fn. So what I have
> done is not valid."


yep


> But I need to access this (modified) array outside this fn. How should
> I go about it?
> This is a string array and I expect it to be very big in some cases.
> So I don't want to copy the entire array outside this fn. Just a
> pointer??
>
> After some thought::- Since after the fn. "xstrip()" is executed all
> the space allotted to the vars in this fn. is out of scope to the ones
> outside it. I get this is the problem. So what is the way?


there are several cannonical ways to do this

1. modify the string you passed in. Don't use a temporary. Manipulate
c
directly. This won't work on a string literal (you aren't allowed to
modify them)
xstrip ("this string is mad, bad and dangerous to gnaw");

2. pass in a result string
char *xstrip (char *result, const char *to_be_stripped);

3. use malloc(). This has the problem that the caller must call
free()

4. use a decent string library. C is a bit weak out-of-the-box
in its string handling

5. use a static as a temporary. Can overflow the temp and your
function
is not re-entrant

6. use a global (file scope) variable. All the bad stuff of 5 plus
the extra problems of globals

those suggestions are roughly in order of preference

<snip>

--
Nick Keighley

A good designer must rely on experience, on precise, logic thinking;
and on pedantic exactness. No magic will do.
(Wirth)
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      12-01-2008
srikar2097 <(E-Mail Removed)> writes:
> I have written this small fn. to strip down whitespaces ("\n") a given
> string (only leading and trailing).


I'm sure that "fn." means "function", but please take the time to
spell it out.

'\n' is the new-line character. There are several other characters
that are considered whitespace, including the space ' ' and tab '\t'
characters. The isspace() function is your best bet here.

> The program itself might not be foolproof but that is not my concern
> right now. When I compile this
> I get a warning :--
>
> "string_utils.c:96: warning: function returns address of local
> variable.


Already answered, but see also the comp.lang.c FAQ,
<http://www.c-faq.com/>, particularly questions 7.5a and 7.5b.

> I have declared the fn. as fn. pointer and this fn. returns the
> address of a string array. Why does
> the compiler give out this warning? Please help.


No, you haven't declared the function as a function pointer. A
"function pointer" is a pointer to a function; you haven't used any
function pointers (at least not explicitly).

The term "string array" is unclear. An array is a particular kind of
data type; you can have an array object, for example. A "string" is a
data *format*, not a data type; it's defined as "a contiguous sequence
of characters terminated by and including the first null character"
(C99 7.1.1p1). An array can contain a string.

> PROGRAM:
> --------------
>
> char *xstrip(char *); //declaration.
>
> char *xstrip(char *c)
> {


This isn't wrong, but the separate declaration isn't really necessary
in this case; the "char *xstrip (char *c)" that's part of the function
definition also serves as a declaration. Also, you can include the
parameter name in a standalone declaration if you like; I generally
prefer to do so just because it's clearer.

Separating a declaration (prototype) from a definition (the body of
the function) is very useful when the function needs to be called from
another source file, or when you want to have calls preceding the
definition within a source file. In this particular case, I wouldn't
bother.


> int i=0;
> char tmp_str[xstrlen(&c[0])];
>
> while(*c != '\0')
> {
> if(*c==32) // if space.
> {
> if((*(c+1)!=32 && *(c-1)!=32))
> ;


As somebody else mentioned, using the value 32 is a bad idea. 32
happens to be the numeric representation for the ' ' character in
ASCII, and it's very likely that every system you ever encounter will
use an ASCII-based character encoding, but (a) it's not guaranteed by
the language (EBCDIC has ' ' == 64), and (b) it's much clearer to use
a character constant ' '.

[snip]

> return &tmp_str[0];


The above is incorrect, as has already been noted. But if it were
correct (say, if tmp_str were declared static), it would be simpler to
write:

return tmp_str;

Read section 6 of the comp.lang.c FAQ to understand why these are
equivalent.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <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"
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      12-02-2008
On Mon, 1 Dec 2008 07:35:32 -0800 (PST), (E-Mail Removed) wrote:

>On Dec 1, 8:55*am, srikar2097 <(E-Mail Removed)> wrote:
>> I have written this small fn. to strip down whitespaces ("\n") a given
>> string (only leading and trailing).
>> The program itself might not be foolproof but that is not my concern
>> right now. When I compile this
>> I get a warning :--
>>
>> "string_utils.c:96: warning: function returns address of local
>> variable.
>>
>> I have declared the fn. as fn. pointer and this fn. returns the
>> address of a string array. Why does
>> the compiler give out this warning? Please help.

>
>Try:
>
>#include <stdlib.h>
>#include <string.h>
>#include <ctype.h>
>
>// Return value must be manually deallocated
>
>char* xstrip(const char* str)
>{
> while (isspace((unsigned char) *str) && *str != '\0')


If isspace returns true, can the second conditional expression ever be
false? If isspace returns false, the second expression won't be
evaluated. Why is it there?
> ++str;
>
> const char* end = str + strlen(str);


Unless you have c99, declarations must precede statements.

> while ((isspace((unsigned char) *end) || *end == '\0') && end >
>str)
> --end;
>
> char* buf = (char*) calloc(1, end - str + 2);


Don't cast the return from calloc (or any standard *alloc).

You are paying to high a price for the single '/0' that survives the
call to strncpy below.

> if (!buf)
> return NULL;
>
> strncpy(buf, str, end - str + 1);
> return buf;
>}
>
>Or, if you want to modify the string in-place:
>
>void xstrip(char* str)
>{
> char* start = str;
>
> while (isspace((unsigned char) *start) && *start != '\0')


The second comparison is still pointless.

> ++start;
>
> char* end = start + strlen(start);
> while ((isspace((unsigned char) *end) || *end == '\0') && end >
>start)
> --end;
>
> memmove((void*) str, (const void*) start, end - start + 1);


The casts serve no purpose since there is a prototype in scope
(courtesy of string.h)

> str[end - start + 1] = '\0';
>}
>
>Sebastian


--
Remove del for email
 
Reply With Quote
 
s0suk3@gmail.com
Guest
Posts: n/a
 
      12-02-2008
On Dec 1, 10:23*pm, Barry Schwarz <(E-Mail Removed)> wrote:
> On Mon, 1 Dec 2008 07:35:32 -0800 (PST), (E-Mail Removed) wrote:
> >On Dec 1, 8:55*am, srikar2097 <(E-Mail Removed)> wrote:
> >> I have written this small fn. to strip down whitespaces ("\n") a given
> >> string (only leading and trailing).
> >> The program itself might not be foolproof but that is not my concern
> >> right now. When I compile this
> >> I get a warning :--

>
> >> "string_utils.c:96: warning: function returns address of local
> >> variable.

>
> >> I have declared the fn. as fn. pointer and this fn. returns the
> >> address of a string array. Why does
> >> the compiler give out this warning? Please help.

>
> >Try:

>
> >#include <stdlib.h>
> >#include <string.h>
> >#include <ctype.h>

>
> >// Return value must be manually deallocated

>
> >char* xstrip(const char* str)
> >{
> > * *while (isspace((unsigned char) *str) && *str != '\0')

>
> If isspace returns true, can the second conditional expression ever be
> false? *If isspace returns false, the second expression won't be
> evaluated. *Why is it there?


Explicitness, I guess.

> > * * * *++str;

>
> > * *const char* end = str + strlen(str);

>
> Unless you have c99, declarations must precede statements.
>
> > * *while ((isspace((unsigned char) *end) || *end == '\0') && end >
> >str)
> > * * * *--end;

>
> > * *char* buf = (char*) calloc(1, end - str + 2);

>
> Don't cast the return from calloc (or any standard *alloc).


That's got to be the most repeated line in this group

> You are paying to high a price for the single '/0' that survives the
> call to strncpy below.


Just because of setting all bits to zero? You know what they say about
premature optimization...

Sebastian

 
Reply With Quote
 
Nick Keighley
Guest
Posts: n/a
 
      12-02-2008
On 2 Dec, 06:38, (E-Mail Removed) wrote:
> On Dec 1, 10:23*pm, Barry Schwarz <(E-Mail Removed)> wrote:
> > On Mon, 1 Dec 2008 07:35:32 -0800 (PST), (E-Mail Removed) wrote:
> > >On Dec 1, 8:55*am, srikar2097 <(E-Mail Removed)> wrote:


> > >> I have written this small fn. to strip down whitespaces ("\n") a given
> > >> string (only leading and trailing).
> > >>
> > >> [...] When I compile this I get a warning :--

>
> > >> "string_utils.c:96: warning: function returns address of local
> > >> variable.


<snip>

> > >Try:


<snip>

> > >char* xstrip(const char* str)
> > >{
> > > * *while (isspace((unsigned char) *str) && *str != '\0')

>
> > If isspace returns true, can the second conditional expression ever be
> > false? *If isspace returns false, the second expression won't be
> > evaluated. *Why is it there?

>
> Explicitness, I guess.


seems like a bad reason


> > > * * * *++str;

>
> > > * *const char* end = str + strlen(str);

>
> > Unless you have c99, declarations must precede statements.

>
> > > * *while ((isspace((unsigned char) *end) || *end == '\0') && end >
> > >str)
> > > * * * *--end;

>
> > > * *char* buf = (char*) calloc(1, end - str + 2);

>
> > Don't cast the return from calloc (or any standard *alloc).

>
> That's got to be the most repeated line in this group


"the correct prototype for main is..."
"this is off-topic for comp.lang.c"


> > You are paying to high a price for the single '/0' that survives the
> > call to strncpy below.

>
> Just because of setting all bits to zero?


I think he's commenting on setting all *bytes* to zero.
Remember calloc() initialises everything to zero.

> You know what they say about
> premature optimization...


this seems more like premature pessimization


--
Nick Keighley

The beginning of wisdom for a [software engineer] is to recognize the
difference between getting a program to work, and getting it right.
-- M A Jackson, 1975
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
WARNING! Prosoftstore.com is a SCAM! WARNING! pentologer@gmail.com ASP .Net Web Services 0 07-08-2007 10:03 AM
warning C4267 and warning C4996 B. Williams C++ 17 10-27-2006 09:41 PM
Untraceable warning: "Warning: Use of "require" without parenthesesis ambiguous at (eval 23) line 1." Julian Mehnle Perl Misc 17 05-18-2006 11:00 AM
Warning: WARNING Charles Computer Support 7 08-16-2005 09:07 PM
Re: A code fix for MSVC warning C4267 (64-bit compatibility warning,e.g. Boost Spirit) Pete Becker C++ 0 02-10-2005 01:13 PM



Advertisments