0からの、超初心者C++相談室




1: 名無しの民 2018/11/12(月) 14:55:13.35 ID:Tf74ZWQr
何にも知らない0からの出発、超初心者のためのC++相談室

2: 名無しの民 2018/11/12(月) 15:33:07.21 ID:uNoTWhhe
まずC#を覚えます

 

4: 名無しの民 2018/11/12(月) 16:05:28.85 ID:JkRQG90v
C99に準拠したCプログラムってC++コンパイラで完全にビルドできますか?

 

5: 名無しの民 2018/11/12(月) 16:09:07.07 ID:Uo1L8t18
>>4
型キャストが必要な場合と、C++キーワードに引っかかるケースがあるから、コンパイルできるとは限らない。

 

7: 名無しの民 2018/11/12(月) 16:35:33.39 ID:D6ILV7Jx
>>4
C99モードにすればおk
$ gcc -Wall -std=c99 -lm round.c

 

6: 名無しの民 2018/11/12(月) 16:21:58.14 ID:Uo1L8t18
例えば、classという名前の変数がある場合は、C++ではコンパイルできない。
void *型の変数にint *の値をキャストなしに代入しようとすると、C++ではコンパイルエラー。

 

8: 名無しの民 2018/11/13(火) 08:18:22.77 ID:0Ele5WZ8
>>5-6
ありがとうございます。
C99では未定義だがC++で定義・予約されている言葉なんかが引っ掛かってしまうんですね。

 

9: 名無しの民 2018/11/13(火) 18:41:26.33 ID:90McxFB4
extern “C” {}って書いてる?

 

10: 名無しの民 2018/11/13(火) 21:54:10.86 ID:RYrE2D9k
まずCから
Cも分かってないのにC++とかムリ

 

