X



【初心者歓迎】C/C++室 Ver.102【環境依存OK】
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
垢版 |
2017/11/04(土) 16:33:35.07ID:NYxCuvMY
エスケープシーケンスやWin32APIなどの環境依存なものもOK
そのような質問は必ず環境を書きましょう
半角空白やタブでのインデントはスレに貼ると無くなります

コードを貼れる所
http://codepad.org/
https://ideone.com/

前スレ
【初心者歓迎】C/C++室 Ver.101【環境依存OK】
https://mevius.5ch.net/test/read.cgi/tech/1500329247/
0013デフォルトの名無しさん
垢版 |
2017/11/07(火) 04:47:47.90ID:T7zw8VZw
意図的に糞コードを書いた事もわからないクソがいるとは
こんな簡単なコードの動作も理解できてないようだし
0014デフォルトの名無しさん
垢版 |
2017/11/07(火) 06:16:53.55ID:pkgJL5Ib
初心者歓迎をうたうスレッドで「意図的に『糞コード』を書いた」などと
しかも後付けで言われてもあんまり支持できないなぁ。
せめて最初から「お前らこれ改善してみろよ」とかで出してくれ。
「糞コード」とけなすだけで、具体的な問題点の指摘がないってのも寂しいわ。

>>3 のソース、引数のpszが""でも、nが0でも妥当な返り値 0 が返るけど、
実は最初に見たとき n==0 で呼ばれた場合に即時終了しないと騙されたわ。
後置デクリメント評価値、ね。
0017デフォルトの名無しさん
垢版 |
2017/11/07(火) 08:24:36.39ID:FXbSqjpU
psz = "", n = 0 はいいけど
char a[8] で psz = a, n = 8 を渡すと不定値どころか鼻から悪魔の糞コード
仕様も理解せずに余計なことしてバグを作り込む知ったかの典型
0018デフォルトの名無しさん
垢版 |
2017/11/07(火) 08:32:51.44ID:T7zw8VZw
>>3

●パフォーマンス
*pszが3回も出てくる
代入して持っておいた方が
チープなコンパイラでは速度が変わる

isdigit
どうせ数字が連続してる前提のコードなんだから
関数を呼ばずに'0' '9'と比較しちゃおう
そうのが速い
関数コールは一般的に遅い

●見やすさ
forループにいくつも入れない
while (n--) か for (size_t i= 0; i < n ; i++)
null文字はbreakで

●仕様
null文字とサイズ、両方で停止は仕様としては問題ない
パフォーマンス最優先であればそれぞれの特別版を作ればいい
文字数もスペースの位置も固定で
パフォーマンス最優先なら
ループアンロールするのが一番
0020デフォルトの名無しさん
垢版 |
2017/11/07(火) 12:47:26.90ID:FXbSqjpU
>>18
> null文字とサイズ、両方で停止は仕様としては問題ない
だからダメだっつーの
知ったかは黙ってろよ
最低限サイズチェックを先にやらないとダメ
0021デフォルトの名無しさん
垢版 |
2017/11/07(火) 13:22:08.68ID:oMcRDniv
仕様として「両方で停止は問題ない」よな?

判別の順番は問題だ
順番が逆

