Re: return a string



underscore0x5f@xxxxxxxxx (Nascimento) writes:
> How to I do to return a string as a result of a function.
> I wrote the following function:
>
> char prt_tralha(int num)
> {
> int i;
> char tralha[num];
>
> tralha = "#";
> for( i = 0; i < num-1; i++ )
> strcpy(tralha, strcat(tralha,"#"));
>
> return tralha;
> }
>
> And I really like to use it, thus:
>
> int main()
> {
> printf("%s \n", prt_tralha(5));
>
> return 0;
> }
>
> But when I compile it, gcc shows this message:
>
> tmp.c: In function `prt_tralha':
> tmp.c:16: error: incompatible types in assignment
> tmp.c:20: warning: return makes integer from pointer without a cast
> tmp.c:20: warning: function returns address of local variable

All three error messages are correct.

tralha = "#";
error: incompatible types in assignment

You can't assign strings like that. The name of a string variable (or
of any array) is implicitly converted, in most contexts, to a pointer
to its first element. See section 6 of the C FAQ,
<http://www.eskimo.com/~scs/C-faq/top.html>. You can initialize a
char array with a string literal, but I don't think that's what you
want in this case.

return tralha;
warning: return makes integer from pointer without a cast
warning: function returns address of local variable

You declared your function to return a char (a single character
value). You're trying to return a char*. The types are incompatible.
(The "integer" in the first warning refers to type char, which is an
integer type.)

Even if prt_tralha() were declared to return a char*, returning the
address of a local variable would be invalid. Your array tralha
ceases to exist as soon as the function terminates. Your main program
would receive a pointer to a non-existent object, and any attempt to
use it will invoke undefined behavior. In the worst case, it will
work as expected, failing only at the most inconvenient possible
moment. (The compiler isn't required to diagnose this error, but gcc
is kind enough to do so anyway.)

Other problems:

Your declaration "char tralha[num];" declares a variable length array
(VLA). This is a new feature in C99. If you're not concerned about
portability to compilers that don't support VLAs, that's fine, but you
should be aware that such support is not (yet?) universal. You might
consider using malloc() to allocate the memory dynamically.

> for( i = 0; i < num-1; i++ )
> strcpy(tralha, strcat(tralha,"#"));

What is the purpose of the strcpy()? strcat() appends "#" to your
string (assuming tralha is a valid string in the first place) and
returns a pointer to its first element. The strcpy() copies the
nstring onto itself. That's either undefined behavior or a no-op, I
don't remember which.

What you're trying to do is set tralha to a string of num '#'
characters. Using strcat() for this is wasteful.

for (i = 0; i < num; i ++) {
tralha[i] = '#';
}
tralha[num] = '\0';

or

memset(tralha, '#', num);
tralha[num] = '\0';

And since you need space for the trailing '\0', the size of tralha had
better be at least num+1.

Since C doesn't treat arrays as first-class objects (you can't assign
them, compare them, or pass them as parameters, at least not
directly), dealing with character strings can be tricky, especially
when you don't know until execution time how big they're going to be.

If you want a function to return a variable-sized string (or any
array) to its caller, there are basically 3 ways to do it.

1. Let the caller allocate the array. The caller then needs to pass
in the address of the array and its size (and you need to decide what
to do if the caller's array isn't big enough). See the standard
fgets() function for an example.

2. Return a pointer to a static variable. Since static variables
continue to exist after the function returns, this avoids the problem
you had. The drawback is that there's only one allocated result; if
you call your function multiple times, each call will clobber the
previous result. This is especially bad in the presence of recursion
<OT>or multi-threading</OT>.

3. Allocate the result array in the function using malloc(). This is
probably the most flexible method, but it then require the caller to
free() the array when it's finished with it.

--
Keith Thompson (The_Other_Keith) kst-u@xxxxxxx <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
.



Relevant Pages

  • Re: chars
    ... foo is a pointer to a string. ... No, foo is a pointer to char, the first element in the anonymous array. ...
    (comp.lang.c)
  • Re: "Mastering C Pointers"....
    ... A pointer is a kind of variable that can "point to" some object. ... has a type (pointer to int), and a value of some kind. ... You may know that you can access these integers by using array notation ... The function will take one argument, a string, and will return the length ...
    (comp.lang.c)
  • Re: Please help!
    ... > hehe i thought type casting to a pointer to an array would do the ... a string is a completely different beastie from a number. ... And in your case you need a single char for each ...
    (comp.unix.programmer)
  • Re: new IL: C (sort of...).
    ... C doesn't need a string type... ... variant of PL/1 which was very Pascal-ish. ... - C does implement an array declaration. ... effectively converted into a pointer that can be used with the offset ...
    (comp.lang.misc)
  • Re: Can C do it ?
    ... Any time you use an lvalue of array type (which includes most used of string literals except as initializers for a char array), it is automatically converted into a pointer to the first element of the array. ...
    (comp.lang.c)