11: 名無しの民 2018/11/13(火) 22:08:24.41 ID:bZ0HXQ7X
C99頃から互換性も無いし、別言語だからそうでも無いけど、どっちかと言うとCのprintfに影響受けてる言語の方が多いね。
どっち先に覚えても良いけど、Cのprintfは押さえておいた方がいい。
(ただ、経験的にC++のオブジェクト指向を覚えるにはJavaかC#から入った方がいいので、挫折したらそっちを一旦勉強する事を勧める)

 

12: 名無しの民 2018/11/13(火) 22:32:00.82 ID:qjyppvvr
今の最新の規格ならだいぶ使いやすくなってるはず
とりあえず変数にはconstを付けれ

 

13: 名無しの民 2018/11/13(火) 23:50:04.90 ID:kE0CzrCg
C++とJavaのオブジェクト指向って、なにが違うのでしょうか?

 

14: 名無しの民 2018/11/13(火) 23:59:43.80 ID:700gS9mA
>>13
C++は、new を付けたらポインタ型になるが、Javaはnewを付けたら参照型になる。

 

15: 名無しの民 2018/11/14(水) 00:06:33.69 ID:bV3/fRvw
>>14
JavaよりC++のほうが難しいといわれるのは、ポインタがあるからっていう意味合いが大きいんでしょうか?

 

16: 名無しの民 2018/11/14(水) 00:19:07.08 ID:XVbpx9nj
>>15
C++のポインタは癌だ。どこにでもアクセスできてしまうし、メモリーリークが起きる恐れがある。安全ではない。
チェック付きの配列とスマートポインタを使えば、少しは安全になるが、完璧ではない。

 

21: 名無しの民 2018/11/14(水) 07:23:04.49 ID:XWwMTSMS
>>15
>>14じゃ無いけど、個人的にはfriendクラスとかJavaには無いクラス同士の関係があったりするが最初はそれがどう言う関係か理解出来なかった。
Javaでオブジェクト指向に慣れた後理解出来た。
C++はそう言う独特のオブジェクト指向があるので、まずそこまで複雑じゃ無いオブジェクト指向言語で慣れる方がC++独特のオブジェクト指向の理解に繋がる。

 

17: 名無しの民 2018/11/14(水) 00:36:22.61 ID:XVbpx9nj
まず、ポインタ変数の宣言が初心者殺し。
int* a, b;の場合、bはポインタではない。

 

関数ポインタはさらに文法が複雑すぎる。
関数ポインタ型の複雑さから逃れるには、typedefを使うとよい。

 

18: 名無しの民 2018/11/14(水) 01:24:53.28 ID:XVbpx9nj
ポインタ型をtypedefしまくった環境がWindowsのWin32 APIだ。
intを大文字でINTと書く。intのポインタをLPINTと書く。unsigned intをUINTと書き、そのポインタをLPUINTと書く。
基本的な関数型は全てtypedefで定義済み。

 

これなら、ややこしいアスタリスク記号(*)に戸惑う必要はない。

 

22: 名無しの民 2018/11/14(水) 11:35:25.78 ID:zVp4oIsl
>>18
無駄に覚えることを増やす馬鹿言語

 

wsとかswとか_sとかいっぱいつけやがってシッチャカメッチャカ

 

19: 名無しの民 2018/11/14(水) 01:35:38.43 ID:XVbpx9nj
型を大文字で書くと分かりやすいという意味で、Win32ではよく使うポインタ型を全て大文字で定義している。
char *にはLPSTRを、const char *にはLPCSTRを用意している。

 

20: 名無しの民 2018/11/14(水) 03:03:41.18 ID:aCPH/+gx
なんてことを昔の人は考えたが、当然スマートポインタのほうがより安全である

 

23: 名無しの民 2018/11/14(水) 11:36:41.07 ID:zVp4oIsl
あとtypedefしてる型を型チェックのときに同一とみなすのが意味ない
せっかく型を別けてるのに

 

24: 名無しの民 2018/11/14(水) 12:34:52.66 ID:OvTvaibz
整数を定義するときって以下の3つだとどれがメモリ消費量とか実行速度の面で一番効率いいですか?

 

#define XXX (1234)
enum{ XXX = 1234};
constexpr int XXX = 1234;

 

26: 名無しの民 2018/11/15(木) 12:16:37.45 ID:lNkjj0jr
>>24
今時のコンパイラならどれも同じになるだろうけど、#defineはただの置き換えだから、実質直接数字に置き換える。
お馬鹿なコンパイラなら、これが一番速い。
(メモリ上のXXXに格納された1234をレジスタに読むのじゃ無く、レジスタに直で1234と書き込むので、メモリアクセス分は速い)

 

25: 名無しの民 2018/11/15(木) 08:07:09.42 ID:HNIzCpqS
効率は実測が基本

 

27: 名無しの民 2018/11/15(木) 17:16:40.52 ID:XHYJGLe7
constexprが候補に上がる時点で最新のコンパイラだと思われる

 

28: 名無しの民 2018/11/15(木) 22:39:39.09 ID:jenSGLjX
AIの力でコンパイラの性能を上げるって可能ですか?

 

29: 名無しの民 2018/11/16(金) 09:32:03.61 ID:37LYr8ZY
a = xxx;
a = yyy;

 

これは、二重定義になりますか?

 

30: 名無しの民 2018/11/16(金) 09:41:00.05 ID:37LYr8ZY
解決方法として

 

a = (“xxx” && “yyy”);

を考えているのですが、これで良いでしょうか?

 

31: 名無しの民 2018/11/16(金) 11:34:07.59 ID:9iOixtPe
a[] = {xxx, yyy};

 

32: 名無しの民 2018/11/16(金) 11:52:01.81 ID:37LYr8ZY
>>31
ありがとうございます!

 

34: 名無しの民 2018/11/21(水) 04:04:25.43 ID:C09+uG2D
整数型とbool型を比較したり代入しようとしたときに警告かエラーを出す方法はありますか?
int i=5;
bool b=true;
i=b;
if(i==b)
if(i)
↑3行すべてでエラーなり警告なりを出してほしい
b=i;とif(b==i)は警告が出ます
環境はvs2017です

 

36: 名無しの民 2018/11/22(木) 06:04:18.72 ID:94o8kAxO
>>34
C++のboolのサイズはcharと同じだから
b=i: で警告になるのは整数型と論理型の変換というより単にサイズの小さい方に
代入しようとしたから警告になるてことだろうね

 

boolを使わずに Booleanクラスとかを自分で作れば型変換の許可/不許可も自在だけど
ま、やらんわな。そんな非効率なことは

 

37: 名無しの民 2018/11/24(土) 11:20:27.36 ID:pkYVxqhq
34です
遅くなりましたがありがとうございます
自作クラスを作ってまでエラー出したいものでもないので気にしないことにします

 

38: 名無しの民 2018/12/02(日) 21:29:56.53 ID:jrjT9DL9
MSがC++をCより勧める利点ってなんでしょう。
.NET関連で商売する為にC#などの利用を推奨するのは理解できるのですが
C++に拘りC99にすら対応しないのは何かよっぽどの理由があるのかなと思ってしまいます。

 

39: 名無しの民 2018/12/03(月) 21:46:10.27 ID:ZMLOrV5M
.net以前はMFCで商売してたからね。
その遺産を保守するのにC++が必要。

 

今でもそう言う会社相手に商売してる。
今はまだマシだけど、開発環境独占だと標準規格無視してた。
対応しなくても売れるのに、対応する必要は無いわな。

 

41: 名無しの民 2018/12/05(水) 04:20:50.45 ID:yf36y6mU
enum EN { yama,kawa}
をアクセスする規則がわかりません。 EN.yama の時もあれば 単にyamaの
時もあります。規則はどうなってるんでしょうか?

 

45: 名無しの民 2019/01/11(金) 18:31:10.60 ID:TUR+WyZ1
win16からwin32への移行では役に立ったのかもしれない。

 

46: 名無しの民 2019/01/22(火) 13:59:06.16 ID:owIFG1wt
ゼロが流行っているのか?

 

51: 名無しの民 2019/08/31(土) 21:44:16.76 ID:r57d4Puh
C++って便利になってもゴチャゴチャしてて汚い言語だとどっかで聞きました

 

52: 名無しの民 2019/09/01(日) 01:17:32.77 ID:6J4Ocwbf
ゴチャゴチャだと?
無理して拡張された機能を使わなければいいだけの話じゃないか
C言語でオブジェクト指向プログラミングをしようとするとどれだけ危険で汚くなるか分かってるんだろ?
C++は表面的にだけどそれをきれいにまとめた点だけでも評価されていいんじゃないか?

 

57: 名無しの民 2019/09/22(日) 18:46:16.43 ID:tiYbs1p9
>>52
STLに関しては、コンテナ以外の部分を使わなければ、かなりスパゲッティー感が
なくなる。C++98以降、STLの実装にしか使わないような template の機能強化
に邁進してしまったようだ。しかし、C++ reference などで STL がふんだんに
使って説明されてしまってるので若い人の間で STL が C++ の標準だと
思われてしまい、そこが難しいので C++ が嫌われる結果となっている。
本来はライブラリはプログラミングが簡単になることを目的にしているはずなのに、
STLはその逆を言ってしまっている。
問題なのは、STLを使いまくったC++コードがネット上に増えてしまっていること。

 

53: 名無しの民 2019/09/01(日) 01:34:32.37 ID:sYwYgS29
つまりテンプレートを使うなということですね判ります

 

54: 名無しの民 2019/09/21(土) 17:36:37.24 ID:BnEC5IrG
c++は元はクラス形オブジェクトシステムを高速に動作させる為に始めたけど
今は単に高速にする事を目的に作っている様に見える
その為に一度に出来る様な記述を追加していってて有る意味便利なんだけど
機能が増えすぎて正確に把握するのが大変
その影響で何処か間違うとその間違った部分とは違う部分が違ってて
それを理解するのが大変
あちこちが絡みすぎてて言語自体がスパゲッティになってる印象
大量の事項を正確に覚えてそれられを正しく組み合わせないといけないから大変
超初心者にはかなりきつい
プログラミング初心者がやる様な物ではない
ある程度他のプログラミング言語をやって出来るようになってからの方が多分良い

 

55: 名無しの民 2019/09/21(土) 17:40:00.07 ID:icgczTg/
>その影響で何処か間違うとその間違った部分とは違う部分が違ってて
>それを理解するのが大変

 

「何処か間違うとその間違った部分とは違う部分が違っててそれを理解するのが大変」
はその通りだが

「その影響で」
は関係無い
大変なのは今に始まったことじゃない
高機能ωになる前からずっとそう

 

58: 名無しの民 2019/09/22(日) 19:24:43.32 ID:vTpi5vA1
奥が深いからね
ショウガナイね

 

59: 名無しの民 2019/09/22(日) 19:40:18.23 ID:+tHa6qta
STLのコンテナ以外の部分とか自作template使わないとプロ感出ないからね
仕方ないね

 

60: 名無しの民 2019/09/23(月) 09:41:06.71 ID:9Vk3Qf6P
言語仕様を一通り学んだ後でライブラリの詳細な使い方を覚えていけるのが理想。
ところが、cppreference では、言語仕様を本文だけでは説明し切れておらず、
サンプルコードを見てやっと理解できるようになっているが、そこで
非常に難解なSTLの使い方をしてしまっている。それでは
STLの非常に詳細な仕様を知らないとSTLの基礎となっている言語仕様すら
理解できないことになり、ある種の「トートロジー」のような現象が起きてしまう。
前段階の理解を元に三段論法的に論理や理解を進めていくという説明の仕方になっていないのだ。
そのやり方が C++ が難解であるというイメージを植えつけてしまっている。
cppreference の執筆者やC++委員会の上の方の人の中に、STLをC++の言語
それ自体だと思っている人がいるように思えてならない。
確かにPythonやRubyでは、似たような機能を持つものが、言語そのものの一部
である位置づけになっている。しかし、その理解はとても容易である。
だから、言語仕様を説明するサンプルコードがその理解を前提にしていたとしても、
理解の妨げにはならない。ところが、C++ではその事情は一変するのだ。

 

62: 名無しの民 2019/09/23(月) 12:36:29.52 ID:9Vk3Qf6P
>>60
正確には、トートロジー というより、循環論法に近い。

 

63: 名無しの民 2019/09/23(月) 13:25:24.38 ID:IaDL9t/N
>>60
たとえば cppreference のどの記事のことを言ってるんですか?
1つか2つでもいいんで、具体例がほしいです。

 

64: 名無しの民 2019/09/23(月) 14:28:50.02 ID:9Vk3Qf6P
>>63
もしかしたら >>60 の説明は「ずれて」いたかもしれないけど、例えば、言語仕様の
サンプルコードに高頻度に vector が出てくるので、それ自体がどうやって実装されているかを
調べることも重要になってくる。すると、initailizer-list なるものが重要であることがわかり、
vector の実装でそれがどう関係しているかも知りたくなる。それを知る前にまずは、vector template
の細かい仕様を調べたくなり、以下を見るとする:
https://en.cppreference.com/w/cpp/container/vector

 

↑は冒頭部分からしてこうなってる:
template<
 class T,
 class Allocator = std::allocator<T>
> class vector;
(1)
namespace pmr {
 template <class T>
 using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>;
}
(2) (since C++17)
1) std::vector is a sequence container that encapsulates dynamic size arrays.
2) std::pmr::vector is an alias template that uses a polymorphic allocator