そもそも相談者の仕様がおかしい
0022デフォルトの名無しさん
垢版 |
2017/11/07(火) 16:16:20.01ID:3ER4WXnW
先に大きさでチェックしてから 内容の nul チェックする
for ( v = 0; n-- && *psz; psz++ ) {
これなら、存在しない指し先のデリファレンスしないし

ただ、
ショートサーキット前提の記述をよしとするかどうかはわからん
0023デフォルトの名無しさん
垢版 |
2017/11/07(火) 17:07:50.15ID:Zpoup5pM
int str2i( const char *s, size_t n )
{
    int v = 0;   
    while ( n-- ) {
        char c = *s++;
        if ( c == '??0' ) break;
        if ( '0' <= c && c <= '9' ) v = v * 10 + ( c - '0' );
    }
    return v;
}
0024デフォルトの名無しさん
垢版 |
2017/11/07(火) 17:17:37.91ID:jEe4bM6y
片山以外に文字化けするブラウザ使ってる奴いるのか
あとnull文字って初心者が背伸びしてる感じがして微笑ましいな
0027デフォルトの名無しさん
垢版 |
2017/11/08(水) 01:37:38.03ID:MEe7IGP8
isdigitが関数コールな処理系ってあるのか?
ここって車輪の再発明好きな人多いのかね
0028片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/08(水) 02:06:05.60ID:TZ5JAUzS
isdigitは、ロケールの関係で遅くなる可能性があるはず。256バイトの配列を使うのが最速だ。
0029はちみつ餃子 ◆8X2XSCHEME
垢版 |
2017/11/08(水) 03:38:56.63ID:xvDlz0If
ちょっとした演算よりメモリアクセスの方が遅いこともあるよ。
本当に配列が最速?
(試したわけではないので配列が最速かもしれない……)
0031デフォルトの名無しさん
垢版 |
2017/11/08(水) 06:36:16.44ID:u4hO2YM0
int str2i( const char *s, size_t n )
{
    int v = 0;   
    while ( n-- ) {
        char c = *s++;
        switch (c){
        case '¥0':
            goto brk;
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
            v = v * 10 + ( c - '0' );
            break;
        }
    }
brk:
    return v;
}
0036デフォルトの名無しさん
垢版 |
2017/11/08(水) 11:33:23.57ID:2d9va5Xh
>>34
ああ、素人はgoto嫌うよな

>>35
もちろん必要は無い
テーブルよりは色々な面でマシってだけ
普通に if ( '0' <= c && c <= '9' ) で良い
一目で意味がわかるし高速
0039デフォルトの名無しさん
垢版 |
2017/11/08(水) 13:01:31.63ID:2VVChtYT
>>37
とおもってアセンブリ吐かせてみたら、すごかった。
48引いた上で、符号なしで10未満か判定してるので、
余分な条件分岐してなかった。
0040はちみつ餃子 ◆8X2XSCHEME
垢版 |
2017/11/08(水) 13:02:27.97ID:xvDlz0If
>>37
&& では分岐しなかった。
'0' <= c && c <= '9' を clang で -O3 付きでコンパイルしてみたらこうなった。

addl $-48, %eax
cmpl $10, %eax
setb %al

賢いな!
直後に分岐するなら結果をレジスタに書き込む必要はないから実質的に二命令だ。
0042はちみつ餃子 ◆8X2XSCHEME
垢版 |
2017/11/08(水) 18:14:28.55ID:xvDlz0If
もっと >>40 を高速化できないかと思って考えてみたが、
'0' を引くんじゃなくて 0x30 と xor を取ってから 10 より小さいか比較するっていうのでもいける。

ただ、最近はビット演算が算術命令より速いとも限らないみたいなんだよね〜
0046デフォルトの名無しさん
垢版 |
2017/11/08(水) 18:57:26.39ID:GPQLPiKH
>>21
> 仕様として「両方で停止は問題ない」よな?
相談者でないとわからん
途中に'\0'があるケースについては書いてないから

> そもそも相談者の仕様がおかしい
それはお前が決める話じゃない
0047デフォルトの名無しさん
垢版 |
2017/11/08(水) 18:59:47.82ID:GPQLPiKH
>>22
> ショートサーキット前提の記述をよしとするかどうかはわからん
if(p != 0 && *p != '\0')
みたいなのは普通に書かない?
0049デフォルトの名無しさん
垢版 |
2017/11/08(水) 19:14:43.13ID:u4hO2YM0
>>46
わからないならだまってれば
正確な要求仕様がわからない事くらい誰でもわかる

両方でとまる関数は片方で止まる関数の機能を含むので
問題になる場面は普通は考えられない
質問に書いてない、文字列の途中にNULL文字とか
いうアホな事を心配しない限り
0052デフォルトの名無しさん
垢版 |
2017/11/08(水) 19:51:21.87ID:CyIcapPx
isdigit関連で性能測ってみた。
環境: Core i7-2600 / gcc 6.4 (-O2)
rund() & 0xff の値で条件分岐して、真ならさらに rand() を呼ぶ、を10億回ループ。
条件式はASCII前提。

数字: 条件式 < int配列ルックアップ < isdigit
英字: 条件式 <= int配列ルックアップ < isalpha
数字英字: int配列ルックアップ < 条件式 < isalnum

ロケールの影響か、isalphaなどはisdigitより遅い。
char配列ルックアップはint配列より遅い。
奇妙なことに、配列ルックアップでも、数字だけより、英字も入ってくると遅くなる。なぜだ。
005352
垢版 |
2017/11/08(水) 19:54:52.03ID:CyIcapPx
あ、ごめん、rand() 呼ぶ分、数字 < 英字 < 英数字の順で遅くなるの、当然だった。
0054デフォルトの名無しさん
垢版 |
2017/11/08(水) 20:30:53.41ID:u4hO2YM0
最速なら前スレの>>995>>997

>>997は演算の依存性が高いので
>>995の方が少し速いかな?
まあコンパイラや環境依存でしょう

x64前提なら、
64bit一気に持ってきて偶数奇数桁に分けて、
LEAで5倍してシフトして足すとか
AVXで乗算してから水平演算とか
色々と考えられるけど
まあ一応このスレのC言語の範囲で
0055デフォルトの名無しさん
垢版 |
2017/11/08(水) 20:49:19.11ID:QAR8Spec
このスレの結論はこれか。
10000*a[0]+10000*a[1]+1000*a[3]+100*a[4]+10*a[6]+a[7]-5333328;

これより速くする方法あるのか
0058デフォルトの名無しさん
垢版 |
2017/11/08(水) 21:12:49.95ID:u4hO2YM0
さすがに '0' * 111111 をコンパイル時に計算しないコンパイラは無いと思うので
このままで良い気はする
当然こちらの方が意味が分かりやすい
0059デフォルトの名無しさん
垢版 |
2017/11/08(水) 21:14:04.15ID:u4hO2YM0
( ) を色々とかえて時間を測ってみたけどほとんど同じ
やっぱりLEAを多用してる
VS2017の64bit Releaseビルドの場合
0060デフォルトの名無しさん
垢版 |
2017/11/08(水) 21:39:10.43ID:u4hO2YM0
VPMOVZXBD xmm0, a
VPMADFWD xmm0, xmm0, [掛け算テーブル]
VPHADDD xmm0, xmm0, xmm0
VPHADDD xmm0, xmm0, xmm0
0062デフォルトの名無しさん
垢版 |
2017/11/08(水) 21:42:47.06ID:u4hO2YM0
微妙に間違った
メモリが連続してれば複数同時に出来る
連続してなくても複数同時にやった方が速い
0063デフォルトの名無しさん
垢版 |
2017/11/08(水) 21:43:54.20ID:YMDhJx7T
>>29でメモリアクセスに言及されてる話の流れの中で
10億回ループがいちいちキャッシュクリアされてるのかが気になる
0064デフォルトの名無しさん
垢版 |
2017/11/08(水) 21:49:19.34ID:u4hO2YM0
普通はキャッシュに入ったままだが、
処理次第で可能性が無いことはない
他のキャッシュを汚染する可能性もある
HTTなどでは特に

他に良い方法が有るのにわざわざ面倒なテーブルにする意味がわからない
0065デフォルトの名無しさん
垢版 |
2017/11/10(金) 07:46:10.46ID:F5y7yLWH
std::vector<std::string>からchar*const[]を作成するいい方法ってないですか。
newするしかないですかね。
0070片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/10(金) 21:39:23.58ID:x1hu0efq
>>68
クラスは構造体に関数を追加したようなもの。
クラス内部の関数はメソッドと呼ばれる。
メソッドからは、クラスのデータとメソッドを参照できる。
データとメソッドのそれぞれの項目をクラスのメンバーと呼ぶ。
クラスの実体はインスタンスと呼ばれる。メソッドからは、thisポインターにより、クラスのインスタンスを参照できる。
メンバーは、public:、protected:、private:によってアクセスを制御できる。アクセスできないメンバーを参照するとコンパイルエラーになる。
0071片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/10(金) 22:11:59.59ID:x1hu0efq
class A
{
int a;
};
と書くとA::aは、privateになる。構造体と同じアクセスにするには
class A
{
public: int a;
};
と書かないといけない。このようにクラスのデフォルトのアクセスはprivateになり、構造体はpublicになるという違いもある。
0072片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/10(金) 22:14:05.73ID:x1hu0efq
クラスはコンストラクタと呼ばれる特殊なメソッドがあり、インスタンスの構築に使われる。
また、インスタンスが破棄されるときに、デストラクタという特殊なメソッドが呼ばれる。
0073片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/10(金) 22:17:22.95ID:x1hu0efq
コンストラクタの例。
class A
{
public:
int m_a;
A(int a) {m_a = a + 1; }
};

int main() {
A a(2);
printf("%d\n", a.m_a);
}
0074片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/10(金) 22:19:15.61ID:x1hu0efq
別のコンストラクタの例。
class A {
public: int m_a;
A(int a, int b) : m_a(a + b) { }
};
int main() {
A a(2, 3);
printf("%d\n", a.m_a);
}
0075はちみつ餃子 ◆8X2XSCHEME
垢版 |
2017/11/10(金) 23:02:09.42ID:4kUQXTj6
そんなの説明してやらなくてもネット上に無数の解説があるだろ。
ちゃんとした説明を読んで理解できないなら掲示板で短い説明読んだってわかりゃしねーよ。
0076片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2017/11/10(金) 23:14:40.61ID:x1hu0efq
>>75
情報が多過ぎて迷子になってるんじゃないか。マニュアル読め、規格票読め、で終わればいいのだが。
0078デフォルトの名無しさん
垢版 |
2017/11/10(金) 23:32:23.63ID:2wx3Dyqu
>クラスは構造体に関数を追加したようなもの

こういうアホってどこにでもいるんですね
0079 ◆QZaw55cn4c
垢版 |
2017/11/10(金) 23:40:07.53ID:qCTAOUdD
>>78
その理解で8割がたOKだと思うのだが、何が問題なの?
0082デフォルトの名無しさん
垢版 |
2017/11/11(土) 00:49:17.73ID:1PUme0lw
山田さんってどんな人?と聞かれて
原子の集まりだよ。って答えるようなもの
形式的にウソじゃあないんだが
そこじゃないだろっていう
0083デフォルトの名無しさん
垢版 |
2017/11/11(土) 02:47:19.31ID:fW1Ux/Kl
純粋にC++のクラスそれ自体の概念というなら
C言語(ベース)でのオブジェクト指向プログラミングをサポートするために言語機能で用意された部品
オブジェクト指向プログラミングにおけるオブジェクト、オブジェクトの状態、
メッセージの送受信、メッセージを受けたときの振る舞いといった概念を具体化した仕組みの一例
0085デフォルトの名無しさん
垢版 |
2017/11/12(日) 23:51:21.74ID:nDRVLcBe
実のところはOOPを知らないからクラスをどう使えばいいのかわからない/
他人の真似でなんとなく使ってるけどなぜクラスを使うのかがわからないといったあたりの話だろ
0086デフォルトの名無しさん
垢版 |
2017/11/22(水) 02:18:46.71ID:jSfISRI4
下手にクラスを説明するやつが多いせいで、コーディング経験なくても理解できる概念的なものだと思われちゃう
クラスは実用あってこそ
0088デフォルトの名無しさん
垢版 |
2017/11/22(水) 17:16:56.90ID:ehTxx6H6
メンバ関数を呼び出す際の
「オブジェクトにメッセージを送る」って言い回しも
C++だと分かりにくいね。

この表現がしっくりくるプログラミング言語というか
環境もあるのだろうけど。
0091デフォルトの名無しさん
垢版 |
2017/11/22(水) 20:55:50.24ID:6XHR1ElK
>>90
あれも結局、関数(メソッド)の動的なコールをそう呼ばせてるだけ
同じSmalltalkでもSmalltalk-72までさかのぼるとメッセージ送信と呼べなくもない仕組みにはなっているけど
それでもオブジェクトに(メッセージを)「送る」というよりは(トークン列を)「流し込む」って感じかと

まあ、ともあれC++の「オブジェクト指向」を説明するときには「メッセージを送る」とかはすっかり忘れていいよ
そもそもC++の設計者の提唱するオブジェクト指向は「抽象データ型(端的にはユーザー定義の型)」を
Simulaという言語から拝借した「クラス」という言語機能で実現することが主軸のアイデアなので
http://www.stroustrup.com/whatis.pdf
0092はちみつ餃子 ◆8X2XSCHEME
垢版 |
2017/11/22(水) 21:08:20.60ID:Rn9KsJdK
言語の意味論とそれを実現するメカニズムは別物だから、
仕組みがどうなっているかから考察するのは無粋だと思うけどなぁ。

まあ C++ は低水準レイヤでの仕組みを意識せざるを得ない、
意味論とメカニズムが不可分なデザインではあるから概念としてのメッセージ指向よりも
メカニズムに意識が引きずられてしまうというのは確かにあるかもしれない。
0094デフォルトの名無しさん
垢版 |
2017/11/22(水) 21:28:03.86ID:+hB2MqUt
>それでもオブジェクトに(メッセージを)「送る」というよりは(トークン列を)「流し込む」って感じかと

違いがわからないw
0097デフォルトの名無しさん
垢版 |
2017/11/22(水) 23:09:00.03ID:NgxFNsMl
>>91
>抽象データ型
これがすべてなのに、どうしてメッセージ駆動の話が今でももちきりなのだろうか?
0098デフォルトの名無しさん
垢版 |
2017/11/23(木) 08:26:45.55ID:Qr4pYIOt
>>96
C++に「動的なものは何もない」という主張ではなく
「静的に決まる何かが一つでもある」時点でそれをメッセージングに例えるのは興醒めという意味

少なくともケイは彼のOOPにおけるメッセージングを「遅延結合の徹底」の目的で提案している
http://d.hatena.ne.jp/katzchang/touch/20080807/p2
「私が考えるOOPはメッセージング、状態処理のローカルでの保有・保護・隠蔽、
そして全ての物に対する強力な遅延束縛、これだけだ。
これはSmalltalkとLISPだけが実現できている。他のシステムでも可能かもしれないが、私は知らない。」

つまるところ、これはすなわち、SmalltalkやLispみたいな変態言語でもなければ、
(あるいはアクター機構のように、並列化を意識して本当にメッセージを送るのでもなければ)
無理して「メッセージパッシング」なんてたとえる必要は無いんやで、という話でしかない
0100デフォルトの名無しさん
垢版 |
2017/11/23(木) 14:15:04.16ID:76J8bh8G
Cのキャストについて教えてください

int a,b;
long c;

の条件下で、a+b 、a*100+b*100(a*100、b*100のどちらもlong型になる)
がそれぞれlong型の解になるような場合のキャストとしては

1 c=(long)a+b;
2 c=(long)a+(long)b;

3 c=(long)a*100+b*100
4 c=(long)a*100+(long)b*100

とそれぞれ、どの記載が正しいのでしょうか?
0101デフォルトの名無しさん
垢版 |
2017/11/23(木) 14:19:02.83ID:5K7m7Mmt
>a*100、b*100のどちらもlong型になる

intでは表せなくてlongが必要
って意味なら3以外
0102デフォルトの名無しさん
垢版 |
2017/11/23(木) 14:20:46.83ID:76J8bh8G
ありがとうございます。
1と3は似ていますが1はa,bそれぞれキャストされるが
3ではb*100はキャストされずint型で計算されてしまう、ということなのですね
0103デフォルトの名無しさん
垢版 |
2017/11/24(金) 16:57:14.87ID:L5ESShiZ
よろしかったら教えてください

  if(a==0){ }

と記述するのにfor文では
  
  for(i=0;1<100;i++){}

と書き、for(i==0;i<100;i++){}

と書かないのはなぜでしょうか?(==の使い方)
0105デフォルトの名無しさん
垢版 |
2017/11/24(金) 17:07:52.77ID:QRhLqwOG
スーパー初心者か?
forでも書いてもいい。だが意味がないか低い。
「=」は代入だが「==」は代入でない。
0106デフォルトの名無しさん
垢版 |
2017/11/24(金) 17:08:50.74ID:L5ESShiZ
片山先生、ありがとうございました!
そういうことなのですね。理解できました、いつもありがとうございます!
0107はちみつ餃子 ◆8X2XSCHEME
垢版 |
2017/11/24(金) 17:38:47.92ID:lG8HVUMw
わかってる人にとってはクソみたいな質問だけど、
数学だと代入 (定義) するっていうのと等しいっていうのは区別がはっきりしないので、
そういうメンタルモデルで考えてると混乱しちゃうってのはわからんでもない。

とはいうものの、よっぽど出来の悪い入門書でもそこらへんわからんようなのは無いと思うんだが、
どういう学び方をしてるんだかちょっと疑問。
0109デフォルトの名無しさん
垢版 |
2017/11/28(火) 12:50:21.53ID:bi1wDt8X
数学のイコールには比較(の結果等しい)の意味しかないだろう
Pascalみたいに代入が:=なら良かったのに
0110デフォルトの名無しさん
垢版 |
2017/11/28(火) 12:57:44.05ID:cL+Re6N7
プログラムを記述する際、等しいかを比較するより、代入のほうが頻度が高いから
Cでは多く入力するであろう代入側を 1文字にして そうでない側を 2文字にした
って聞いたことがある
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況