🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

4回答

1974閲覧

c言語 複数の変数を指定する場合

mtlc0566

総合スコア6

C

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

0グッド

1クリップ

投稿2020/12/25 07:34

編集2020/12/25 07:37
#include <stdio.h> #include <limits.h> int main() { int num; char str[]; num = 1996, printf("%d",num); str[]="HELLO c";   printf("%s",str); } ```### 前提・実現したいこと ### 発生している問題・エラーメッセージ 内定先の課題でc言語の基礎をやっているのですが、strのサイズが不明というエラーが出てしまいます。どうしたらよいのでしょうか? ### 該当のソースコード ```ここに言語名を入力 ソースコード

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

Zuishin

2020/12/25 07:38

二回宣言してるからでは?
mtlc0566

2020/12/25 07:40

間違えて投稿してしまい編集しました。上記のようなcodeでもstrのサイズが不明と出てしまいます。
Zuishin

2020/12/25 07:49 編集

上の宣言を行ごと削除して下の str[] に char を入れてみてください。
mtlc0566

2020/12/25 07:58

内定先の方にそれで提出したら、c言語では変数は原則初めに記述してくださいと言われてしまって。。。
Zuishin

2020/12/25 07:59

意味不明なルールですが、それなら二番目のを上に持っていけばいいでしょう。
pepperleaf

2020/12/25 12:19

> c言語では変数は原則初めに記述 以前はそうだった筈、、もっとも20世紀の話か?
ozwk

2020/12/25 14:58

> もっとも20世紀の話か? C99からですね 浸透したのはもっと後でしょうか
guest

回答4

0

あなたの書いたCソースプログラムをコンパイルするとき、コンパイラは、それを機械命令に翻訳します。
コンパイラが機械命令を作り出すとき、機械命令に変数の場所を教えてあげます。

例えばmain関数の int num; というのを見たコンパイラは、以下のように考えます。
このnumという名前は、main関数の中で宣言されているから自動変数なのだな。だったら、スタックのここに置くことにしよう。int型だから4バイトの場所を取っておけばいいな。(コンピュータのCPUやOSによっては8バイトの場合もあります)

次に、char str[]; を見たコンパイラは、以下のように考えます。
strという名前はmain関数の中で宣言されているから自動変数なのだな。だったら、スタックのここに置くことにしよう。文字の配列だけど長さを書いていないから何バイト取ればいいかわからない。困った、エラーメッセージを出して中止しよう。

もしも、char str[]="HELLO c";と書いてあったなら、コンパイラは、これを入れるなら8バイトあればいいな、あとそこにはHELLO cという7文字と終了文字1文字を入れておこう、と思って仕事を続けます。こういう文を変数の初期化といいます。

配列ではない変数を初期化する場合は int i = 42; で代入に似ていますね。
このために、配列に対する代入文が str[]="HELLO c"; と書けそうな気しますね。
それが出来ない理由は、コンパイラは何バイトコピーするかが分からないからなのです。
詳しい説明は長くなるので省略しますが、Cというコンパイラ言語を作ったときに、OSを作ることが出来るような仕様にしたことが影響しています。

ということで、コンパイラに分かることと分からないことがあるとか、コンパイラを作ったときに事情でCの文法はそうなっているのです。皆さんが書いているように、間違った文法で書くとコンパイラが困りますので、文法はは覚えておいてください。

投稿2020/12/25 11:38

ppaul

総合スコア24670

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

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

fana

2020/12/25 13:07

> エラーが出てしまいます。どうしたらよいのでしょうか? という質問に対する回答というのは何になるのでしょうか? 「文法を覚えろ」ということでしょうか?
ppaul

2020/12/25 14:48