これは、初心者には難しすぎるし、実装を調べたいような上級者には情報が不足しており、
「帯に短し襷に長し」状態である(ちゃんとした説明になっていないのだ)。
上の部分を見た場合、最初に、allocator とはなんなのか、ということが疑問になる。
そして、allocator を調べなくてはならなくなる・・・・。

まず、vector とは何なのかが大まかに知りたかった人にすら、これでは難しい。
例えば、Ruby なら、[a,b,c] は、リストといって、集合です、と説明して
わずかなサンプルでもその全体像が分かった気がしてくる。
それとは全然違うことになってしまっている。

 

65: 名無しの民 2019/09/23(月) 14:39:03.51 ID:9Vk3Qf6P
>>64
誤:initailizer-list
正:initializer-list

 

vector の仕様を調べようとすると、(1),(2)の2つの定義が出ており、(2)では
なぜか、namespace pmr が出てきて、さらに、using vector = ・・・、で
vector という名前が alias で定義されているらしい。基礎の基礎を知りたくて
vectorを調べたのに、namespace と using alias が出てくる。そして、pmr
という namespace がいったい何なのかということを知る必要が出てくる。

まず説明に言葉が足りてない気がする。英語は曖昧さを含み易い言語らしく、
英語に強い人に聞いても「文脈でどっちとも取れるので正確な意味は分からない」
と言われる。日本語に比して言葉の意味が薄くて、サンプルコードが重要となる。
IntelのCPU命令のマニュアルだと、擬似コードで説明されている事があり、
その場合にはほぼ正確に言っていることが分かるが。cppreferenceはそれもない。
ほぼ、サンプルコードだけが頼りになっているが、そのサンプルも分かりにくい。
サンプルに対する英語の説明が少なすぎるから。

 

