質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

1457閲覧

C言語でchar型の変数に値を代入すると、代入元のcharの中身がなくなる現象の理由をしりたい。

Kchan_01

総合スコア110

char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/02/24 10:38

C言語を基礎を学んでいます。
C言語でstrcpy関数を自作していたら、変な現状に出会いました。
whileでchar型変数へ代入すると、代入元の値が消えます。
while分の使い方を省略した書き方から、変えると値は保持されます。
私のwhile文の理解が間違っているようなのですが、どこが間違っているのかわからないです。
アドバイスをいただければ幸いです。

c

1#include <stdio.h> 2 3void istrcpy(char *s1, char *s2) 4{ 5 6 while((*s2++ = *s1++) != '\0'){ 7 } 8 *s2 = '\0'; 9} 10 11int main(void) 12{ 13 char str1[] = "aiueo"; 14 char str2[] = "12345"; 15 16 printf("str1 : %s\n", str1); 17 printf("str2 : %s\n", str2); 18 printf("str1 p : %p\n", &str1); 19 printf("str2 p : %p\n", &str2); 20 21 istrcpy(str1, str2); 22 23 printf("str1 : %s\n", str1); 24 printf("str2 : %s\n", str2); 25 printf("str1 p : %p\n", &str1); 26 printf("str2 p : %p\n", &str2); 27 28 return 0; 29}

実行結果

terminal

1str1 : aiueo 2str2 : 12345 3str1 p : 0x7ffeeee3cb56 4str2 p : 0x7ffeeee3cb50 5str1 : 6str2 : aiueo 7str1 p : 0x7ffeeee3cb56 8str2 p : 0x7ffeeee3cb50

#試したこと

while文について下記の書き換えを行うと元の値は消えないです。

c

1 while (*s != '\0') { 2 *d = *s; 3 d++; 4 s++; 5 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

*s2 = '\0'; が不要だと思います。

while の条件式として与えている (*s2++ = *s1++) != '\0' において、(*s2++ = *s1++)\0 であるとき (終了しようとするとき) には (*s2++ = *s1++) はもう評価が終わっているのです。 コピー元である s1'\0's2 に代入してからループが終わっているのです。

ですから、 *s2 = '\0'; としたときには str2 として確保されているメモリの範囲を超えて代入されていて、超えたところがたまたま str1 の先頭だったのでしょう。

str1str2 がどのように配置されるかは言語仕様では決まっていないのでこのような結果になったのは偶然でしょうが、いずれにしても str2 の範囲の外を書き換えているのが間違いです。

投稿2020/02/24 10:47

編集2020/02/24 11:16
SaitoAtsushi

総合スコア5444

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2020/02/24 10:59

> どのように配置されるかは言語仕様では決まっていないのでこのような結果になったのは偶然 ですね。 VC++ 2019のコンパイラでは、4バイトのアライメントだったので、問題無し。
Kchan_01

2020/02/24 11:03

>>超えたところがたまたま str1 の先頭だったのでしょう。 この偶然によって、値が移動したように感じて混乱していました。 while文についてもう一度復習します。 ご回答ありがとうございます。
guest

0

  • 余計な *s2 = '\0'; によって 'a' が上書きされてしまう…ことが
  • 質問者の実行結果から、このような配置だったことが分かる
  • メモリレイアウトを描くと一目瞭然

メモリレイアウト

…ホワイトボードが手に入ったので描いてみました。コントラスト悪くないですね。青、赤のマーカーも揃えなきゃw

投稿2020/02/25 04:44

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

while((*s2++ = *s1++) != '\0')

これは、\0も書き込みますので

*s2 = '\0';

を行ってしまうと、この時点のs2は元のs2文字列の範囲外となり
偶然s1の先頭だったためs1に書き込みが行われてしまいました。

c

1int main(){ 2 char str1[] = "aiueo"; 3 char str2[10] = "12345";

などとするとその現象が起きなくなるでしょう。

投稿2020/02/24 11:00

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

原因は他の方々の回答のとおりですが、こんな風に書いても動くようになります。

c

1void istrcpy(char *s1, char *s2) 2{ 3 while((*s2 = *s1) != '\0'){ 4 s1++, s2++; 5 } 6 *s2 = '\0'; 7}

あと、libcのstrcpy関数と引数の順序が違うのが気になりました。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/strcpy.3.html

投稿2020/02/24 10:59

編集2020/02/24 11:01
shiracamus

総合スコア5406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

istrcpyの最後にある*s2 = '\0';が余計です。

「ループを抜けてきた」ということは、*s2++ = *s1++\0だった、つまり最後のヌル文字までコピーした状態です。なので、*s2 = '\0';とすると、終端の次に\0を書き込んでしまうことになります。

投稿2020/02/24 10:46

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問