teratailでの質問に答えるとき、私は質問者がどういう立場であるかによって、答え方を変えるようにしています。 もしも、学校での課題を聞いているなら、多少のヒントは出しても答えは教えません。それで分からない人なら単位を落とした方が良い経験になると思うからです。 必要に迫られてプログラムを作っているひとなら、重要な部分を作ってあげることもあります。 これからプログラミングを覚えようとしている若い(と思われる)人に対しては、いろいろなアルゴリズムやテクニックがあるのだと実例を見せてあげます。 mtlc0566さんの場合は内定先からC言語の宿題が出たと言うことですので、これからソフト開発を仕事にしていく人だと認識しています。そういう立場の人にとって、C言語の文法を覚えることは最低線です。しかし、文法だからと言う理由で丸暗記をするのは、出来る人もいれば出来ない人もいます。 ソースプログラムというのはコンピュータに対する指示書ですから、それを実行するコンピュータが理解して実行できるか、その仲介をするコンパイラが指示を理解できるかというように考えると、文法のある部分は自然と理解できるようになります。そうやって覚えた文法は、忘れてしまったときでも思い出しやすくなり、丸暗記に比べて応用が利きます。 ピンポイントで助け船を出すことは、安易に人に頼る習慣をつけ、職業ソフト開発者としては使いものに 成らなくなる危険があるのです。 そうならないようにとの思いで、この回答を書いたのです。 この思いがmtlc0566に伝わってくれることを願っています。
mtlc0566

2020/12/26 02:42

ありがとうございます!!! 調べたら、わかりました!
guest

0

自己解決

#include <stdio.h>
#include <limits.h>

int main()
{
int num = 1996;
char str[7]="HELLO c";

  printf("%s",str);
printf("%d",num);

return;

}

投稿2020/12/25 13:38

mtlc0566

総合スコア6

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

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

thkana

2020/12/25 23:03 編集

誤っているので低評価...コンパイル時に警告(warning)が出ていませんか? もし出ていたら、警告はその内容を吟味して、無視して良いという根拠が無い限り無視しちゃいけません。 (追記:試してみたらgccもMicrosoft Cもデフォルトだと警告は出ないな..) ついでに、limits.hはなんのため?
mtlc0566

2020/12/26 02:09

どこか間違っているでしょうか? 課題に初めからついていたのでよく分かりません!
thkana

2020/12/26 03:00

コンパイラに何を使っているかにもよりますが、microsoft c(Visual Studio)なら/Wall, gccなら-Wallを付けてコンパイルし、出てくる警告メッセージを読んでみて下さい。 > よく分かりません! なにを元気に感嘆符? まぁ、簡単に言えば「要らない」ので削って下さい>limits.h あともう一点、int型の関数なので、returnするのならなにか値を返しましょう。main関数なので適当に補ってくれているようですが。
guest

0

char str[];

C言語ではこのような宣言はできません。
サイズを明記する必要があります
そして、

str[]="HELLO c";

C言語ではこのような代入はできません
strcpy関数を使うなどする必要があります

投稿2020/12/25 08:40

y_waiwai

総合スコア88038

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

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

0

strのサイズが不明というエラーが出てしまいます。どうしたらよいのでしょうか?

指摘されているとおり、配列strのサイズが不明なので、宣言時に要素数を指定してください。
要素数は、後でコピーする文字列が入るのに十分な数を確保しておきます。

Diff

1- char str[]; 2+ char str[10];

そして、次は文字列のコピーの仕方を調べて、プログラムを書き換えてください。

投稿2020/12/25 07:48

Daregada

総合スコア11990

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

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

mtlc0566

2020/12/25 07:57

回答ありがとうございます!!! strに10をいれてもコンパイルすると移植性のないポインタ変換(関数main)というえらーがでてしまいます。何か間違えているんでしょうか?
Daregada

2020/12/25 10:36 編集

配列に文字列を設定するのに「str[] = "...";」という書き方は(宣言時以外には)できません。 回答にすでに書いてあるように、「そして、次は文字列のコピーの仕方を調べて、プログラムを書き換えてください。」
Zuishin

2020/12/25 08:10

できますよ。
Daregada

2020/12/25 08:13

ええと、"宣言時に「str[] = "...";」する(初期値として設定する)のではなく、質問のコードに記載されているように、宣言後に「str[] = "...";」として文字列をコピーすることはできません。"と書けばいいですか?
Zuishin

2020/12/25 08:17 編集

宣言が二回あるのが問題なので、それを一つにすればコピーしなくてもコンパイル通ります。
Daregada

2020/12/25 08:59