66: 名無しの民 2019/09/23(月) 15:02:06.71 ID:9Vk3Qf6P
>>64
時々、「コードこそがドキュメント」などという人がいて、それに従って
cppreferenceが書かれてしまっている可能性がある。しかし、vectorの
「仕様」とは、vectorが如何に実装されているかではなく、如何に使うか
の説明から入るべきなのに、>>64は、実装をモロに見せてしまってるから
難しくなっている。(1)のtemplate文だけでは、templateの仕様がまだ理解できてない
段階では、vectorの仕様を知ることが出来ないことになる。そう書くよりも、
いきなり、

 

std::vector<int> v = {7, 5, 16, 8};  // (100)

で、4つの整数型の要素を持つ配列を確保します。
メモリ上で要素は、隣り合わせに並びます。
配列の長さは動的に変更することが出来ます。

と書いたほうが良いし、完全な referece を書きたい場合でも、>>64 の(1)のように
書くべきではなくて、例えば、(100)を一般化して

[vector 型オブジェクトの作成方法]
std::vector<int> オブジェクト名 = 初期化子;  // (101)
 初期化子 := {初期値リスト}

などと書かないいけない。

>>64 の (1)は、vector自体の「実装方法」を書いているだけで
vectorの「仕様書」にはなっていない。

 

