简体   繁体   中英

why does passing char[] not work, but (deprecated conversion) char* does?

I cannot explain myself the reason for the following behaviour. I initialize two pieces of text, one as char*, the other as char[] and put them into a structure. Both appear fine in the structure, but back in main, the second one is lost, and the first gives me a compiler warning which i understand (deprecated conversion from string constant to char*).

This is the first question I ask here, and I apologize for anything done wrong. And yes, I tried to search, but related to char* and char[], there appear a lot of Q&A, none I found similar to the nested problem I am having.

From the attached code I get the output:

get_struct: 5 test test2
main: 5 test

(the test2 at the end missing)

So the code:

    #include <iostream> 

    typedef struct {
        double a_double;
        char* a_char1;
        char* a_char2;
    } testStruct;

    testStruct make_struct(double d, char* c1, char* c2) {          
        testStruct t;

        t.a_double = d;
        t.a_char1 = c1;
        t.a_char2 = c2;

        return t;
    }

    void get_struct(testStruct &t) {    
        char* test_char1 = "test";
        char test_char2[] = "test2";
        double test_double = 5;

        t = make_struct(test_double, test_char1, test_char2);

        std::cout << "get_struct: " << t.a_double << " " 
            << t.a_char1 << " " << t.a_char2  << std::endl;
    }

    int main() {
        testStruct t;
        get_struct(t);
        std::cout << "main: " << t.a_double << " " 
            << t.a_char1 << " " << t.a_char2 << std::endl;
        return 0;
    }

You have a problem in that you store pointers to local variables in the structure.

In the case of the test_char2 array, it no longer exists once the get_struct function returns. This means that the pointer a_char2 no longer points to a valid string, and dereferencing this pointer is undefined behavior.

The reason the first pointer works, is because it doesn't point to a local variable, it points to a string literal, and those are stored elsewhere in memory.

When coding in C++, there is no longer a reason to use pointers or arrays for string, instead use the std::string class.

char* test_char1 = "test";

This creates a pointer to a string literal. String literals are const but, for historical reasons, the language allows the pointer to be non- const ; however, this is deprecated, hence the warning. If you attempt to modify the string, then you'll get undefined behaviour.

char test_char2[] = "test2";

This creates a local array, initialised by copying a string literal. It is not const , so you can modify it if you like. But once the function returns, this is destroyed, so your structure ends up with a dangling pointer to invalid memory. That is why you get undefined behaviour when you try to print it in main .

Two pieces of advice:

  • Don't use C-style character arrays and pointers to represent strings; use std::string . That manages memory for you, avoiding the lifetime issues you're encountering here.
  • If you really want to mess around with arrays and pointers, use const char* unless you actually need to modify it. Otherwise, it's difficult to work with string literals.

When assigning a string literal to a local char[] -variable, that storage is allocated locally.

Exporting that pointer from that scope violates the (automatic) storage duration constraints of the local variable and accessing the memory behind the pointer is undefined behaviour.

In contrast, when assigning to char* , a pointer to a statically allocated string is created and no copying to local storage takes place. Thus, the pointer remains valid outside that scope.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM