0からの、超初心者C++相談室
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
2018/11/12(月) 14:55:13.35ID:Tf74ZWQr 何にも知らない0からの出発、超初心者のためのC++相談室
61デフォルトの名無しさん
2019/09/23(月) 11:55:25.99ID:3qdqqJ07 codecvtですね判ります
2019/09/23(月) 12:36:29.52ID:9Vk3Qf6P
>>60
正確には、トートロジー というより、循環論法に近い。
正確には、トートロジー というより、循環論法に近い。
2019/09/23(月) 13:25:24.38ID:IaDL9t/N
2019/09/23(月) 14:28:50.02ID: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] は、リストといって、集合です、と説明して
わずかなサンプルでもその全体像が分かった気がしてくる。
それとは全然違うことになってしまっている。
もしかしたら >>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] は、リストといって、集合です、と説明して
わずかなサンプルでもその全体像が分かった気がしてくる。
それとは全然違うことになってしまっている。
2019/09/23(月) 14:39:03.51ID: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はそれもない。
ほぼ、サンプルコードだけが頼りになっているが、そのサンプルも分かりにくい。
サンプルに対する英語の説明が少なすぎるから。
誤:initailizer-list
正:initializer-list
vector の仕様を調べようとすると、(1),(2)の2つの定義が出ており、(2)では
なぜか、namespace pmr が出てきて、さらに、using vector = ・・・、で
vector という名前が alias で定義されているらしい。基礎の基礎を知りたくて
vectorを調べたのに、namespace と using alias が出てくる。そして、pmr
という namespace がいったい何なのかということを知る必要が出てくる。
まず説明に言葉が足りてない気がする。英語は曖昧さを含み易い言語らしく、
英語に強い人に聞いても「文脈でどっちとも取れるので正確な意味は分からない」
と言われる。日本語に比して言葉の意味が薄くて、サンプルコードが重要となる。
IntelのCPU命令のマニュアルだと、擬似コードで説明されている事があり、
その場合にはほぼ正確に言っていることが分かるが。cppreferenceはそれもない。
ほぼ、サンプルコードだけが頼りになっているが、そのサンプルも分かりにくい。
サンプルに対する英語の説明が少なすぎるから。
2019/09/23(月) 15:02:06.71ID: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の「仕様書」にはなっていない。
時々、「コードこそがドキュメント」などという人がいて、それに従って
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の「仕様書」にはなっていない。
67デフォルトの名無しさん
2019/09/23(月) 15:16:09.23ID:3qdqqJ07 なるほど
それならトートロジーとか循環論法と言うよりも
もっと適切な言葉があるはず
それならトートロジーとか循環論法と言うよりも
もっと適切な言葉があるはず
2019/09/23(月) 15:21:18.30ID: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 は
実装と仕様が混合されてしまったもので、どっちつかずの状態になっている。
集合や、データベース系のソフトウェアでは、言葉は忘れたが、
初期化、追加、削除、参照、検索、個数の取得
などが良く使われる(ほぼ必須の)基本機能だとされるから、
[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 は
実装と仕様が混合されてしまったもので、どっちつかずの状態になっている。
69デフォルトの名無しさん
2019/09/23(月) 15:26:14.73ID:3qdqqJ07 ソースから自動生成してるなら仕方ない面もある
70デフォルトの名無しさん
2019/09/23(月) 23:08:32.79ID:MNSCG3IB 実装で仕様が隠蔽されている
2019/09/23(月) 23:52:06.90ID: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
こんな厳密な事を決めるのには、向いていない
図解・サンプルの方が、圧倒的に理解しやすい。
だから、下の3冊などは、神の書と呼ばれる
サンプルを示すことで、OK/NG というのがハッキリわかるから!
C++11/14 コア言語、江添 亮、2015
組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド、MISRA‐C研究会、2006
Linux プログラミング・インタフェース、Michael Kerrisk、2012
理解できないような事を書いている、香具師が悪い。
そういうのを追っかけても、時間の無駄
プログラミング・フレームワーク・構造がわかるためには、Ruby でもやった方が余程よい。
C/C++ などポインタのある言語は、プログラミングを学ぶのに適していないし、
バグで時間を浪費するから、結局学べないw
2019/09/30(月) 10:42:32.26ID:6yDcPDBq
なるほどね
初心者にとっては
一度に多くのことを覚えないといけないのは負担が多い
生配列を使うのは良くないから最初からvectorを教えるのは
有る意味正しいけど
理解するには難易度が上がってしまっている
オブジェクト指向プログラミングでも同じ様な感じで
例の
動物クラスから継承して犬猫クラスを作ってワンニャン
とかの説明とかが良く有るけど
機能の説明としてはそれでいいんだけど
実際にそういう風には作らない(別にそういう風にやりたきゃやってもいいけど)
実際上は別な構造として作ったりするんだけど
その別なやり方をどうするのか?という説明が殆ど無いので
オブジェクト指向は糞
みたいな話になってくる
唯一の例題として有るのが
デザインパターン
だと自分は思っているが
あれを意味が無い
とか言っている人が結構居て
そのせいで軽視されているのが残念というか問題だと思ってる
初心者が手がかりにするのは難しい面も有るけど他に良さそうな例題が余り無い
適切な教科書を作る
というのは結構高度で大変で
作れる人が少ない
その割には作った人には余り金にならなかったりして
作ってくれる人が余り居ない印象
初心者にとっては
一度に多くのことを覚えないといけないのは負担が多い
生配列を使うのは良くないから最初からvectorを教えるのは
有る意味正しいけど
理解するには難易度が上がってしまっている
オブジェクト指向プログラミングでも同じ様な感じで
例の
動物クラスから継承して犬猫クラスを作ってワンニャン
とかの説明とかが良く有るけど
機能の説明としてはそれでいいんだけど
実際にそういう風には作らない(別にそういう風にやりたきゃやってもいいけど)
実際上は別な構造として作ったりするんだけど
その別なやり方をどうするのか?という説明が殆ど無いので
オブジェクト指向は糞
みたいな話になってくる
唯一の例題として有るのが
デザインパターン
だと自分は思っているが
あれを意味が無い
とか言っている人が結構居て
そのせいで軽視されているのが残念というか問題だと思ってる
初心者が手がかりにするのは難しい面も有るけど他に良さそうな例題が余り無い
適切な教科書を作る
というのは結構高度で大変で
作れる人が少ない
その割には作った人には余り金にならなかったりして
作ってくれる人が余り居ない印象
73デフォルトの名無しさん
2019/09/30(月) 12:08:38.76ID:vkIGDak2 gcc も g++ も VC も肥大化し過ぎた
digital mars c とか Borland C 5.5 かそれよりもっと前
tiny c compiler でもいい
初心者用にはもっとシンプルな C で充分
digital mars c とか Borland C 5.5 かそれよりもっと前
tiny c compiler でもいい
初心者用にはもっとシンプルな C で充分
2019/10/06(日) 17:06:30.65ID:42LxT2AQ
quick c
2020/03/26(木) 16:08:19.66ID:71CdUQnj
>まず説明に言葉が足りてない気がする。英語は曖昧さを含み易い言語らしく、
英語は抽象意味言語だから指している範囲がザックリしてて
短い文章とかだと何を言っているのか解らない
その分覚えておかないといけない分量が少なくて良い
英語から日本語に自動翻訳を掛けても上手く翻訳されていない時はその文章が何の分野で有るか解らないから間違っている様に見えると感じる
日本語は一つの意味を指している事が多いけど覚えておかないといけない分量が多いから大変だけど
その分広い範囲の意味を指していないのでちゃんと使うと意味が一点を指して誤解し難い
けどプログラムを書く時は
javaだととりあえず.を書いておけば良いから迷わないけど
c++だと.だったり->だったり::だったりするから迷う事がある
そんなに致命的な問題では無いけど
英語は抽象意味言語だから指している範囲がザックリしてて
短い文章とかだと何を言っているのか解らない
その分覚えておかないといけない分量が少なくて良い
英語から日本語に自動翻訳を掛けても上手く翻訳されていない時はその文章が何の分野で有るか解らないから間違っている様に見えると感じる
日本語は一つの意味を指している事が多いけど覚えておかないといけない分量が多いから大変だけど
その分広い範囲の意味を指していないのでちゃんと使うと意味が一点を指して誤解し難い
けどプログラムを書く時は
javaだととりあえず.を書いておけば良いから迷わないけど
c++だと.だったり->だったり::だったりするから迷う事がある
そんなに致命的な問題では無いけど
76デフォルトの名無しさん
2020/03/27(金) 14:39:56.26ID:9RtDMjhb ::あんまり使わないな
2020/05/06(水) 18:31:54.91ID:K0jT0mUL
入門ロベールC++の188ページに
const char* MONTH_NAME[]={"睦月,"如月,"弥生"......
というのがあるのですが、なぜchar*型の前にconstをつけると文字列リテラルをたくさん代入出来るのでしょうか?
const定数を外すと同じことが出来ないのがよく分からないです。ポインタが理解できてないのでしょうか。
const char* MONTH_NAME[]={"睦月,"如月,"弥生"......
というのがあるのですが、なぜchar*型の前にconstをつけると文字列リテラルをたくさん代入出来るのでしょうか?
const定数を外すと同じことが出来ないのがよく分からないです。ポインタが理解できてないのでしょうか。
2020/05/06(水) 18:38:37.65ID:wd9+jhuU
それの場合MONTH_NAMEの型は
「書き換えられないchar」「へのポインタ」「の配列」
であることがわかれば後はわかるっしょ
「書き換えられないchar」「へのポインタ」「の配列」
であることがわかれば後はわかるっしょ
2020/05/06(水) 18:46:19.97ID:K0jT0mUL
2020/05/06(水) 19:06:59.66ID:8YawtAIF
2020/05/06(水) 19:07:03.19ID:K0jT0mUL
何故文字配列なのに文字列を沢山入れられるのか…
2020/05/06(水) 19:09:49.04ID:8YawtAIF
>>77
あーわかった。あんたがエラーメッセージを読んで理解しようとしないから分からないんだよ。
あーわかった。あんたがエラーメッセージを読んで理解しようとしないから分からないんだよ。
2020/05/06(水) 20:16:45.31ID:K0jT0mUL
分かりません。
ポインタを直接文字列の値で初期化してるのもよくわからないです。
ポインタを直接文字列の値で初期化してるのもよくわからないです。
2020/05/06(水) 20:38:11.69ID:5oVnKxXT
char *s = "abc"; がダメな理由と
int a[] = { 1, 2, 3 }; がOKな理由を考えろ
int a[] = { 1, 2, 3 }; がOKな理由を考えろ
2020/05/06(水) 20:47:05.11ID:Fjn1hDTG
const char* MONTH_NAME[]=
型 変数名[]
各要素の型は、const char*
[ ] は配列
最近、ロベールは本屋で売ってない
型 変数名[]
各要素の型は、const char*
[ ] は配列
最近、ロベールは本屋で売ってない
2020/05/06(水) 20:51:54.79ID:Fjn1hDTG
Ruby なら、変数名はラベルだから、変数に再代入できるけど
a = "a"
a = "abc"
a = "a"
a = "abc"
2020/05/06(水) 20:53:56.70ID:K0jT0mUL
2020/05/06(水) 21:05:23.65ID:K0jT0mUL
2020/05/06(水) 21:49:00.63ID:K0jT0mUL
char* str[]={"aaa","bbb","ccc"}はできないのに
const char* str[]={"aaa","bbb","ccc"}はエラーにならないのも意味わからないです
const chr*のエンティティ云々も意味不明なのですがロベール188pまでにその説明は載ってるのでしょうか
const char* str[]={"aaa","bbb","ccc"}はエラーにならないのも意味わからないです
const chr*のエンティティ云々も意味不明なのですがロベール188pまでにその説明は載ってるのでしょうか
2020/05/06(水) 21:54:43.49ID: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, ... }; の関係と同じであることを考えればわかるはず
これはどこかにある "abc" という配列へのポインタでsを初期化しなさいっていう意味で、
char *s = "abc"; がダメなのは "abc" が変更不可だから
あとは const char *s = "abc"; と const char *MONTH_NAME[] = { "睦月", ... }; の関係が int i = 0; と int a[] = { 0, ... }; の関係と同じであることを考えればわかるはず
2020/05/06(水) 22:11:15.73ID:8YawtAIF
>>89
「できない」理由はエラーメッセージに書いてあるだろ。読めよ。
「できない」理由はエラーメッセージに書いてあるだろ。読めよ。
2020/05/06(水) 22:58:31.48ID:K0jT0mUL
93デフォルトの名無しさん
2020/05/07(木) 12:23:12.56ID:iKRewGMt94デフォルトの名無しさん
2020/05/07(木) 17:22:45.52ID:8jv+kISL char r[] = "hoge";
char *s = "hoge";
const char *t = "hoge";
char *MONTH_NAME_A[]={"睦月","如月","弥生"};
char MONTH_NAME_B[][7]={"睦月","如月","弥生"};
どれもエラーも警告も出んかった
char *s = "hoge";
const char *t = "hoge";
char *MONTH_NAME_A[]={"睦月","如月","弥生"};
char MONTH_NAME_B[][7]={"睦月","如月","弥生"};
どれもエラーも警告も出んかった
2020/05/07(木) 18:27:09.29ID:wkYaXeHy
char *t = "hoge";
これがエラーにならないのは言語上の欠陥
これがエラーにならないのは言語上の欠陥
2020/05/08(金) 06:37:37.35ID:Br/73fC2
2020/05/08(金) 09:24:37.89ID:0HhOrENw
2020/05/08(金) 09:31:38.60ID:oIDbptWL
2020/05/08(金) 21:53:35.81ID:+i26a8kQ
ロベールの入門書に /*構造体変数student*/
int length = sizeof stundent /sizeof *student
というのがあるのですが何故これで配列の要素数が出るのでしょうか?
sizeof student / sizeof student[0]だと配列の要素数が出る理屈は何となく分かるのですが
配列とポインタは別のものですよね?
int length = sizeof stundent /sizeof *student
というのがあるのですが何故これで配列の要素数が出るのでしょうか?
sizeof student / sizeof student[0]だと配列の要素数が出る理屈は何となく分かるのですが
配列とポインタは別のものですよね?
100デフォルトの名無しさん
2020/05/08(金) 22:21:29.33ID:/+tKw0XQ student[0] と *student は同じ
101デフォルトの名無しさん
2020/05/08(金) 23:07:29.79ID:+i26a8kQ 何で同じなのでしょうか?これで動くからこういうもの。という理解で大丈夫なんでしょうか
102デフォルトの名無しさん
2020/05/08(金) 23:48:12.63ID:xx+9oYGy MSの陰謀。
103デフォルトの名無しさん
2020/05/09(土) 06:15:34.68ID:LKKpAq9a とりあえず stundent は誤りで正しくは student だとして
多くの場合、配列名は「配列の先頭要素を指すポインタ」と解釈される、から。
つまり配列studentについて student == &student[0] が成り立つ。
*演算子を作用させて *student == *&student[0] == student[0]
よって sizeof *student == sizeof student[0]
ここで注意すべき点は「配列名がsizeof演算子のオペランドになった場合は
配列の先頭要素を指すポインタとは解釈されない」ってこと。
sizeof 配列名 == 配列全体が占有するメモリ容量
なぜそうなっているか、という理由は「そう決めると便利だから」かな。
Cの頃からそういう感じでプログラム書いてたから、という歴史的経緯もある。
>>102 初心者をからかっちゃアカンよ。信じちゃうかも知れん。
多くの場合、配列名は「配列の先頭要素を指すポインタ」と解釈される、から。
つまり配列studentについて student == &student[0] が成り立つ。
*演算子を作用させて *student == *&student[0] == student[0]
よって sizeof *student == sizeof student[0]
ここで注意すべき点は「配列名がsizeof演算子のオペランドになった場合は
配列の先頭要素を指すポインタとは解釈されない」ってこと。
sizeof 配列名 == 配列全体が占有するメモリ容量
なぜそうなっているか、という理由は「そう決めると便利だから」かな。
Cの頃からそういう感じでプログラム書いてたから、という歴史的経緯もある。
>>102 初心者をからかっちゃアカンよ。信じちゃうかも知れん。
104デフォルトの名無しさん
2020/05/09(土) 09:28:26.57ID:3rxWY8lS コロチャンもゲイツの陰謀とか言ってる人が居てわろす
温暖化も陰謀ω
温暖化も陰謀ω
105はちみつ餃子 ◆8X2XSCHEME
2020/05/09(土) 10:52:17.88ID:MmeKQuXy >>99
「暗黙の型変換」によって配列がポインタに型変換されるルールがある。
スムーズにポインタとして使えてしまうから混同してわけわからんようになる初心者が多いんだけど、
あくまでも別物であるという理解が出来ているなら入門者としてはかなり優秀だと思う。
ほとんどの場合に配列はポインタに暗黙に型変換されるんだけど、
例外としては
@ sizeof を適用するとき
A 単項の & を適用するとき
B 参照で受け取るとき
があって、これらの状況では型変換されずに解釈される。
----
余談だけど暗黙の型変換とは別に仮引数の調整というのもあって、
関数の仮引数として配列を書いた場合も配列はポインタに調整される。
たとえば
void foo(int a[10]) {}
という定義を書いたら
void foo(int* a) {}
と全く同じように解釈される。
「暗黙の型変換」によって配列がポインタに型変換されるルールがある。
スムーズにポインタとして使えてしまうから混同してわけわからんようになる初心者が多いんだけど、
あくまでも別物であるという理解が出来ているなら入門者としてはかなり優秀だと思う。
ほとんどの場合に配列はポインタに暗黙に型変換されるんだけど、
例外としては
@ sizeof を適用するとき
A 単項の & を適用するとき
B 参照で受け取るとき
があって、これらの状況では型変換されずに解釈される。
----
余談だけど暗黙の型変換とは別に仮引数の調整というのもあって、
関数の仮引数として配列を書いた場合も配列はポインタに調整される。
たとえば
void foo(int a[10]) {}
という定義を書いたら
void foo(int* a) {}
と全く同じように解釈される。
106デフォルトの名無しさん
2020/05/11(月) 03:00:46.06ID:II69MMpE すいませんロベール持ってる人にお聞きしたいのですが
305ページの
for (int i = 0, size = a.Size(); i < size; ++i) という文があるのですが
このsizeというローカル変数は何処に定義されてるんでしょうか?
305ページの
for (int i = 0, size = a.Size(); i < size; ++i) という文があるのですが
このsizeというローカル変数は何処に定義されてるんでしょうか?
107デフォルトの名無しさん
2020/05/11(月) 05:46:42.66ID:k4wInV7m >>106
“ロベール本”を持ってないので答えられない立場かも知れんけど…。
この size は「ここ」で定義されているんだと思うよ。
for の初期化式 int i = 0, size = a.Size(); で、
「int の i」と「int の size」という2つの変数を定義している。
“ロベール本”を持ってないので答えられない立場かも知れんけど…。
この size は「ここ」で定義されているんだと思うよ。
for の初期化式 int i = 0, size = a.Size(); で、
「int の i」と「int の size」という2つの変数を定義している。
108デフォルトの名無しさん
2020/05/11(月) 07:45:03.87ID:II69MMpE109デフォルトの名無しさん
2020/05/11(月) 09:53:48.32ID:MhpqGE2N 型が違うときは?
for (long i = 0, int size = a.Size(); i < size; ++i)
for (long i = 0, int size = a.Size(); i < size; ++i)
110デフォルトの名無しさん
2020/05/11(月) 19:53:43.37ID:8B6Lebzi C++17なら
for (auto [i, size] = tuple(0L, a.Size()); i < size; ++i)
for (auto [i, size] = tuple(0L, a.Size()); i < size; ++i)
111デフォルトの名無しさん
2020/05/21(木) 23:33:00.50ID:fIo5j0A9 class DataStore {
public:
DataStore(int v) : mValue(v) {}
bool operator==(const DataStore& rhs) const;
private:
int mValue;
};
bool DataStore::operator==(const DataStore& rhs) const
{
return mValue == rhs.mValue;
}
int main()
{
DataStore ds1(10), ds2(10);
if (ds1 == ds2) {}
}
というのがあるんですがoperatorに記述されてる仮引数はどっから実引数をコピーしてるのですか?
後演算子のオーバーロードに関して分かりやすく解説してるとこあれば教えていただけると嬉しいです
public:
DataStore(int v) : mValue(v) {}
bool operator==(const DataStore& rhs) const;
private:
int mValue;
};
bool DataStore::operator==(const DataStore& rhs) const
{
return mValue == rhs.mValue;
}
int main()
{
DataStore ds1(10), ds2(10);
if (ds1 == ds2) {}
}
というのがあるんですがoperatorに記述されてる仮引数はどっから実引数をコピーしてるのですか?
後演算子のオーバーロードに関して分かりやすく解説してるとこあれば教えていただけると嬉しいです
112デフォルトの名無しさん
2020/05/21(木) 23:57:47.49ID:ut4Weg2U operatorも、ただの関数
if (ds1.operator==(ds2)) {}
if (ds1.operator==(ds2)) {}
113デフォルトの名無しさん
2020/05/22(金) 00:55:03.99ID:H9gcgSgg const DataStore& rhsの実引数はds1ってことですか?
114デフォルトの名無しさん
2020/05/22(金) 06:44:02.17ID:8neFOyTD この流れだと、仮パラメータ rhs にバインドされる実引数は ds2 でしょ。
クラスのメンバ関数として宣言された2項演算子の operator OP(rhs) は、
lhs OP rhs と書くと lhs.operator OP(rhs) が呼び出される。
…と書いても分かりにくいね。
具体的には ds1 == ds2 と ds1.operator==(ds2) が同じ意味、
ってのが >>112 の人の言ってること。
クラスのメンバ関数として宣言された2項演算子の operator OP(rhs) は、
lhs OP rhs と書くと lhs.operator OP(rhs) が呼び出される。
…と書いても分かりにくいね。
具体的には ds1 == ds2 と ds1.operator==(ds2) が同じ意味、
ってのが >>112 の人の言ってること。
115デフォルトの名無しさん
2020/05/22(金) 09:23:45.22ID:JweU/zGV 余談だけど左右の引数が const な比較演算子は非メンバ関数として実装した方が好ましい場合が多い。
(標準ライブラリでもだいたいそうなってる。)
(標準ライブラリでもだいたいそうなってる。)
116デフォルトの名無しさん
2020/05/22(金) 12:29:55.77ID:6NFPH2hn constかどうかで決めるのはアホ
117デフォルトの名無しさん
2020/05/30(土) 06:36:15.09ID:1Zwy+dfa なぜ文字から'0'を引くと数字を数値に変換できるのですか? char c='8' int a=c-'0'
理屈がよくわからないです。
よろしくお願いします
理屈がよくわからないです。
よろしくお願いします
118デフォルトの名無しさん
2020/05/30(土) 07:25:50.69ID:/FCD7s4m 順番に並んでいるから。
119デフォルトの名無しさん
2020/05/30(土) 07:33:59.81ID:1Zwy+dfa 文字コードが順番に並んでるのは分かったのですが
なぜ'0'引くとキャストせずにint型の変数に代入できるようになるかが分かりません
よろしくお願いします
なぜ'0'引くとキャストせずにint型の変数に代入できるようになるかが分かりません
よろしくお願いします
120デフォルトの名無しさん
2020/05/30(土) 07:57:34.41ID:/LdiluDZ '0'を引かなくてもキャストせずにint型の変数に代入できるよ
c/c++では文字は整数型に文字コードを入れて扱うんだよ
c/c++では文字は整数型に文字コードを入れて扱うんだよ
121デフォルトの名無しさん
2020/05/30(土) 08:07:04.11ID:1Zwy+dfa 苦しんで覚えるC言語という本の255ページに
”数字を使うときには引き算で本来の数値を知ることも出来ます。
数字に持っ文字の番号が割り当てられており例えば'0'は48番に割り当てられてます。
数字から'0'の番号を引き算すれば数値に変換され計算に使用できます。”
とあるんですが
”数字から'0'の番号を引き算すれば数値に変換され計算に使用できま”というのが意味わからないです
”数字を使うときには引き算で本来の数値を知ることも出来ます。
数字に持っ文字の番号が割り当てられており例えば'0'は48番に割り当てられてます。
数字から'0'の番号を引き算すれば数値に変換され計算に使用できます。”
とあるんですが
”数字から'0'の番号を引き算すれば数値に変換され計算に使用できま”というのが意味わからないです
122デフォルトの名無しさん
2020/05/30(土) 08:27:53.58ID:CZP1xQZw 文字が元々数値(文字コード)であることが理解できてないのでは
ASCIIコード表でググってみれ
ASCIIコード表でググってみれ
123デフォルトの名無しさん
2020/05/30(土) 10:03:05.95ID:/LdiluDZ 2に3を足す時、
int a = 2; int b = 3; int c = a + b;
とやるとc == 5になる
int a = '2'; int b = '3'; int c = a + b;
とやってもc == '5'にはならない
今やほぼASCIIだからc == 'e'になる
int a = '2' - '0'; int b = '3' - '0'; int c = a + b;
とやるとc == 5になる
'0'から'9'まで連続していることはcの規格が強制してるから
これが”数字から'0'の番号を引き算すれば数値に変換され計算に使用できます”の意味
int a = 2; int b = 3; int c = a + b;
とやるとc == 5になる
int a = '2'; int b = '3'; int c = a + b;
とやってもc == '5'にはならない
今やほぼASCIIだからc == 'e'になる
int a = '2' - '0'; int b = '3' - '0'; int c = a + b;
とやるとc == 5になる
'0'から'9'まで連続していることはcの規格が強制してるから
これが”数字から'0'の番号を引き算すれば数値に変換され計算に使用できます”の意味
124デフォルトの名無しさん
2020/05/30(土) 16:37:51.27ID:A5Abb6S3 char c = '8'; // '8'を表す文字コードの値(ASCIIでは56) char型
// '0' ... '0'を表す文字コードの値(ASCIIでは48) char型
// c - '0' ... '8'を表す文字コードから'0'を表す文字コードを引いた値(==8) char型
int a = c - '0'; // char型の数値8 で int変数a を初期化・代入
一般にint変数にchar型の値を格納することは認められている。
思うに「'8' - '0' が 8 になる」('8'の文字コードでなく「タダの8」)
という部分に引っ掛かってるんじゃなかろうか。
// '0' ... '0'を表す文字コードの値(ASCIIでは48) char型
// c - '0' ... '8'を表す文字コードから'0'を表す文字コードを引いた値(==8) char型
int a = c - '0'; // char型の数値8 で int変数a を初期化・代入
一般にint変数にchar型の値を格納することは認められている。
思うに「'8' - '0' が 8 になる」('8'の文字コードでなく「タダの8」)
という部分に引っ掛かってるんじゃなかろうか。
125124
2020/05/30(土) 16:49:13.96ID:A5Abb6S3 すまん 124 は間違ってるみたい、忘れてくれ。
char c = '8'; // '8'を表す文字コードの値(ASCIIでは56) char型
// '0' ... '0'を表す文字コードの値(ASCIIでは48) char型
// c - '0' ... '8'を表す文字コードから'0'を表す文字コードを引いた値(==8) int型
int a = c - '0'; // 数値8 で int変数a を初期化・代入
思うに「'8' - '0' が 8 になる」('8'の文字コードでなく「タダの8」)
という部分に引っ掛かってるんじゃなかろうか。
'8' - '0' は「char型の8」ではなく「int型の8」だね。(以下検証コード)
std::cout << "sizeof('8') == " << sizeof('8') << '\n';
std::cout << "sizeof('8'-'0') == " << sizeof('8'-'0') << '\n';
char c = '8'; // '8'を表す文字コードの値(ASCIIでは56) char型
// '0' ... '0'を表す文字コードの値(ASCIIでは48) char型
// c - '0' ... '8'を表す文字コードから'0'を表す文字コードを引いた値(==8) int型
int a = c - '0'; // 数値8 で int変数a を初期化・代入
思うに「'8' - '0' が 8 になる」('8'の文字コードでなく「タダの8」)
という部分に引っ掛かってるんじゃなかろうか。
'8' - '0' は「char型の8」ではなく「int型の8」だね。(以下検証コード)
std::cout << "sizeof('8') == " << sizeof('8') << '\n';
std::cout << "sizeof('8'-'0') == " << sizeof('8'-'0') << '\n';
126デフォルトの名無しさん
2020/05/30(土) 18:38:26.55ID:1Zwy+dfa127124
2020/05/30(土) 19:18:59.52ID:A5Abb6S3 型の検証はC++11なら直接的にできるね。
#include <typeinfo>
...
std::cout << "'8' is " << typeid('8').name() << '\n';
std::cout << "'8'-'0' is " << typeid('8'-'0').name() << '\n';
実装定義の型の名前を得られる。
#include <typeinfo>
...
std::cout << "'8' is " << typeid('8').name() << '\n';
std::cout << "'8'-'0' is " << typeid('8'-'0').name() << '\n';
実装定義の型の名前を得られる。
128デフォルトの名無しさん
2020/06/05(金) 17:55:42.30ID:8OoEw/S/ なかなか、適当なスレを見付けるのが難しいわい
C++ 且つ初心者だから、ここでいいのかな
subroutine で、例えば、boolean と string のふたつの変数の値を
return するには、やっぱり std::map を使うのが一番簡単でしょうかね?
C++ 且つ初心者だから、ここでいいのかな
subroutine で、例えば、boolean と string のふたつの変数の値を
return するには、やっぱり std::map を使うのが一番簡単でしょうかね?
129デフォルトの名無しさん
2020/06/05(金) 18:21:06.88ID:Uv2w5eYU std::pair<>じゃないのか?
https://ja.cppreference.com/w/cpp/utility/pair
https://ja.cppreference.com/w/cpp/utility/pair
130デフォルトの名無しさん
2020/06/05(金) 19:03:13.94ID:8OoEw/S/ うーん、なんとなくそうおもいます、ええ
131デフォルトの名無しさん
2020/06/05(金) 19:06:38.66ID:8OoEw/S/ あ、では、boolean, string, int の三つをreturn するには普通どうやるのが王道でしょうか?
132デフォルトの名無しさん
2020/06/05(金) 19:08:18.91ID:8OoEw/S/ 連投すまん。
std::tuple ですか。
std::tuple ですか。
133デフォルトの名無しさん
2020/06/05(金) 19:12:47.23ID:Uv2w5eYU たぶんそうだとお芋ます、ええ。
あと、コンテナに突っ込みたいときにはstd::variantなんかも良く使います。
今回は関係なさそうですが。
あと、コンテナに突っ込みたいときにはstd::variantなんかも良く使います。
今回は関係なさそうですが。
134デフォルトの名無しさん
2020/06/21(日) 13:29:09.07ID:hTPD8Gtd >>131
王道かどうかは知らんが、C++17以降なら
auto func() {
return std::make_tuple(a, b, c);
}
auto [f, s, n] = func();
っていう風にできるで
王道かどうかは知らんが、C++17以降なら
auto func() {
return std::make_tuple(a, b, c);
}
auto [f, s, n] = func();
っていう風にできるで
135デフォルトの名無しさん
2020/06/21(日) 16:38:41.93ID:rRP2z2l8 std::tie の方が好き
136デフォルトの名無しさん
2020/06/22(月) 16:40:35.96ID:sjaABjGh C++でint[変数]というようなことが出来ないのはstack overflow防止のためなんでしょうか?
137はちみつ餃子 ◆8X2XSCHEME
2020/06/22(月) 16:50:40.23ID:H8+bL0cM138デフォルトの名無しさん
2020/06/22(月) 20:24:27.49ID:83jG8pXe Cの新しいのだと出来る
139はちみつ餃子 ◆8X2XSCHEME
2020/06/22(月) 22:04:26.97ID:H8+bL0cM140デフォルトの名無しさん
2020/06/22(月) 23:23:01.67ID:rtw5aKlF Cは89/90が基本
141デフォルトの名無しさん
2020/06/23(火) 01:32:00.34ID:UY2AjBBL 以下のコードは比較関数をSTLのlistに渡す為のものなのですが
これを最新のVC++でコンパイルできるようにするにはどう書き直せばいいでしょうか?
typedef SubType* LPSUBTYPE;
template<> inline bool greater<LPSUBTYPE>::operator()
(const LPSUBTYPE& pObj1, const LPSUBTYPE& pObj2) const {
…
}
これを最新のVC++でコンパイルできるようにするにはどう書き直せばいいでしょうか?
typedef SubType* LPSUBTYPE;
template<> inline bool greater<LPSUBTYPE>::operator()
(const LPSUBTYPE& pObj1, const LPSUBTYPE& pObj2) const {
…
}
142デフォルトの名無しさん
2020/06/23(火) 09:26:35.36ID:RMSfHJVB143デフォルトの名無しさん
2020/06/29(月) 08:08:09.53ID:PYBXxpGI VC++についての質問になってしまうのですが、C#のようにソースファイルをリンクとして追加することは出来ないのでしょうか?
144デフォルトの名無しさん
2020/06/29(月) 18:23:34.98ID:gWW+3u18 C#と違って「既存の項目」で追加したものに関してはコピーされずに参照扱いだよ
作業フォルダ下以外のファイルをそうやって追加した場合は追加のインクルードディレクトリも設定しないとダメだけど
作業フォルダ下以外のファイルをそうやって追加した場合は追加のインクルードディレクトリも設定しないとダメだけど
145デフォルトの名無しさん
2020/09/08(火) 02:57:29.22ID:ZBc9FXfY 何で構造体のchar配列は直接値が代入できず
strcpyを使う必要があるのでしょうか?
strcpyを使う必要があるのでしょうか?
146デフォルトの名無しさん
2020/09/08(火) 03:20:04.77ID:jacy6RM2 できるよ
struct A {
int x;
char b[4];
} a = {0, 1, 2, 3, 4};
struct A {
int x;
char b[4];
} a = {0, 1, 2, 3, 4};
148デフォルトの名無しさん
2020/09/08(火) 05:56:11.78ID:ZBc9FXfY typedef struct {
char str[32];
}A;
int main(}{
A a;
a.str="aaa";
}
これができないってことです
言葉足らずですいません
char str[32];
}A;
int main(}{
A a;
a.str="aaa";
}
これができないってことです
言葉足らずですいません
149デフォルトの名無しさん
2020/09/08(火) 08:44:00.12ID:h4K4tlm9 int main(void) {
int arr[5];
arr = 3;
}
ができないのと同じ理由です
int arr[5];
arr = 3;
}
ができないのと同じ理由です
150デフォルトの名無しさん
2020/09/08(火) 09:53:15.41ID:zoI9JNor かわいいw
151デフォルトの名無しさん
2020/09/08(火) 10:55:42.52ID:0vfIbeP0 ちょっと忘れたから、推測だけど、
a.str="aaa";
"aaa" を右辺で使うと、先頭要素のアドレスに変換されるとか?
例えば、4バイトのサイズで、10〜13 アドレスに存在する場合に、10が代入されるとか
char str[32];
一方、ここにはアドレスじゃなくて、aaa\0 という4バイトの実体を代入しないといけないとか
a.str="aaa";
"aaa" を右辺で使うと、先頭要素のアドレスに変換されるとか?
例えば、4バイトのサイズで、10〜13 アドレスに存在する場合に、10が代入されるとか
char str[32];
一方、ここにはアドレスじゃなくて、aaa\0 という4バイトの実体を代入しないといけないとか
152デフォルトの名無しさん
2020/09/08(火) 11:16:05.69ID:h4K4tlm9 意図してるだろうことを無理してやるなら
str[0] = 'a';
str[1] = 'a';
str[2] = 'a';
str[3] = '\0';
でできる.そしてこれをするためにstrcopyがある
str[0] = 'a';
str[1] = 'a';
str[2] = 'a';
str[3] = '\0';
でできる.そしてこれをするためにstrcopyがある
153デフォルトの名無しさん
2020/09/08(火) 15:36:44.61ID:JkCXGknl >>148
型が違うし
型が違うし
154デフォルトの名無しさん
2020/09/08(火) 15:57:15.69ID:SNM207t1 出来ない訳じゃないんだよな
typedef struct {
char b[4];
} A;
int main(void) {
A b = {1, 2, 3, 4};
A a;
a = b; // ok
a.b = b.b; // bad
return 0;
}
自分で for で配列要素代入すれば良い訳で
面倒だから memcpy や strcpy 使ってるだけ
typedef struct {
char b[4];
} A;
int main(void) {
A b = {1, 2, 3, 4};
A a;
a = b; // ok
a.b = b.b; // bad
return 0;
}
自分で for で配列要素代入すれば良い訳で
面倒だから memcpy や strcpy 使ってるだけ
155デフォルトの名無しさん
2020/09/08(火) 16:02:13.68ID:JkCXGknl >何で構造体のchar配列は直接値が代入できず
構造体のchar配列だけじゃなくて
ただのchar配列でもダメだろ
宣言と同時に代入してるときはたまたま出来るだけ
int main() {
char a[4] = "abc"; // OK
char b[4];
b = "abc"; // BAD
return 0;
}
構造体のchar配列だけじゃなくて
ただのchar配列でもダメだろ
宣言と同時に代入してるときはたまたま出来るだけ
int main() {
char a[4] = "abc"; // OK
char b[4];
b = "abc"; // BAD
return 0;
}
156デフォルトの名無しさん
2020/09/09(水) 20:41:42.30ID:s+S5qxFe >char a[4] = "abc"; // OK
これがおkなのは、cの言語仕様におけるほんの雀の涙猫の額ばかりの文字列サポート
たまたま、ってw
これがおkなのは、cの言語仕様におけるほんの雀の涙猫の額ばかりの文字列サポート
たまたま、ってw
157デフォルトの名無しさん
2020/09/09(水) 23:49:08.55ID:N/YnHGom はじめたころは、こういうことにいちいちひっかかってたな…
わかっちゃえば、慣れちゃえばどーってことないんだけど
わかっちゃえば、慣れちゃえばどーってことないんだけど
158デフォルトの名無しさん
2020/09/10(木) 00:06:01.62ID:Qspm/kAl 同じようでいて、初期化と代入では見た目の作用がことなることがあるね
159デフォルトの名無しさん
2020/09/10(木) 00:07:00.73ID:Qspm/kAl 見た目「と」作用が
160デフォルトの名無しさん
2020/09/10(木) 15:36:27.72ID:rLZBXCmM a も b も代入禁止だ
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 中国の局長は「両手をポケット」で対峙 宣伝戦で国民に示す ★3 [蚤の市★]
- 中国側が首相答弁の撤回要求、日本側拒否 [夜のけいちゃん★]
- 日本行き空路49万件キャンセル 中国自粛呼びかけ 日本行きチケット予約の約32%に相当 ★4 [ぐれ★]
- 映画「鬼滅の刃」の興行収入急減、日本行き航空券大量キャンセル…中国メディア報道 [蚤の市★]
- 【音楽】Perfume・あ~ちゃんの結婚相手「一般男性」は吉田カバンの社長・吉田幸裕氏(41) 高身長で山本耕史似 [Ailuropoda melanoleuca★]
- 「タワマン天国」に飛びつく若者…SNSに転がる「成功体験」に続けるのか 湾岸エリアの業者が語った現実 [蚤の市★]
- 【悲報】高市効果で「1ドル=160円」が相場へwwwwwwwwwwwwwwwwwwwwwwwwwwwww 止まらぬ高市円安💥💥 [871926377]
- 小川彩佳アナ「高市総理はここまで影響が出ることを想像して発言したんでしょうか」高市ソルジャー「!!!!(シュババババ)」 [931948549]
- 【悲報】おこめ券、9.5億円配布分のうち2.4億が経費、うちJAが1億円中抜き🤗高市ありがとう [359965264]
- FGOで好きなサーヴァントがアビゲイル、北斎、楊貴妃なんだが
- 自閉症が「んなっしょい」と連呼するお🏡
- 【悲報】高市有事で日本に同調する国、1つも現れないwwwwwwwwwwwwwww [603416639]