68: 名無しの民 2019/09/23(月) 15:21:18.30 ID:9Vk3Qf6P
>>66
集合や、データベース系のソフトウェアでは、言葉は忘れたが、
初期化、追加、削除、参照、検索、個数の取得
などが良く使われる(ほぼ必須の)基本機能だとされるから、

 

[vector 型オブジェクトの作成方法]
std::vector<要素の型> オブジェクト名 = 初期化子;  // (200)
std::vector<要素の型> オブジェクト名 初期化子;  // (201)
 初期化子 := {初期値リスト}

[vector 型オブジェクトへの末尾への要素の追加]
オブジェクト名.push_back(要素);         // (210) 要素をコピーして追加したい場合
オブジェクト名.push_back(std::move(要素));   // (211) 要素を移動して追加したい場合

[vector 型オブジェクトの idx 番目の要素の参照]
オブジェクト名[idx]    // (220) : idx は先頭が 0 から始まる。
・・・

などと書いていけばよい(自分は細かい仕様が分かってないのでこれ以上詳しくは
書けないが、reference manual を書く人なら書けるはず)。
初心者が期待する reference manual とは上記のようなもので、
>> 64 のようなものではない。何度も言うが、>>64
実装と仕様が混合されてしまったもので、どっちつかずの状態になっている。

 

61: 名無しの民 2019/09/23(月) 11:55:25.99 ID:3qdqqJ07
codecvtですね判ります

 

67: 名無しの民 2019/09/23(月) 15:16:09.23 ID:3qdqqJ07
なるほど
それならトートロジーとか循環論法と言うよりも
もっと適切な言葉があるはず

 

69: 名無しの民 2019/09/23(月) 15:26:14.73 ID:3qdqqJ07
ソースから自動生成してるなら仕方ない面もある

 

70: 名無しの民 2019/09/23(月) 23:08:32.79 ID:MNSCG3IB
実装で仕様が隠蔽されている

 

71: 名無しの民 2019/09/23(月) 23:52:06.90 ID:U2/CMzYE
大きい・小さいとか、言葉は、about で抽象的だから、
こんな厳密な事を決めるのには、向いていない

 

図解・サンプルの方が、圧倒的に理解しやすい。
だから、下の3冊などは、神の書と呼ばれる

サンプルを示すことで、OK/NG というのがハッキリわかるから!

C++11/14 コア言語、江添 亮、2015
組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド、MISRA‐C研究会、2006
Linux プログラミング・インタフェース、Michael Kerrisk、2012

理解できないような事を書いている、香具師が悪い。
そういうのを追っかけても、時間の無駄