ええと、現在の(私が回答した時点の)質問のコードは修正されて宣言はひとつだけなんですが。
Zuishin

2020/12/25 09:05

宣言しかありませんね。コンパイルエラーになります。strcpy でコピーしてもできますが、コピーしなくても宣言時に定義できる方法があるので調べてみてください。
Zuishin

2020/12/25 09:07

少なくとも > 配列に文字列を設定するのに「str[] = "...";」という書き方はできません。 これは間違いですし、サイズは自動的に設定されるのでサイズ指定も不要です。
Zuishin

2020/12/25 09:09

8 バイトしかない固定データを使うのに 10 バイトの配列を宣言するのも意味がわかりません。ただのマジックナンバーになっています。
Daregada

2020/12/25 09:37

ご自分で満足できる回答を書いて、そちらで十分に論を述べてくださいよ。
Zuishin

2020/12/25 09:49

ええと、間違っていても指摘するなということですか?
Daregada

2020/12/25 10:05 編集

いいえ。宣言時に文字列を指定できることは、すでに訂正コメントを書いているので、そちらをご覧下さい。 さて、質問者が現在コードに書いている「str[] = "HELLO c";」は、現時点で(型が欠けていて)宣言になっていないという点はいいですよね? 「(最初の質問に書いていたように)先頭にcharを付けてこれを宣言にし、(内定先に言われているので)上に持って行けばいい」という解決策と、「上に書いてある宣言を要素数を指定してエラーを解消し、"HELLO C"の設定はstrcpyなりstrncpyなりで行なう」という解決策が、優劣は別にしてどちらも考えられますよね?
Daregada

2020/12/25 10:04

あとは、この後の内定先の方針次第でしょう。このまま、文字列リテラルを変更したり、キーボードからの入力に変更したり、ファイルからの入力に変更したりするなら、現在の文字列リテラルの文字数に固執せず、この先の進行に「十分な大きさ」の配列を用意して、sizeofの使い方を説明しつつ、バッファーオーバーフローを起こさない文字列コピーのしかたなどを教育していくことになります。
Zuishin

2020/12/25 10:17

訂正を書く前の指摘についてこれだけ反論していたのでは?
Zuishin

2020/12/25 10:23

どちらの方法が良いかではなく、できることをできないと書いたことについて間違いだと指摘しています。
Daregada

2020/12/25 10:35 編集

えー? それは直後に訂正しているじゃないですか。 宣言時には文字列を設定できることは最初から理解していますし、その上で、「現在のコードでは宣言時に設定していないので、そういう風には書けません」と言っているのですが。
Daregada

2020/12/25 10:37

> さて、質問者が現在コードに書いている「str[] = "HELLO c";」は、現時点で(型が欠けていて)宣言になっていないという点はいいですよね? こちらについては理解されていますか?
Zuishin

2020/12/25 11:07

ええと、修正依頼でそのように書いていまぁす。 質問者の間違っているところを指摘するのではなく、別の方法を取らせようとそこまでこだわるのはなぜですかぁ?
Daregada

2020/12/25 11:08

人のことは気にせず、十分にお飲みください。
Zuishin

2020/12/25 11:09

まさかの素面でしたか。お疲れ様です。
Zuishin

2020/12/25 11:10

ええと、質問者のコードは間違っていますがぁ、方法自体は間違っているわけじゃないのでぇ、それを間違っているという間違いを回答しなくてもいいと思いまぁす。
Zuishin

2020/12/25 11:22 編集

そりゃ strcpy とマジックナンバーを使うこの回答の方法でも求められる結果は出ますよ? malloc を使ってもいいし、printf を puts に変えたっていい。 でも、質問者は自分のコードのどこが間違っているかわからないのに、そこをスッパリ無視して文字列で配列を定義するところ(間違ってないところ)が間違いのように言って別の方法を提案するのはどうなんでしょうね、って話ですよ。
Daregada

2020/12/25 11:32

そうですか。わかりました。さようなら。
Zuishin

2020/12/25 11:34

ようやくわかりましたか。今夜はぐっすりお眠りください。明日も早いんでしょうから。 眠れなかったら運動するといいみたいですよ。
mtlc0566

2020/12/25 11:49

メリークリスマス!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問