LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How to return empty char * ? (https://www.linuxquestions.org/questions/programming-9/how-to-return-empty-char-%2A-750700/)

cpthk 08-27-2009 02:22 PM

How to return empty char * ?
 
Hi:

Here is my code:
Code:

char * func1(){

...
...
return "";
}

This code give me warning "deprecated convertion from string to char *
I then try:
Code:

char * func1(){

...
...
return '';
}

This gives me error "empty character constant", how do I fix this?

orgcandman 08-27-2009 02:27 PM

Depending on how you're using the return value, you likely either want to return:
"\0"

or

NULL

fantas 08-27-2009 02:38 PM

First you need to make yourself clear why you get this warning. It's appearing because you return a constant string literal while the function should return a (non const) char pointer.

I can think of two ways to fix this, one in an ugly way (but leaving the function signature intact), the other the much better way - assuming you want a valid c string as returned data.

dirty (static data as returned data):
Code:

char * func1()
{
    // ...
   
    static char empty[1] = { '\0' };
    return empty;
}


better (const correctness, valid string literal)
Code:

const char * func1()
{
    // ...
    return "";
}


cpthk 08-27-2009 03:28 PM

so anything like "", gcc treats it as constant?

Another question, if I do "", does gcc treat it as string or char * ? I know in vc++, it treats "" as char *.

fantas 08-27-2009 04:49 PM

Yes, GCC will treat it as 'const char *'. MSVC has some settings to treat string literals as constant too IIRC (and store them in read-only memory). Are you sure 'char *' is the default setting there ? Would be a bit surprising, but MSVC has always been a sort of black box to me concerning some of its settings.

bigearsbilly 08-27-2009 05:30 PM

what are you trying to do?

what you are returning is a constant string, i.e. compiled in.
the fact that you specified it ""
means it's there at compilation, so is, of course, constant

cpthk 08-27-2009 06:02 PM

I guess MSVC treat "" as const char *. I said char * just to say MSVC doesn't treat "" as std::string

orgcandman 08-27-2009 06:19 PM

Quote:

Originally Posted by fantas (Post 3659896)
Code:

char * func1()
{
    // ...
   
    static char empty[1] = { '\0' };
    return empty;
}


Quick aside - the biggest reason that this is code above is a bad technique is that it is actually functionally different from:

Code:

char *func1()
{
    // ...
   
    return "\0";
}

The reason being this code following:

Code:

{
  char *p = func1();
  *p = 'A';
}

Not only will code using the static variable not segfault, but it'll allow you to reassign the value of empty. At least on modern systems with modern gcc, you should get a segfault due to writing to a read-only codespace. Both aren't good, but one can lead to "dangerous things" where the other (hopefully) just crashes.

fantas 08-27-2009 06:30 PM

I agree - both are bad, but I at least made a mention of it not being preferable, while you gave it as a solution to the OP. Apart from that, your code will still spawn this warning mentioned in the first post ...

And "dangerous things" ??? Oh, please ... *facepalm*

graemef 08-27-2009 09:27 PM

Quote:

Originally Posted by cpthk (Post 3659950)
so anything like "", gcc treats it as constant?

Another question, if I do "", does gcc treat it as string or char * ? I know in vc++, it treats "" as char *.

From the C++ standard 2.13.4 String Literal

Quote:

A string literal is a sequence of characters (as defined in 2.13.2) surrounded by double quotes, optionally beginning with the letter L, as in "..." or L"...". A string literal that does not begin with L is an ordinary string literal, also referred to as a narrow string literal. An ordinary string literal has type “array of n const char” and static storage duration, where n is the size of the string as defined below, and is initialized with the given characters. A string literal that begins with L, such as L"asdf", is a wide string literal. A wide string literal has type “array of n const wchar_t” and has static storage duration, where n is the size of the string as defined below, and is initialized with the given characters.
Or put another way anything in double quotes should be const char *.

If you plan to return a sting literal then the signature of your function should reflect that the return value is a const. If you are returning a string that can be modified but you want to be able to return an empty string return 0, the null pointer, and then test that the return value points to a valid address before doing anything with the value.

cpthk 08-28-2009 06:19 AM

so what is the final answer if I really need to return char * instead of const char * ?

dmail 08-28-2009 07:31 AM

Quote:

Originally Posted by cpthk (Post 3660641)
so what is the final answer if I really need to return char * instead of const char * ?

Returning 0 or NULL would be the best action so that you do not try and modify the string pointed to but you can use the same way as you are even though the quote by graemef states it is constant. As IIRC a string literal will deform to a char* for C compatibility reasons. This behaviour is depreciated yet not disallowed.

fantas 08-28-2009 09:01 AM

Quote:

Originally Posted by cpthk (Post 3660641)
so what is the final answer if I really need to return char * instead of const char * ?

The question remains why would you have to return a non-const char * if not for backwards compatibility to some badly coded interfaces ?
Or is it that you want to be able to modify the char * ?

orgcandman 08-28-2009 09:50 AM

Quote:

Originally Posted by fantas (Post 3660137)
while you gave it as a solution to the OP.

Hrrm? No I didn't. I said either return NULL or return "\0" directly.

Quote:

Apart from that, your code will still spawn this warning mentioned in the first post ...
Code:

[10:39:29][aconole@weston:~]
$ cat t.c
#include <stdio.h>

char *func1()
{
    // ...
    return "\0";
}

int main()
{
    char *f = func1();

    *f = 'a';

    return 0;
}
[10:39:35][aconole@weston:~]
$ gcc -o t t.c
[10:39:39][aconole@weston:~]
$ ./t
Segmentation fault

It does not - (Note the crash... it's not guaranteed by C99, but will work this way on most linux machines compiled with gcc).

With a static member:
Code:

[11:08:00][aconole@weston:~]
$ cat t.c
#include <stdio.h>

int global = 0;

char *func1()
{
    static char empty[1] = {'\0'};

    return &empty;
}

int main()
{
    char *f;

    f = func1();

    *f = 'a';

    return 0;
}
[11:09:11][aconole@weston:~]
$ gcc -o t t.c
t.c: In function âfunc1â:
t.c:9: warning: return from incompatible pointer type
[11:09:18][aconole@weston:~]
$ ./t
[11:09:21][aconole@weston:~]
$

Note - the warning, because we are not returning a correct pointer type (should be const), and the fact that this code did not crash, but instead, has altered the value of the variable empty.

Relevant sections are
6.2.4, 6.2.5, and 6.2.6 of C99

fantas 08-28-2009 09:56 AM

Quote:

Originally Posted by orgcandman (Post 3660858)
Hrrm? No I didn't. I said either return NULL or return "\0" directly.

So what's the difference ?

Quote:

Originally Posted by orgcandman (Post 3660858)
Code:

[10:39:35][aconole@weston:~]
$ gcc -o t t.c
[10:39:39][aconole@weston:~]
$

It does not.

Of course not, without enabling all warnings.


All times are GMT -5. The time now is 06:15 PM.