プログラミング・フレームワーク・構造がわかるためには、Ruby でもやった方が余程よい。
C/C++ などポインタのある言語は、プログラミングを学ぶのに適していないし、
バグで時間を浪費するから、結局学べないw

 

72: 名無しの民 2019/09/30(月) 10:42:32.26 ID:6yDcPDBq
なるほどね
初心者にとっては
一度に多くのことを覚えないといけないのは負担が多い
生配列を使うのは良くないから最初からvectorを教えるのは
有る意味正しいけど
理解するには難易度が上がってしまっている

 

オブジェクト指向プログラミングでも同じ様な感じで
例の
動物クラスから継承して犬猫クラスを作ってワンニャン
とかの説明とかが良く有るけど
機能の説明としてはそれでいいんだけど
実際にそういう風には作らない(別にそういう風にやりたきゃやってもいいけど)
実際上は別な構造として作ったりするんだけど
その別なやり方をどうするのか?という説明が殆ど無いので
オブジェクト指向は糞
みたいな話になってくる
唯一の例題として有るのが
デザインパターン
だと自分は思っているが
あれを意味が無い
とか言っている人が結構居て
そのせいで軽視されているのが残念というか問題だと思ってる
初心者が手がかりにするのは難しい面も有るけど他に良さそうな例題が余り無い

適切な教科書を作る
というのは結構高度で大変で
作れる人が少ない
その割には作った人には余り金にならなかったりして
作ってくれる人が余り居ない印象

 

73: 名無しの民 2019/09/30(月) 12:08:38.76 ID:vkIGDak2
gcc も g++ も VC も肥大化し過ぎた
digital mars c とか Borland C 5.5 かそれよりもっと前
tiny c compiler でもいい
初心者用にはもっとシンプルな C で充分

 

74: 名無しの民 2019/10/06(日) 17:06:30.65 ID:42LxT2AQ
quick c

 

75: 名無しの民 2020/03/26(木) 16:08:19.66 ID:71CdUQnj
>まず説明に言葉が足りてない気がする。英語は曖昧さを含み易い言語らしく、

 

英語は抽象意味言語だから指している範囲がザックリしてて
短い文章とかだと何を言っているのか解らない
その分覚えておかないといけない分量が少なくて良い
英語から日本語に自動翻訳を掛けても上手く翻訳されていない時はその文章が何の分野で有るか解らないから間違っている様に見えると感じる

日本語は一つの意味を指している事が多いけど覚えておかないといけない分量が多いから大変だけど
その分広い範囲の意味を指していないのでちゃんと使うと意味が一点を指して誤解し難い

けどプログラムを書く時は
javaだととりあえず.を書いておけば良いから迷わないけど
c++だと.だったり->だったり::だったりするから迷う事がある
そんなに致命的な問題では無いけど

 

77: 名無しの民 2020/05/06(水) 18:31:54.91 ID:K0jT0mUL
入門ロベールC++の188ページに

 

