0

以下のコードで、strncpyのコンパイルと実行の両方を削除すると、セグメンテーション違反は発生しません。しかし、strcpyを使用すると、セグメンテーション違反が発生します。どちらの場合も、読み取り専用アドレスを正しく変更しようとしていますか?それでは、なぜ予期しない動作が発生するのでしょうか。

#include<stdio.h> 
#include<string.h>
int main()
{
unsigned char* newPrompt="# ";
static unsigned char* au1CLIPromptStrings [] =
{
 "",
 "Login: ",
 "Password: ",
  "0123456789012345678901234",
  "0123456789012345678901234",
};
/* here am trying to moodify the read only address */
au1CLIPromptStrings[3] = "# \0";
au1CLIPromptStrings[4]  = "# \0";
/* removed two strncpy second time */
printf("a1 = %s and a2 = %s\n",au1CLIPromptStrings[3],au1CLIPromptStrings[4]);

/* here using strcpy am trying to modify */
strncpy(au1CLIPromptStrings[3],newPrompt,strlen(au1CLIPromptStrings[3])) ;
strncpy(au1CLIPromptStrings[4],newPrompt,strlen(au1CLIPromptStrings[4])) ;
}

前もって感謝します..

私が今直面している問題が1つあります。au1CLIPromptStringsの値を、多くの場所で使用されているbiengである別のダブルポインターに渡す必要があります。したがって、構造要素elemetにあるunsigned char型のダブルポインターにau1CLIPromptStringsのアドレスを割り当てると、要素は、アドレスが適切になっている場合でもNULLを取得します。どこでも同じau1CLIPromptStrings varibaleを使用することはできません。これは、私が言った、

 unsigned char **newPrompt1 =NULL;
 newPrompt1 = au1CLIPromptStrings;
 printf("a1 = %s and a2 = %s\n", newPrompt1[3],newPrompt1[4]); 


#include<stdio.h>
#include<string.h>
int main()
{
unsigned char *newPrompt="# ";
unsigned char **newPrompt1 =NULL;
unsigned char au1CLIPromptStrings [7][30] =
{
"",
"Login: ",
"Password: ",
" 0123456789012345678901234",
" 0123456789012345678901234",
};
newPrompt1 = au1CLIPromptStrings; // here am assigning the address
printf("b1 = %u and b2 = %u\n",newPrompt1,au1CLIPromptStrings);
printf("a1 = %s and a2 = %s\n",newPrompt1[3],newPrompt1[4]);
}
4

2 に答える 2

2

を使用する方法を示すために変更された独自のプログラムは、使用 [][]する代わりに混乱を減らすのに役立ちます*[]

#include<stdio.h> 
#include<string.h>
int main()
{
unsigned char newPrompt[10]="# ";
unsigned char au1CLIPromptStrings [5][30] =
{
 "",
 "Login: ",
 "Password: ",
  " 0123456789012345678901234",
  " 0123456789012345678901234",
};

printf("a1 = %s and a2 = %s\n",au1CLIPromptStrings[3],au1CLIPromptStrings[4]);

strcpy(au1CLIPromptStrings[3],"# \0");
strcpy(au1CLIPromptStrings[4],"# \0");

printf("a1 = %s and a2 = %s\n",au1CLIPromptStrings[3],au1CLIPromptStrings[4]);

strncpy(au1CLIPromptStrings[3],newPrompt,strlen(au1CLIPromptStrings[3])) ;
strncpy(au1CLIPromptStrings[4],newPrompt,strlen(au1CLIPromptStrings[4])) ;
}
于 2013-03-19T05:59:42.740 に答える
1
static unsigned char* au1CLIPromptStrings [] =
{
    "",
    "Login: ",
    "Password: ",
    "0123456789012345678901234",
    "0123456789012345678901234",
};

これは、各メンバーが char 型を指すポインターである配列を定義します。初期化後、各メンバーは変更できない静的領域を指しています。はい、そのポインターを変更して、別のメモリ ブロックを指すようにすることができます。

au1CLIPromptStrings[3] = "# \0";
au1CLIPromptStrings[4]  = "# \0";

しかし、実際には、元のメモリ ブロックを変更するのではなく、ポインターの値を変更していました (または、単に別のメモリ ブロックを指していると言います)。オリジナルは読み取り専用です。

2番目の質問の私のコード:

#include<stdio.h> 
#include<string.h>

int main()
{
    unsigned char **newPrompt1 =NULL;
    static unsigned char* au1CLIPromptStrings [] =
    {
        "",
        "Login: ",
        "Password: ",
        "0123456789012345678901234",
        "0123456789012345678901234",
    };

    newPrompt1 = au1CLIPromptStrings;
    printf("a1 = %s and a2 = %s\n", au1CLIPromptStrings[3],au1CLIPromptStrings[4]);
    printf("a1 = %s and a2 = %s\n", newPrompt1[3],newPrompt1[4]); 

    return 0;
}

gcc を使用した cygwin では、次のように表示されます。

a1 = 0123456789012345678901234 and a2 = 0123456789012345678901234
a1 = 0123456789012345678901234 and a2 = 0123456789012345678901234
于 2013-03-19T05:46:55.660 に答える