0
struct employee {
        int employeeId;
        double payrate;
        char *inputname;
    };



    int main (void){

        //remember the struct before employee

        struct employee davidB;
        fgets(davidB.inputname, 20, stdin);
        davidB.employeeId = 1;
        davidB.payrate = 45020.50;


        printf("The employees name is %s\n The employees id num is  %d\n The employees payrate is %f\n", davidB.inputname, davidB.employeeId, davidB.payrate);

        struct employee ericG;

        printf("Please enter employee name, id number, and payrate\n");

        scanf("%s", ericG.inputname);
        scanf("%d", &ericG.employeeId);
        scanf("%lf", &ericG.payrate);

        printf("The employees name is %s\n The employees id num is  %d\n The employees payrate is %f\n", ericG.inputname, ericG.employeeId, ericG.payrate);

        return 0;
    }

私の質問は次のとおりです。

                          fgets(davidB.inputname, 20, stdin);  
                          scanf("%s", ericG.inputname);

最初のものはなぜ機能し、2番目のものはスタックオーバーフローを引き起こすのですか? さらに、「文字列」をポインターに直接割り当てることができるのはいつですか? また、事前定義された char 配列である必要があるのはいつですか?

例えば:

   const char *string = "Hey"; //works? so can't I do the same with the scanf above?
4

3 に答える 3

1

これらの関数を使用するには、メモリを割り当てる必要があります。そうしないと、このポインタ ( davidB.inputname) がガベージを指しているため、スタック オーバーフローが発生します。

1つのオプションは、次のように定義することですが、読み取る文字数を制限できるchar inputname[21];ため、これは関数に対してのみ機能します。fgetsしかし、scanf読もうとしている文字列のサイズを 100% にできない限り、できることは何もないので、それ以外の場合は避けたほうがよいでしょう。

于 2013-01-28T23:56:34.587 に答える
1

にメモリが割り当てられていません`inputname。したがって、どちらも未定義の動作を呼び出します。いずれにしても合法的な C では動作しません。

しかし、次のように直接割り当てると:

const char *string = "Hey";

string文字列リテラルを指すだけです。したがって、そこにメモリを割り当てる必要はありません。

このようにして、structメンバーに直接割り当てることができます。

    struct employee davidB;
    davidB.inputname = "Eric"; // Thiis is valid.
    davidB.employeeId = 1;
    davidB.payrate = 45020.50;

それ以外の場合は、動的にメモリを割り当てる必要がありますinputname:

    struct employee davidB;
    davidB.inputname = malloc(256);
    fgets(davidB.inputname, 256, stdin); 
    davidB.employeeId = 1;
    davidB.payrate = 45020.50;
于 2013-01-28T23:57:27.870 に答える
1

一方がうまくいくのはたまたまの運で、もう一方はそうではありません。inputname が指すメモリを割り当てていないため、どちらの方法も正しくありません。したがって、関数はランダムなメモリ位置にデータを入力しているだけです。

const char *string = "Hey" が機能するのは、これが静的データであり、コンパイラがどこかにスペースを割り当てているためです。

于 2013-01-28T23:58:03.510 に答える