const char* MONTH_NAME[]={“睦月,”如月,”弥生”……  
というのがあるのですが、なぜchar*型の前にconstをつけると文字列リテラルをたくさん代入出来るのでしょうか?
const定数を外すと同じことが出来ないのがよく分からないです。ポインタが理解できてないのでしょうか。

 

80: 名無しの民 2020/05/06(水) 19:06:59.66 ID:8YawtAIF
>>77
文字列リテラルの指す文字列は書きかえてはいけない。
char* の指す先の文字列は書きかえできる。
const char* の指す先の文字列は書きかえできない。

 

82: 名無しの民 2020/05/06(水) 19:09:49.04 ID:8YawtAIF
>>77
あーわかった。あんたがエラーメッセージを読んで理解しようとしないから分からないんだよ。

 

93: 名無しの民 2020/05/07(木) 12:23:12.56 ID:iKRewGMt
>>77
const 付けたくないなら
char MONTH_NAME[][5]={“睦月,”如月,”弥生”……

 

96: 名無しの民 2020/05/08(金) 06:37:37.35 ID:Br/73fC2
ロベールさんで紹介してる環境に限定されると語れる立場じゃないんだが…。

 

>>93
漢字1文字を2byteと仮定するのは危険じゃないかしら。
このごろUTF-8でベタに文字列書くことが多いんでちょい気になる。
と言ってu8プレフィックス付けるほどお行儀良くもない中途半端な人。

>>94
char *s = “hoge”; で警告出ないとは
ストラウストラップ先生がガッカリしそうなコンパイラね。

 

78: 名無しの民 2020/05/06(水) 18:38:37.65 ID:wd9+jhuU
それの場合MONTH_NAMEの型は
「書き換えられないchar」「へのポインタ」「の配列」
であることがわかれば後はわかるっしょ

 

79: 名無しの民 2020/05/06(水) 18:46:19.97 ID:K0jT0mUL
>>78
すいません、分からないです・・・
何が分かってないからこうなってるのか。も分かってないからまた読み直して同じページに戻っても理解できないです・・

 

81: 名無しの民 2020/05/06(水) 19:07:03.19 ID:K0jT0mUL
何故文字配列なのに文字列を沢山入れられるのか…

 

83: 名無しの民 2020/05/06(水) 20:16:45.31 ID:K0jT0mUL
分かりません。
ポインタを直接文字列の値で初期化してるのもよくわからないです。

 

84: 名無しの民 2020/05/06(水) 20:38:11.69 ID:5oVnKxXT
char *s = “abc”; がダメな理由と
int a[] = { 1, 2, 3 }; がOKな理由を考えろ

 

87: 名無しの民 2020/05/06(水) 20:53:56.70 ID:K0jT0mUL
>>84
char* sはchar型の変数の参照が入ってないから駄目なのでは?
下はただの配列変数だからできてるのでは?

 

85: 名無しの民 2020/05/06(水) 20:47:05.11 ID:Fjn1hDTG
const char* MONTH_NAME[]=

 

型 変数名[]

各要素の型は、const char*
[ ] は配列

最近、ロベールは本屋で売ってない

 

88: 名無しの民 2020/05/06(水) 21:05:23.65 ID:K0jT0mUL
>>85
const char*という新しい型があるのですか?
constとは定数を宣言するだけのものじゃないのでしょうか

 

86: 名無しの民 2020/05/06(水) 20:51:54.79 ID:Fjn1hDTG
Ruby なら、変数名はラベルだから、変数に再代入できるけど

 

a = “a”
a = “abc”

 

89: 名無しの民 2020/05/06(水) 21:49:00.63 ID:K0jT0mUL
char* str[]={“aaa”,”bbb”,”ccc”}はできないのに
const char* str[]={“aaa”,”bbb”,”ccc”}はエラーにならないのも意味わからないです
const chr*のエンティティ云々も意味不明なのですがロベール188pまでにその説明は載ってるのでしょうか

 

91: 名無しの民 2020/05/06(水) 22:11:15.73 ID:8YawtAIF
>>89
「できない」理由はエラーメッセージに書いてあるだろ。読めよ。

 

90: 名無しの民 2020/05/06(水) 21:54:43.49 ID:5oVnKxXT
じゃあ const char *s = “abc”; がわからないのか
これはどこかにある “abc” という配列へのポインタでsを初期化しなさいっていう意味で、
char *s = “abc”; がダメなのは “abc” が変更不可だから

 

あとは const char *s = “abc”; と const char *MONTH_NAME[] = { “睦月”, … }; の関係が int i = 0; と int a[] = { 0, … }; の関係と同じであることを考えればわかるはず

 

92: 名無しの民 2020/05/06(水) 22:58:31.48 ID:K0jT0mUL
>>90
文字列って定数なんですか?
何となく分かってきた気がします!細かく教えていただきありがとうございます

 

94: 名無しの民 2020/05/07(木) 17:22:45.52 ID:8jv+kISL
char r[] = “hoge”;
char *s = “hoge”;
const char *t = “hoge”;
char *MONTH_NAME_A[]={“睦月”,”如月”,”弥生”};
char MONTH_NAME_B[][7]={“睦月”,”如月”,”弥生”};
どれもエラーも警告も出んかった

 

95: 名無しの民 2020/05/07(木) 18:27:09.29 ID:wkYaXeHy
char *t = “hoge”;
これがエラーにならないのは言語上の欠陥

 

97: 名無しの民 2020/05/08(金) 09:24:37.89 ID:0HhOrENw
>>95
C++11 以降の言語仕様では許していない。
それより前の仕様では許していたという歴史的経緯があるので
(エラーではなく) 警告にとどめている処理系がまあまあ有るという事情。

 

98: 名無しの民 2020/05/08(金) 09:31:38.60 ID:oIDbptWL
C++
https://ideone.com/lWQYBs
C++14
https://ideone.com/2CLzMB

 

どっちもスルーされる

 

99: 名無しの民 2020/05/08(金) 21:53:35.81 ID:+i26a8kQ
ロベールの入門書に /*構造体変数student*/
int length = sizeof stundent /sizeof *student
というのがあるのですが何故これで配列の要素数が出るのでしょうか?
sizeof student / sizeof student[0]だと配列の要素数が出る理屈は何となく分かるのですが
配列とポインタは別のものですよね?

 

105: 名無しの民 2020/05/09(土) 10:52:17.88 ID:MmeKQuXy
>>99
「暗黙の型変換」によって配列がポインタに型変換されるルールがある。
スムーズにポインタとして使えてしまうから混同してわけわからんようになる初心者が多いんだけど、
あくまでも別物であるという理解が出来ているなら入門者としてはかなり優秀だと思う。

 

ほとんどの場合に配列はポインタに暗黙に型変換されるんだけど、
例外としては
 ① sizeof を適用するとき
 ② 単項の & を適用するとき
 ③ 参照で受け取るとき
があって、これらの状況では型変換されずに解釈される。

—-

余談だけど暗黙の型変換とは別に仮引数の調整というのもあって、
関数の仮引数として配列を書いた場合も配列はポインタに調整される。
たとえば
void foo(int a[10]) {}
という定義を書いたら
void foo(int* a) {}
と全く同じように解釈される。

 

100: 名無しの民 2020/05/08(金) 22:21:29.33 ID:/+tKw0XQ
student[0] と *student は同じ

 

101: 名無しの民 2020/05/08(金) 23:07:29.79 ID:+i26a8kQ
何で同じなのでしょうか?これで動くからこういうもの。という理解で大丈夫なんでしょうか

 

103: 名無しの民 2020/05/09(土) 06:15:34.68 ID:LKKpAq9a
とりあえず stundent は誤りで正しくは student だとして

 

多くの場合、配列名は「配列の先頭要素を指すポインタ」と解釈される、から。
つまり配列studentについて student == &student[0] が成り立つ。
*演算子を作用させて *student == *&student[0] == student[0]
よって sizeof *student == sizeof student[0]

ここで注意すべき点は「配列名がsizeof演算子のオペランドになった場合は
配列の先頭要素を指すポインタとは解釈されない」ってこと。
sizeof 配列名 == 配列全体が占有するメモリ容量

なぜそうなっているか、という理由は「そう決めると便利だから」かな。
Cの頃からそういう感じでプログラム書いてたから、という歴史的経緯もある。

>>102 初心者をからかっちゃアカンよ。信じちゃうかも知れん。

 

106: 名無しの民 2020/05/11(月) 03:00:46.06 ID:II69MMpE
すいませんロベール持ってる人にお聞きしたいのですが
305ページの
for (int i = 0, size = a.Size(); i < size; ++i) という文があるのですが
このsizeというローカル変数は何処に定義されてるんでしょうか?

 

107: 名無しの民 2020/05/11(月) 05:46:42.66 ID:k4wInV7m
>>106
“ロベール本”を持ってないので答えられない立場かも知れんけど…。
この size は「ここ」で定義されているんだと思うよ。

 

for の初期化式 int i = 0, size = a.Size(); で、
「int の i」と「int の size」という2つの変数を定義している。

 

108: 名無しの民 2020/05/11(月) 07:45:03.87 ID:II69MMpE
>>107
forの中で2つ宣言できるんですね!そんな事も知りませんでした。
ありがとうございます。

 

109: 名無しの民 2020/05/11(月) 09:53:48.32 ID:MhpqGE2N
型が違うときは?
for (long i = 0, int size = a.Size(); i < size; ++i)

 

110: 名無しの民 2020/05/11(月) 19:53:43.37 ID:8B6Lebzi
C++17なら
for (auto [i, size] = tuple(0L, a.Size()); i < size; ++i)

引用元

https://mevius.5ch.net/test/read.cgi/tech/1542002113/




コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です