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

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

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

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

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

4回答

5166閲覧

C言語の関数にchar配列を渡し、ポインタとして扱った時の動作

dotbot

総合スコア10

char

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

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2020/05/15 03:08

はじめに

C言語でタイトルに書いたことが気になり、プログラムを実行してみたところ、よくわからない結果となったため、どのような仕様でそうなってるのか気になったので質問します。

基本のコード

C

1#include <stdio.h> 2 3void charrr(char*); 4 5int main(void) { 6 char c[5] = "ABC"; 7 8 charrr(c); 9 10 puts("a"); 11 12 puts(c); 13 14 return 0; 15} 16 17void charrr(char *c) { 18 c = "XYZ"; 19 c[1] = 'O'; 20}

まず、このコードはコンパイルに成功します。
そして実行してみると、puts("a");を実行することなく終了します。関数の中で文字列を渡したポインタを添え字でアクセスして代入してしまっていることが原因と考えられます。
次に、関数内のc[1] = 0;をコメントアウトして実行してみます。その結果がこちらです。

a ABC

配列に文字列は代入できないので当然と言えば当然ですが、それならば上のコードはなぜ実行停止してしまうのか分かりません。c言語のどのような仕様がこれを引き起こしているのか教えていただきたいです。よろしくお願いします。

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

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

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

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

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

guest

回答4

0

C言語の仕様としては、それはアクセス違反となるので、なにが起こるかわからない、なにが起こっても文句言えない、ということになっとります。

まあ、至極正しい反応、ということになろうかとおもいます

投稿2020/05/15 03:17

y_waiwai

総合スコア88042

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

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

0

ベストアンサー

前提1

同じ文字列リテラルでも、文脈に依って意味が異なります。

  • char c[5] = "ABC";

これは配列の要素の初期化です。
書き換え可能な領域に各文字が確保されるので、後から要素を入れ替えられます。

  • *char c = "ABC";

書き換え不可能な連続領域に文字列を確保した後、先頭アドレスをcに代入しています。

前提2

関数charrr内では、cはただのポインタ変数です。
中に配列が入っているかどうかなんて知ったこっちゃありません。

C

1void charrr(char *c) { 2 c = "XYZ"; // この "XYZ" は書き換え不可能な領域に確保されます 3 c[1] = 'O'; 4}

本題

関数の中で文字列を渡したポインタを添え字でアクセスして代入してしまっていることが原因と考えられます。

落ちるのは書き換え不可能な領域を書き換えようとしているからでしょう。

配列に文字列は代入できないので当然と言えば当然ですが

関数charrr内の変数cはただのポインタ変数ですので、代入それ自体には成功しています。
呼び出し元に影響しないのは別件です。

次のように書いたとき、『0』と表示されないことは理解できるでしょうか。
これと同じ理由で、ポインタ変数そのものを書き換えても呼び出し元には影響しません。

C

1void func(int a) { 2 a = 0; 3} 4 5int main(void) { 6 int a = 42; 7 func(a) 8 9 printf("%d\n", a); // 42と表示される 10 11 return 0; 12}

投稿2020/05/15 03:30

LouiS0616

総合スコア35668

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

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

0

配列に文字列は代入できないので当然と言えば当然ですが

いえ、charrr内でのc = "XYZ";は、cポインタ値を変えているだけで、渡されたchar c[5]のほうにはまったく影響しません

投稿2020/05/15 03:22

maisumakun

総合スコア146018

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

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

0

「文字列リテラルを書き換えてはダメですよ.未定義ですぞ」 ← どうなるかやってみた

とか わざとやっておいて
「何故止まるのか?」とか言われましても.

投稿2020/05/15 03:26

fana

総合スコア11996

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問