C言語なら俺に聞け 157
レス数が1000を超えています。これ以上書き込みはできません。
前スレ末期の流れを再掲
> 996 自分:デフォルトの名無しさん (ワッチョイ 0f45-Sffs)[sage] 投稿日:2021/06/28(月) 09:33:23.09 ID:so+vl3vs0 [1/2]
> printf("%d", sizeof (char)123); とやろうとしたら
> キャストのカッコがsizeofのカッコと解釈されてエラーになるのな
> printf("%d", sizeof((char)123)); ならおkなんだけど
> なんだか気持ち悪い
>
> 997 返信:デフォルトの名無しさん (ワッチョイ cf05-Ibo0)[sage] 投稿日:2021/06/28(月) 10:13:18.97 ID:x/UkG1ge0
> >>996
> sizeofって括弧なしで使えるの? 知らなかった
>
> 998 返信:デフォルトの名無しさん (ワッチョイ 0fda-qjGA)[sage] 投稿日:2021/06/28(月) 10:20:43.69 ID:WejOUFlX0
> >>996
> sizeof演算子の優先順位はcast演算子の優先順位より高いので、括弧がないと
> まず最初にsizeofと数値リテラルが評価されてその後でその結果をcastで評価するという
> おかしな状態になるのでエラーになったのでは?
>
> 999 自分:デフォルトの名無しさん (ワッチョイ 0f45-Sffs)[sage] 投稿日:2021/06/28(月) 10:38:03.51 ID:so+vl3vs0 [2/2]
> sizeofとキャストはどちらも単項式なので右から結合するはず
> にも関わらずキャストが先に読まれないので気持ち悪いと言ったんだ
> 字句解析と意味解析ってことかな
>
> 1000 名前:デフォルトの名無しさん (ワッチョイ 0fd2-kMi9)[] 投稿日:2021/06/28(月) 11:05:48.75 ID:HW6dR9O/0
> そもそも
> sizeof (char)
> paだけでいいものをそう記述してるのが気持ち悪い。 >>前スレ1000
いやcharのサイズが知りたいのではなく
キャスト式(char)123のサイズを調べようとしたんだ
Cはchar変数の値を使おうとするとintに拡張するし文字定数もint型なので
char型の値を持つ式なんてあるのかって cppreferenceのc operator precedenceの項の注釈によるとオペアンドはtype castにはできないって書いてあるね。ただ仕様書の該当箇所は探せなかった 脚注2は俺が気持ち悪いと言ったことと似てるけどsizeof(int)*pが
(sizeof(int)) * pという算術乗算になるという話なら単項式のsizeofより優先順位が低いからまだわかる A.2.1が引用元みたいなんで読んでみるとsizeof (int)123はダメだね。
sizeof +(int)123なら動くようだ。sizeof (int){1}も動きそう。 あーそうか
A.2.1. (6.5.3)では
unary-expressionに該当するものの1つに
unary-operator cast-expressionがあるけど
unary-operatorにキーワードsizeofが含まれず、
カッコなしのキャスト式は
sizeof unary-expressionとなっていて
sizeof cast-expressionではないってことか ところで sizeof((char) 123) と sizeof(char) って同じことだよな? ポインタキャストは敷居線さえ跨がなきゃ思い通りの値出てくるけど
数値キャストは難しいんだよな >>8
GCC 9.3.0 では両方とも 1 でした >>10
ていうかやるまでもなく結果が同じにならないとおかしいよね。
一方は値を char 型にキャストしているんだから sizeof の結果は char 型のサイズになる。
もう一方は char 型のサイズを求めているから char 型のサイズになる。 二項演算子のいくつかでは汎整数拡張が適用されることになっているが
sizeof に渡す分には char のオブジェクトは char のオブジェクトだよ。 char型 + char型 の式でもint型に拡張されるんだっけ? typedefによる新しい型の定義って、コンパイラの工程的にはどの工程で定義されるの?
字句解析?構文解析?プリプロセスじゃないよね 質問が間違ってる気がするけどね。
コンパイルレベルで処理されるのか、リンクするまで処理されないのか、でしょ。
で、typedefは前者 構文解析の後 typedef と認知したうえで、シンボルのテーブルに追加してかないと
置換?読み替え?はできないよねぇ…
C言語は、その構造上1回の通読では解決できないんだっけ? 5.1.1.2 Translation phasesくらい読んでから来いよ だからぁw
構文解析ってのはパーサね?w←これは例えばbisonで作るやつね?w
字句解析ってのはレキシカルアナライザね?w←これは例えばflexで作るやつね?w
レキシカルアナライザかパーサかって、そもそもレキシカルアナライザってのは
字句区切るだけだよwそれをどんな命令であるかを解釈を決めるのが構文解析ねw
コンパイルの1pass,2passって話なら、まあそれでもいいけどさw
用語がでたらめすぎんでしょ。
だいたいそんなこと知ってどうするんだよ?w Cの構文解析器実装してるんだけどBNFのtypedefの扱いがイミフなんだよねー >>23
またぁw
BNF関係ないでしょうw
つか、typedefなんて意味不明なんてことはないと思うけど。
特定の記法のことを指してるの?BNFで書かれた
typedefの規則が読みとれないって言ってるの?w
typedef struct {...};
と
struct {...} xxx;
を区別できないとかそんな話?
よくわかんないけど、変に切り出すんじゃなくて、
ストレートにこれがやりたいけど、これどうしたらいいか
わかんない、って聞く方がいいと思うんだが。
なにいってんだか、知ってる人ほど却ってわかんねーと思うんだが。 typedefがstorage-class specifierに属してることを言ってるなら
構文上の便宜のためだけ(for syntactic convenience only)って6.7.1(5)に書いてあるけど
Annexのsyntax summaryだけ見てる感じかな
かなりエスパーしてるから的外れだったらすまぬ みなさんレスありがとう
「C BNF」でググって一番上に出るBNFを参考に実装しているんだけど、BNFが古いせいかtypedefの構文が欠落してるような気がして(気のせいでした。↓のレス参照)
でも<typedef-name>という要素はあるからtypedef機能自体はあるらしい
BNFに書いてないってことは構文解析以前の処理になるのかもしれないと思ってここで聞いてみたんだけど
混乱した人もいるみたいですまない
>>25
あー!そういうことですか
なるほど疑問が解けました
typedefをspecifierで扱ってるわけですね
ありがとうございます typedefがないってことはK&R Cか
規格票でもドラフトでもいいから拾って読んでみ
http://www.open-std.org/jtc1/sc22/wg14/ >>27
参照してるBNFはおそらくK&R Cですね
関数の宣言が古いスタイルになっているので
ありがとうございます、参照してみます リスト型構造体配列って他の言語でもあるのでしょうか?
現在職業訓練で勉強中なのですが、独学でやらないといけない範囲のようでして、
時間的余裕があまりない状態です。
他言語でも似たような考えが出てきて、Cで覚えておくと役立つなど
ございましたら、頑張って挑戦してみようと思っています。 リスト型構造体配列ってのは講師の人の自作用語?
それなら定義を示してもらわんと。 リンクリストなら他の言語にもある
普通は配列とは言わないからその言葉は謎だけど…… ポインタの代わりに配列のインデックスを保持してるような感じなのかね?
リスト型構造体配列 C99かそれ以降の標準的な環境において
(bool)someval
と
!!someval
って(例外なしに)全くおなじ効果を生むと思っていいですか。
前者はJISX3010の6.3.1.2などで「値が0になるなら0,それ以外なら1」と書かれている一方,
後者は(初学者なので経験がなく,正しい認識ではないかもしれませんが)慣用的な書き方なので
規格票にも書かれておらず,正確に同じ意味なのかどうかを確かめられませんでした。 >>33
「意味するところは全く違うが、結果だけ見れば全く同じ」です。 bool型が導入されたことで得られるメリットはは何かあるでしょうか
またデメリットはあるでしょうか メリットは、必ず真偽値になること
デメリットは、必ず真偽値になってしまうこと
例えばエラーコードのようにいい加減な経緯で拡張していくことはできない >>35
ctypes.h の isalpha() とか islower() とかその他大勢は、偽のときは 0 を必ず返しますが、真のときは 1 とは限らない 0 でない別の数を返したりするんですよ
そういうのは紛らわしいので、そういう紛らわしさが減る bool の存在はありがたいですね 関数の () は演算子
キャストの () は演算子
だそうですが
数学の数式で優先度上げるのに相当する () は演算子ですか? >>33
真偽値型にキャストした結果の型は _Bool で、 !! を通した型は int という違いはある。
https://wandbox.org/permlink/zlxhRTGr5Sj8IsiH
整数を扱う多くの場合では整数拡張が入ったりして違いが吸収
されてしまうからどちらでもいい場合がほとんどだと思うけど、
あらゆる状況で完全に同じとは言い切れない。
ちなみに C++ では整数に ! を適用した結果は bool なので、
もちろん !! の結果も bool になる。 >>38
違う
一次式を囲む()は
後置式に属する関数呼び出しの()でも
単項式に属するキャスト記法のキャストの()でもない >>42
_Generic 便利ですね……。C11から追加されたんだ。 >>38
ほとんど関係ないけど,Haskelだと優先度を上げる()記法を
$演算子で代用できるから,
「優先度を上げる()を演算子としてみる」というのはそう不自然ではないかも。
でも(たぶん)C言語だとそういうことはない。 こういう認定試験用にC言語勉強するときって
https://www.sikaku.gr.jp/js/cpjv/
32bit版のコンパイラの方が良いんでしょうか?
64bit版でintとかsize_tとかサイズ変わると困りませんか? 逆にsizeof(size_t)が返す値が処理系定義であることを考え落とす癖がつくと
そこを弱点として狙われるぞ 変わって困ることならむしろ困ってみたほうが勉強になるんじゃね。 > 1級で使用する環境について(公開試験)
コンパイラ Borland C++ Compiler 5.5
JIS X 3010-1993に対応
エディタ TeraPadまたはメモ帳
文字コード:SHIFT-JIS、改行コード:CR+LF
※当コンパイラの操作にはコマンドプロンプトの知識が必要です。
※解答用のソースプログラムは、SHIFT-JISで保存してください。
※指定した保存形式で保存されていない場合は、採点の対象となりません。
・・・なんだかなぁ JISX 3010 1993で使えない構文や関数を回避して回答する能力を受験者に課すなんてなかなか高度な試験だね BCCってまだVSの無料版が無かった頃に無料で使えるコンパイラとして粂井氏のHPで紹介されてて使ってたなあ
その時代から何も進化してない資格なんだろうな…… bccとかLSI-C(試食版)とか、Cマガの付録で > JIS X 3010-1993に対応
つーことは
int main(void)
{
printf("");
int x; /* これがダメ */
//このコメントもダメ
for(int y = 0; y < 1; y++) ; //これもダメ
}
今どきのコンパイラはみんなOKなのに
うっかり使うと減点されるという陰険な罠だな 検定する側が時代遅れで
しかもこんなレベルじゃ
最早コボちゃん世代を嗤えませんね? まあそういう時代もあったというのは知識として有るに越したことは無いが、
前提とされるとだいぶんしんどいな。 Cの範囲内なのにえらいストレスフルやな
//コメントや for 内の変数宣言が禁じられると辛い だんだんいじくり回されてワケわからん言語になるんだろうな >>60
あまり変更するのもどうかと思うけど
昔のままで良しというわけにもいかん部分もあるし、
現実的な妥協点をさぐりながら改定していくしか仕方がないだろ。 今日,O'rellyの『Lex & Yacc』で「自己参照型構造体」という概念を知ったんだけど,
これが動作する理屈とかこういう書き方をする利点がマジでわからなくて苦戦してる。
でもこれを理解できるようになればメモリ確保やポインタ参照の話がわかるようになる……
と期待してがんばる。 基本的なメモリ管理をわからない段階で yacc の本を読んでるのか。
実用を通して理解するのもひとつの道ではあるだろうけど、
最初はもっと単純な事例集みたいなのを見るほうがいいと思う。 >>62
言わば再帰的定義の産物だよ。
論理的に入れ子の構造にする訳。
ヌルポインタで終わり。 自分が興味あることから掘り下げて行くのはいいと思うよ
とりあえず C言語 リスト構造 とかでググってみて struct A { A a; }; ではないからな
struct A { A *p; }; ならただのポインタ >>63
「勉強不足」といわれればそれはその通りなんだけど
寧ろC言語のやっかいな部分にできるだけ触らないですむように
という動機でlexとyaccを学んでるんですよね……。
↑まあこういう考え方が間違ってるかもということに
『Lex & Yacc』を読んでいて気付きはじめていますが……
>>65
こういう↓ことですよね。
https://dev.grapecity.co.jp/support/powernews/column/clang/031/page02.htm
実は『Lex & Yacc』内ではそのコード概念の名前はでてこなくて
コード断片でggったりしてました。 >>66
- A *p;
+ struct A *p;
ここはCスレだぞ
struct A
{
struct A a; //incomplete typeなのでオブジェクトは定義できない
}; 「自己参照型」っていうのが
誤訳なんじゃないかって思ってる
実際には「自己型参照型」でしかない
ポインタを代入するときに自分自身(オブジェクト)のポインタを代入する訳じゃないから
自己を参照してる訳じゃないんだ
ここを誤解するから理解が進まない
>>69 君には伝わってるから良いよ ISO: self-referential structure
JIS: 自己参照する構造体
誤訳かねえ int arg;
p = (*p)(arg);
戻りが関数(A)のポインタとなる 引数int を取る関数(A) の宣言もまた
記述が無理な事案ですかの 自己参照型は、2分木とか?
親は、2つの子のポインターを持っていて、それが再帰的に続くもので、
親子は同じ構造をしているもの わざわざ「自己参照する構造体」という用語が与えられているのは構造体タグのスコープを
説明する文法解説上の都合じゃないかな。
ノードを直列に接続すればリストになったり複数の接続を持てば木になったりというデータ構造のことと、
他のノードへの接続には C ではポインタを使うのが自然だというふたつの事柄を併せると
結果的に自分自身 (を含む構造体) と同じ型のオブジェクトを指すポインタが現れることもあるというだけのことで、
(データ構造、また、その管理においては) 指している型が同じなのか違うのかで
ことさらに区別して考える意味はあまりないように思う。 C言語の勉強中にリスト構造とかの部分でポインタがよくわからない!って人良く見るけど
実際のところC言語で仕事するときにリストとか二分木ってあんま使わなくね?
構造体の配列は良く見るけど
組み込み系とかだとメモリ少しでも節約するためにリストにしたりするの? > 組み込み系とかだとメモリ少しでも節約するためにリストにしたりするの?
意味がよくわからんが
組み込みでもリストもmallocも普通に使うぞ
OSがなきゃmalloc使えんとでも思っているのか? >>76
いや一般的にリソース制約の多い組み込み系だからこそmallocとリスト構造使って
本当に使う分だけメモリ確保するのかなと思ったんだけど
なんか気に触ったのならすみません > C言語で仕事するときにリストとか二分木ってあんま使わなくね?
気に障るってか、数秒えってなった >>75
ワイはプロではないし組み込みのこともよう知らんけど
言語処理系を作ったときに当然ながら構文木を組み立てたりはしたし、
宣言した名前を保存するハッシュテーブルはチェイン法を使ったのでリストの一種でもあるわな。
(今なら面倒くさいので C++ で書いてしまう (標準ライブラリのコンテナを使う) だろうけど。)
分野によるとは思うけど、リストや木がそんなにほとんど目にしないというほうが不自然な気がする。 >>77
横からだけどマイコン次第だわな。メモリの動的確保なんて、
そもそも無理ーって処理系もある。コンパイル時にメモリは固定しちゃう。
昨今の32bitのARMマイコンやらESPやら最近触ってるけどmallocも普通にあるし、
サポートライブラリにlistのソース付いてたり(それを使うべきかは悩む)。
更にc++なんかも普通に使えるから、なんか落ち着かんw あれは簡単なのか?w
コマンド自由に操れる人、果たしているのかな? よくUnixについての記事や書籍に,
「sedは入力全体を一度に読み込まず一行ごとに処理するから
動作が遅くならず,メモリ容量も気にしなくていい」
みたいなことが書いてあって,それは概ね事実だと思うんだけど,
C言語でsedを実装するときもviを実装するときに比べて
メモリ確保とかが楽なんだろうか。 Ruby では、
IO.readlines は、ファイル内のすべてを読み込むが、
IO#each_line は、1行ずつ読み込む sedにもホールドスペースがあるから、テキスト全体を読み込んで処理する事も出来る >>88
そらviよりは楽だろうが、Nコマンドとかで複数行抱える必要はあるし、そもそも数百万桁の行食わされるかもしれんし。
オリジナルsedは確か桁数制限あったよね? POSIX標準は満たすべき最低レベルを規定しているって事ではないかな?
GNU sed の実装はこうみたいだ
For those who want to write portable sed scripts, be aware that some implementations have been known
to limit line lengths (for the pattern and hold spaces) to be no more than 4000 bytes. The POSIX standard
specifies that conforming sed implementations shall support at least 8192 byte line lengths. GNU sed has
no built-in limit on line length; as long as it can malloc() more (virtual) memory, you can feed or construct
lines as long as you like. 自己参照型構造体(用語法的に正しくないという指摘もあるけど…)がちょっとわかったかも。
はじめは『もう一度基礎からC言語』の第31回「データ構造(10)〜構造体をポインタでつなぐ」
https://dev.grapecity.co.jp/support/powernews/column/clang/031/page02.htm
を参考にしてたんだけど,記事集の題名からも察せる通り「初めてC言語を学んでいる」
という状態で読むには向いていなかった。
図書館でそれっぽい本を漁って見つけた,
『C実践プログラミング』の17章「高度なポインタ」にある解説が
初学者としては一番わかりやすかった。
わざわざこのスレで報告する需要はないかもしれないけど,
将来に,おなじような概念の理解で詰まっているひとの
助けになるかもしれないからという言い訳でもって書き込ませてください。
--
C言語でデータ構造を作ろうと思ったら,
基本的にコンパイル時から大きさを決め打ちして用意せざる得ないけれど,
無から有を作り出せるー*1]malloc関数を用いることで
コンパイル時ではなく実行時に自由に拡大できるという,
記憶領域を食いにくいのに大規模な情報を格納できるデータ構造を作れる。
なぜ構造体を使うのかは自明すぎるためか書籍では明言されていなかった。
あえて言葉にするなら,
C言語において 複雑な情報を格納できるデータ構造を作るにあたって
「構造体を定義する」ことはもっとも一般的な慣行であることと,
C言語の演算子に自己参照型構造体の操作に非常に便利な演算子
構造体ポインタ演算子->が用意されているということが決め手なのかな。
*1: ちょっと違う気がするけど,書籍にはそう書いてあった。 >『C実践プログラミング』の17章「高度なポインタ」にある解説が
君にとって判り易かったのかも知れないが
君の感想文を読むとあまり良い本ではなさそう ama zon 4900900648
2冊目か3冊目に読む本
2005年6月21日に日本でレビュー済み
以前、某雑誌の特集で、Cがわかればすべてがわかるというのがあり
ましたが、まぁヨイショのし過ぎな文句なのかもしれませんが、依然
として、知っておいたほうがよい言語だと思います。
Cでプログラムするような機会は、ほんとここしばらく全くないです
けど、Cを勉強していたおかげで今までかなり助かってます。なんと
いってもCの影響を受けた言語は多いですからね、色々応用がきくも
のなのですよ。
で、肝心のこの本ですが、前訳本でも書きましたが、初心者を脱しよ
うとしている人にとっては最適だと思います。よくありがちな、Cの
文法やテクをただ書いているだけの本とは違います。プログラムのス
タイルやプログラムの仕方についての記述が数多くあります。
Cのような言語の場合、どのようにコーディングするのか、言い換え
るとWHATだけでなくHOWについて必ず考えなくてはならないと思いま
す。この本は常に、HOWについて意識した記述をしており、そういった
点が、この本を推奨する大きな理由です。
ただ、この本だけで、ポインタとかのキモはさすがに理解できません
でしたので、別の本を読む必要があります。 >>74
>(データ構造、また、その管理においては) 指している型が同じなのか違うのかで
>ことさらに区別して考える意味はあまりないように思う。
それ
>>94
>C言語の演算子に自己参照型構造体の操作に非常に便利な演算子
>構造体ポインタ演算子->が用意されているということが決め手なのかな。
まだ誤解してると思う 不充分。この本だけでは足りない。
2019年4月13日に日本でレビュー済み
敢えてこの本を買う意味が分からない。
20世紀に買ったが、この本だけでは解決できない問題があり、投げた。
よくある fgets & sscanf のコードの部分では、入力バッファのクリアを行う方法が書かれていなかった。
当時はインターネットのコンテンツが今ほど発達しておらず独学ではお手上げ。
他にも何か問題点があった気がするし、今や様々な解説サイト、また「よくある解説サイトの誤りを指摘するサイト」で足りる。
セキュリティ対策についても、wikipediaのサンプルコードやjpcertの「CERT セキュアコーディングスタンダード」など、今では豊富な資料がネットで入手できる。必要なら英文資料だってネットで容易に入手できる(もちろんC99の規格文書も)。 諸々のコンパイラや環境がC11に準拠するようになって久しく、また業務やOSSでもC11で導入された新機能を使うようになってきてる印象があるんだけど(要出典w)、こと並列処理に関してはまだまだC99+POSIXスレッドを使ってた方が良さそうね。
久しぶりに並列処理を書いてみようと思ったんだけど、C11で標準規格として導入されたthread.hに対応してるコンパイラが現時点でも(特にUnix系で)ほとんどないことが意外だった。
今のところthread.hをUnixで使いたかったらmusl Cくらいしか選択肢がないし、
ttps://www.etalabs.net/compare_libcs.html
3年前の電子掲示板の書き込み(要は典拠性が低い)ではあるけど
ttps://www.reddit.com/r/C_Programming/comments/94acpl/c11_vs_pthreads/
ほとんどの人がC11ではなくPOSIXが定めてるスレッド使ってるみたいだし。
せっかく汎OS的に並列処理がかけそうな規格なのに、もったいないというかなんというか。。。 >>99
>入力バッファのクリアを行う方法
入力バッファのフラッシュは確か MS のコンパイラだけでしか使えない環境依存だったかと
行末に \n が在る、とかのルールがあれば、それが出るまで読み捨てればいいのですが、そういうルールがなければどうしようもない気が >>100
>せっかく汎OS的に並列処理がかけそうな規格
C11 は調べていませんが、C++ と比べてどうですか?私は C++11 以降でそういうのを書いています‥‥ >>100
C11 のスレッドはオプショナルなのでスレッドを提供しなくても C11 準拠を名乗れる。
C の立場からすれば標準ではあまり高レイヤな機能を要求するのは気が引けるだろうし、
かといっていまどきスレッドに全く触れないでいるというわけにもいかないという妥協なんじゃないかな。
C11 のスレッドの基本的なモデルは POSIX のスレッドとそんなに違いがない (名前が違う程度) ので、
かえって乗り換える強い動機にならないのかも。 >>96
>>98
ご指摘ありがとうございます。
構造体リストについてもう一度 勉強しようと思います。
(他の方も書評の引用などありがとうございます)
『C実践プログラミング』のAmazon書評にあった
『Cクイックリファレンス 第2版』というのを試しに読んでみたところ,
かなり規格網羅的で丁寧だと感じたので,
当面はこれで勉強してみようと思います。
こちらの書籍には「
struct data {
// some code...
struct data *next
}
」という形のコードの解説そのものはありませんが,
ポインタの解説をCの規格に沿ってしてくれているので
かなり良い教科書として使えそうです。
以後言い訳::
いまのところ,まだC言語の規格が全て頭に入っている状態ですらなく,
ましてや実際のプログラミング作法も分かっていない段階なので,
ある書籍を見たときの(現代における)正確性・信頼性の判断が
できないんですよね……。
『C実践プログラミング』は昔のO'Reillyが出している書籍なので
ある程度信頼できるかな,と思って読み進めていたんですが,
(実際,本質を突いていて分かりやすいと感じる部分も多くありました)
時代的にも正味の内容的にも現代において参考にすべき
良書とはいいがたいのかな……? ポインターで次へつないでいく、リストみたいな自己参照型。next pointer。
同じ構造体のリスト。
動的関数型のElixir は、片方向リストを使う
a → b → c → d
struct data {
struct data *next
}
これが両方向リストなら、struct data *prev も持たなければならない。
次・前の2方向へ、たどれなければならないから
a ←→ b ←→ c ←→ d
ポインターに、null を代入すれば、次・前は存在しない。
つまり、終端を表す
詳細は、アルゴリズム・データ構造を参照 >>98
いや確かに -> は自己参照する構造体を使うときに好都合だぞ
(*(*p).next).next が p->next->next で済むんだから 双方向で b を削除するのに
b->prev->next = b->next;
b->next->prev = b->prev;
b さよなら
これで済むからありがたい表記ではあるな >>110
異論があるなら堂々と言えよ
自分の意見が屁理屈かどうか見せずにそれを言うのは卑怯だぞ そもそも話がかみあってない
こっちは気付いてるけど
君は気付いていない
ただそれだけ
だから屁理屈 結局、自分は尻尾を見せないんだな
やりあう価値もないゴミだな、唾棄 自己参照型の構造体で固定段数のリンク手繰るのに便利にはなってるけど
自己参照型の構造体があるがゆえに -> ができたんじゃなく
単にポインタの指し先(構造体)のメンバを (*). じゃ遠回りなので直接指定したいがための存在だと思ってる >>114
同意だが、.で共用出来なかったんかね?
関数と関数ポインタみたいな感じで、左辺がポインタだったら逆参照してからメンバアクセス。 >>115
Rust ではそうしてるんだから C でも最初からそういう選択も出来たはずではあると思う。
だけど違うことをするのに同じ見た目にするのが良いかどうかというのは微妙なところ。
どちらが良いと一概に言えるもんではないからな。 >>117
派生関係も時系列も前提にしてない。
別の選択をしたものが事実として存在するので可能であるのは疑いないと言ってる。 FortranやCobolにも導入して欲しいのか? うーん?
ある構文(範疇としては演算子の形態論?)について,
「他の言語での採用例があるからC言語がそういう構文を持っていても不思議じゃなかった」
という話が展開されていたと思うんですけど,
どうして「RustはCの派生」とかFortranやCOBOLの構文の話になったんですかね……? C99以降で真偽型をboolのように表記したいときは<stdbool.h>を読み込みますが,
規格票には「型boolはマクロとして定義しろ」とあります。
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n2596.pdf#section.7.18
一般に既存の型から新しい表記の型を定義するときはtypedefを使うべきだと
(典拠は失念したのですが)聞いたことがあります。
たしか,コンパイラによる検査があったりより構文的に厳密になったりするから,
というような理由だったはずです。
真偽型boolがtypedefではなくマクロで定義されている理由ってなんでしょうか。
思い当たる理由としては,C++との互換性がありますが,それをC言語の規格で考慮する意味がない
(というか,C++の規格をC側から参照すると循環的になってしまう気がする)
気がします…。
C規格の論理的根拠の真偽型にかんする節も読みましたが,
「typedefではなくマクロを使う理由」は記載されていませんでした。
http://www.open-std.org/JTC1/SC22/WG14/www/docs/C99RationaleV5.10.pdf マクロだと#undefできるから自分でboolを定義してる古いコードのための移行措置っぽいね
<stdbool.h>をincludeしなければいいと思うけど間接的にincludeされるケースもあるんだろう
_Boolの方は予約語になってる
7.18 (4)
..., a program may undefine and perhaps then redefine the macros bool, true, and false.
プログラムはbool、true、falseマクロをundefineして再定義することができる
7.31.11 (1)
The ability to undefine and perhaps then redefine the macros bool, true, and false is an obsolescent
feature.
⇒ bool、true、falseをundefineして再定義できる特性は廃止されつつある Win32APIとか使わずに
Cの標準関数でカレントディレクトリではなく
今実行中のexeのpathを得る方法はどれですか? int main(int argc, char* argv[])
の argv[0] で実行ファイルへのフルパスがえられるのは環境依存だったかな・・・ mainの第2引数の argv[0] にはコマンドラインから入力した通りのコマンド名が入っているんだっけ
フルパスで入っているんだっけ 被った
たしか Windows はフルパスだったような…
違ってたらごめんなさい Windows という書き方はよくないかな
シェルの実装によると思います
なので、WSLに持っていくと期待通りに動かなかったりするかもしれません
ここでは Windows限定でよさそうだけど え?そう? Windows で C 使う人って今はあまりいないのでは? Linux とかなら分かるけど。 powershellはフルパスだけどcmdは入力のまま
結局はCreateProcessに渡した文字列なのでフルパス前提にしちゃだめよ
OSに依存しない方法で確実なのはないよなぁ
argv[0]が
ファイル名のみ:カレント+環境変数pathを走査
相対パス:カレントと連結
絶対パス:そのまま
とかやればそこそこいけるだろうけどめんどくさいな 純粋なC標準の範囲では不可能な気がする
カレントディレクトリをとるgetcwd()もPOSIX(unistd.h)だし
C言語の標準ライブラリにはディレクトリ階層の概念自体がなさそう >>131
powershell と cmd で違うのか…
なんでそうしたんだろ
何れにしても、けぅこう面倒なのね みなさんありがとうございます
dirname(argv[0]) したら argv[0] が壊れました
ほんとうにがりがとうございました これ解決策じゃなくて愚痴なんだが、main()関数が使えるのはホスト環境で、つまりmain()関数のargv[]引数は「OSによる支援」を前提にできるんだから、実装依存じゃなくて「argv[0]には実行されたファイルのOSにおけるパス名が格納される」みたいな仕様にしてもよかった気がする。
それこそstdint.hみたいに、多種多様な機器への対応を考えなくてもいい関数なんだから、実行環境のファイルシステムやらをある程度は仮定しちゃってもいいわけで。 ファイルシステムもOSもない組み込み機器もあるわけで・・・ >>136
どんな OS でも Unix 風のファイルシステムを採用しているというわけではなくて、
たとえば BTRON が採用しているファイルシステムでは
同名のファイルが存在してよく、ディレクトリのような階層化は存在しない。
全体で唯一に区別できる名前 (フルパスに相当するもの) がない。
OS だってファイルシステムだって多種多様なんで、
起動時に「なんらかの」文字列で情報が与えられるということ以上は
環境依存にならざるを得ないよ。 >>137
その場合は通常の main 関数からの起動にはならない (main に意味のある引数が渡されないか特別なスタートアップ経由で起動される)
ので、「main に値が渡されるならば」それなりの OS が仮定できるというのが >>136 の言ってることやで。 >>139
すげぇ
たまには正しくわかりやすい説明できんじゃん
ちょっと見直した コード記述してて実行ファイルのフルパスが必要となるんだから
それなりのOSから叩き起こされてること前提よね >>138
> BTRON が採用しているファイルシステムでは
> 同名のファイルが存在してよく、ディレクトリのような階層化は存在しない
知らんかった……。
調べたところBTRONは組込み機器向けのファームウェアじゃなさそうだし,
ホスト環境=「それなりのOSが期待できる」環境あっても,
「あるファイルのパス名が存在して,その絶対値が文字列として一意に定まる」
ことさえ期待できないのか……。 >>134
dirname()は引数を破壊するのでコピーしてから渡すべし
今回のケースでは結局ダメだけどw > [...] the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n2596.pdf#section.5.1.2.2.1
C2xでもargv[0]に何が格納されるかは「実装依存」って書いてあるね……めちゃくちゃ残念だ。
あとこれ読んでて気が付いたけど,「ホスト環境」ってhost environmentじゃないのね。
hosted enviromentだから,正確に訳すなら「ホスト済み環境」とかのほうが良いのかな? そのhosted environmentはプログラムの実行環境(execution environments)を
・freestanding(自立した環境=OS無しの組み込み系)
・hosted(OSにhostされた環境)
に分けたものだからOSとかプラットフォームを指すホスト環境とはたぶん別の意味 hosted environmentの概念には明らかにUNIXが背景になってるね
MS-DOSだのCP/MだのROM BASICだのまでは想定してない >>146
くわしくしりたいです。
「OSというのものは高性能である」という前提が
Unixとかでしか通用しなかったってことですか? >>147
性能とかじゃなくてモデル化の仕方が多様という話。
たとえば古い時代の BASIC (N-BASIC など) は環境変数やコマンドラインという概念は持たないが、
違う形でデータを受け渡す方法は持っていて、どちらが高性能かというようなものではない。 >>148
今 調べた知識なのでいろいろ間違っているとは思うのですが,
N-BASICとかってそもそも「OS」なんですかね……?
「hosted environmentという概念はUnixを想定したもので,
古いBASICでは通用しない」
という話からは,
1. Unixと古いBASICが同列の概念である
2. hosted environmentは「OSがある環境」を指している
ようなことが読み取れるんですが,
1. N-BASICはUnixのような
「機器→抽象化層1 (HAL/OS) →カーネル→シェル」
みたいな構造では表わせない位置にあるため
Unixと同列(あるいは類似)の概念として扱うのは
違うような気がすること
2. そもそもhosted environmentは
C2x規格の5.1.2.2で規定されている動作を実装した処理環境であって
「OSがある環境」を指してはいないこと
(だからUnixがどう,みたいな話は関係ない?)
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n2596.pdf#paragraph.5.1.2.2
などから,ちょっと納得しがたいです……。 IPLで起動して、ハードウエアへのアクセスを代行し、
コマンドをタイプして結果を文字で表示するCUI
という観点からはUNIXとBASICは同列だよ
MS-DOSでのデバドラはお行儀でしかなく
アプリが直接I/Oなんて珍しくもなんともないが
一応argc, argvという概念はあった
言い出すとマイクロカーネルをヨイショする連中を嘲笑うように
モノリシックカーネルでいったLinuxは、じゃあOSに非ずなのかと
OSとは何か、何が該当し、何が該当しないのかは
見方が色々で誰もが認める基準はなかなかできない OSから外れた例をわざわざ挙げたのだろうと思っていたが、OSが何か分からない人でしたか... >>149
> N-BASICとかってそもそも「OS」なんですかね……?
---------- JIS X 0001-1994 ----------
オペレーティングシステム, OS(省略形)
プログラムの実行を制御するソフトウェアであって,
資源割振り,スケジューリング,入出力制御,
データ管理などのサービスを提供するもの。
備考
オペレーティングシステムは,ソフトウェアが主体であるが,
部分的にハードウェア化することも可能である。
-------------------------------------
まあ要するに OS がどのような構成を持つものなのかというのは曖昧で、
Unix 的な立ち位置も OS が持ちうる構成のひとつでしかないんよ。
> Unixと同列(あるいは類似)の概念として扱うのは
> 違うような気がすること
「モデル化の仕方は多様」という例のひとつとして N-BASIC を出している。
違うように感じられるならそれは提示した意図通り。 この人の理解が間違えている。
わざと言っているとしたら悪質 >>154
俺もわからん。
何がどう間違ってるのか説明しておくれ N-BASICは確かにハードウエアを直接制御できるという意味では
OSに近い。ただ今のOSとは全然違う。BASICだと遅すぎるので
大半はマシン語で直接書いてある。今のOSとは考え方が違う。 >>156
たしかにそういう意味では「OS」といえるのかもしれないですね。
ただ,それだと組込み機器のファームウェアだって
機器を操作できる,対人インターフェースがあるという点ではOSといえることになりません? >>158
はっきりした基準はないという前提だけどぼんやりとした概念的な部分では
OS はアプリケーションソフトの対比的なものだと思う。
用途ごとのアプリケーションソフトを起動するという前提がないなら機能的に OS 相当のものを
含んでいても普通は OS とは言わないんじゃないかな。 ホントにOSだと主張するなら、ぜひWindowsの仮想環境で動かしてみてくれ 動かせないのなら、回りくどい事言わず、無理ですと言えば済むよ amd64で動くN-BASICがあるならできるんじゃない?
無いなら無理だわな 最近はスマホのカメラ部品にTRON OS入ってるんだって?
もうBIOSやファームウェアもOSになるんじゃないかとも思っちゃう。 >>152-153
BIOS: BI + OS
DOS: D + OS
OSとは >>154
>わざと言っているとしたら悪質
ほんそれ
最近そういう書き込みが多い
5chから人を減らす作戦だろう >>167
> BIOS: BI + OS
ネタか?
Basic Input/Output System やぞ
> DOS: D + OS
こっちは合ってる >>169
もちろんネタと書いてあるのでネタなんでしょ。 質問です
int flagA = 3 == 3;
int flagB = 3 == 3 == 3;
int flagC = 3 == 3 == 1;
の結果が
flagA : 1
flagB : 0
flagC : 1
になるのですが
flag B とか flag C は何が怒っているのでしょうか? >int flagB = 3 == 3 == 3;
↓
int flagB = (3 == 3) == 3;
↓
int flagB = (1) == 3;
↓
int flagB = 0;
>int flagC = 3 == 3 == 1;
↓
int flagC = (3 == 3) == 1;
↓
int flagC = ( 1 ) == 1;
↓
int flagC = 1; int flagD = 3 != 3;
int flagE = 3 != 3 == 0;
int flagF = 3 != 3 == 1;
flagD : 0
flagE : 1
flagF : 0
になります タイホするっ!! ダーン ダーン
int flagB =
ここまでと
3 == 3 == 3
が別のパーツになっていて
== は左から結合するので
(3 == 3) == 3 となり真は1になるので
1 == 3 で偽すなわち0だ 演算子の優先順位って覚えるのヤダー。自分書くと括弧だらけだわ。
どの辺が塩梅なんかねー?明示的でないと駄目よってコーディングとかもあるし。 & ^ | なんかのビット演算が比較よか低いのが微妙に嫌 結合の優先度は、自分が分かっていても
記憶があやふやな人が不安になるといけないから
結局カッコを明示的に描くかな… >>181
覚える気があっても、覚えさせられる気がしねー。 自分を磨くのは本人なので
そんなお節介は考えなくていい CでC++の純粋仮想関数のような事をやりたいのですができますか? 疑似インターフェースです。 typedef struct iunknown iunknown;
struct vtable
{
int (*query_interface)(iunknown*, int, void**);
int (*add_ref)(iunknown*);
int (*release)(iunknown*);
};
struct iunknown
{
long count;
vtable* vtbl;
};
みたいなことか? あ、いかんvtableのtypedef忘れたけどまあ許せやw 幅があると言うなら狭めるようなヒント書けばいいだけ
たたき台として>>187はそれほど悪くないと思う >>187
スゴーイ 感謝感激 ありがとうございます。
typedef struct {
void (*interface_a)();
void (*interface_b();
,
.
} TINTERFACEXXX;
typedef struct {
TINTERFACE ia;
} TOBJA;
なんてリレーションスタイルも考えたんですが、
いずれにしろ、クリーンアーキテクチャーのCでのSOLID原則ができるというところまでこぎつけました。
ありがとうございます。 奥村晴彦 『改訂新版 C言語による標準アルゴリズム事典』の
「改訂新版 序」に、
> 現代の慣習に従って、[…] EXIT_SUCCESSを0にしたりした
とあるのですが、EXIT_SUCCESSマクロ変数を使った方が
定数即値を決め打ちするよりも可搬的であり、
それこそ「現代の慣習」であるように思うのですが、
実際はEXIT_SUCCESSより0を使う方が「現代的」なんですかね。
なお、誤植も疑ったのですが、集録されている実際のコードにおいても
return 0;と書かれていました。 >>193
0以外 は1以上も-1以下もあるし、下手すりゃ数値以外の可能性すらあるけど
0 は絶対0なので、少なくともこれに関してだけは
私は許そう >>194
なるほど、「0 は絶対0なので」というので納得できました。
ありがとうございます。 >>193
思想的にはともかく、その件については習慣として定着してるという事実があるんで、
事実に逆らってもしょうがない。
ちなみに main 関数だけは return 文を通過せずに } に到達した場合には
return 0; と同じになるという仕様になってるんで、 return 文自体を省略するという
スタイルもある。 >>193
mainの出口は仕方ないんだよ
enumなんて考え方ができる遙か前に決まったことで今さら変えられないというのが現実だ
mainの第2引数だって今ならconst付けそうなところだけど
これまたconstなんかなかった頃に決まったことだ >>197
歴史的にはそうなのかもしれないけど、それだと「EXIT_SUCCESSを0に」することが「現代の慣習」であることの説明になってなくないような
なんでEXIT_SUCCESSと書いてたのを0と書くようにしたのかが知りたいんでは
もう納得してるみたいなんでアレだけども マジックナンバーなんて駄目でしよってノリでEXIT_SUCCESSを使ってたけどあまり流行らなかったから0に戻したってことじゃないの? >>199
マクロ (#define) の話だからenum関係ないよ C言語7不思議
enum { A=1 } main(void) { return A; }
このコードは合法か否か? >>200
だね
じゃあEXIT_SUCCESSはマジックナンバーないのかって >>204
マジックナンバーって何かわかってる?
ググってからでないとenumみたいに頓珍漢なこと言って恥かくよ? 横だけどeasing関数でマジックナンバーっての見たけど、結局何だったのかわからないままですわ >>202
基本的には否だが、許容される場合はありうる。
main の型は以下のいずれか。
@ int main(void);
A int main(int argc, char * argv[]);
B 以上の二つのいずれかと等価 †1
C 以上の三つのいずれでもない処理系定義の方法
それとは別に
「main関数の返却値の型がintと適合しない場合,ホスト環境に戻される終了状態は,未規定とする。」†2
とするという文言もある。
C で言う「未規定」というのは処理系が挙動を選択して良いことを意味するので、
適合しなくても適合したときと同等の処理になるように実装している処理系はあるかもしれない。
enum で定義した型 (列挙型) は
「char,符号付き整数型又は符号無し整数型と適合する型とする。型の選択は,処理系定義とする」 †3
とあり、列挙型が int と適合する可能性はある。
また、上述のCとして処理系が main の返却値の型が列挙型であったときを許容するような定義をしているかもしれない。
-------------------------
†1 typedef やマクロによる別名、あるいは型調整などで同等になるものという意味
†2 「適合」に関する規則は複雑なのでここでは説明しない
†3 個別の列挙型ごとに選択してよい >>206
おまえさんこそ何かわかってなさそうだな
なぜ、その値なのか由来が不明な定数は
スペルが0であろうがEXIT_SUCCESSであろうが
0x00であろうが本質的に同じことだぞ
UNIXを背景とせずにreturn 0;が説明できるか?
おまえさんみたいにググって拾った情報を丸呑みしてると
わかってないやつの間違った理解が伝搬するだけだぜ >>210
EXIT_SUCCESSがどういう意味かもわからないなら英語からやり直せよw
値の話じゃないことぐらい理解しろ
非常に稀な例としてEXIT_SUCCESSが0でないシステムが存在する
例えばOpenVMSでは
EXIT_SUCCESS = 1
EXIT_FAILURE = 2
だったりする
http://fafner.dyndns.org/cgi-bin/conan.com?key=CRTL~exit%2C_exit~Argument&title=VMS%20Help
なのでそういうシステムへの移植を考えてるなら意味はあるけどそんな人はほとんどいないからreturn 0;でいいやんって話
そもそもunixでも0, 1以外の値を返すコマンドは多数あってその場合は自分でEXIT_xxxを定義する必要あるから0, 1だけ定義されててもねぇって感じもあるし >>211
おまえさんは>>193が英語の話だと思っていたのかw
0がどういう意味かもわからないならCをやり直せよ >>211
関係ない。 言語仕様としては 0 が成功を表すというのは保証された動作で、
もしもホスト環境の都合と食い違うならランタイムサポート (スタートアップルーチン) で補正すべきこと。
EXIT_SUCCESS 「も」成功を意味する値として使えるというのとは独立した話。 >>212
まじでマジックナンバー知らんのか?
0じゃ何を意味するかわからんから名前をつけるって話だぞ
EXIT_SUCCESSが英語だから英語の勉強しろって言ってるだけ
日本語使える環境なら
正常終了 = 0
でもいい
で、>>193の件はそうは言っても正常終了で0以外なんてまずないし、たいていの人はmain()が0を返したら正常終了ってわかるからreturn 0;でいいやってなってるだけ >>213
> 関係ない。 言語仕様としては 0 が成功を表すというのは保証された動作
どこで規定されてるのか示してみ
そもそもOpenVMSの処理系は規格違反とでも言うのかよw >>214
ほかはともかく、 0 だけはマジックではなく明確に意味を共通で持たせている
という話なのでは? >>215
mainの戻り値がデフォルトで正常なときは 0 なのは言語仕様に規定されてるね
0又はEXIT_SUCCESSの場合,成功終了
この「又は」はほんとにORなので、EXIT_SUCCESS=1 のときは 0でも1でも正常よ >>215
繰り返すが EXIT_SUCCESS 「も」成功を表すことは保証されている。
それとは関係なく 0 が成功なのは保証された動作
以下は C99 からの抜粋 (日本語は JIS から対応箇所を抜粋)
5.1.2.2.3 Program termination
If the return type of the main function is a type compatible with int,areturn from the
initial call to the main function is equivalent to calling the exit function with the value
returned by the main function as its argument
main関数の返却値の型がintと適合する場合,main関数の最初の呼出しからの復帰は,
main関数が返す値を実引数としてもつexit関数の呼出しと等価とする
7.20.4.3 7.20.4.3 The exit function
If the value of status is zero or
EXIT_SUCCESS, an implementation-defined form of the status successful termination is
returned. If the value of status is EXIT_FAILURE, an implementation-defined form
of the status unsuccessful termination is returned. Otherwise the status returned is
implementation-defined.
statusの値が0又はEXIT?SUCCESSの場合,成功終了(successful termination)状態を処理系定義の形式で返す。
statusの値がEXIT?FAILUREの場合,失敗終了(unsuccessful termination)状態を処理系定義の形式で返す。
それ以外の場合,返される状態は処理系定義とする。 >>214
#define AHO_NO_3zvDecHz0 0
int main(void)
{
return AHO_NO_3zvDecHz0;
}
こう書いてもなぜ0なのかはわからない
マジックナンバーとはこういうことだぞ
extern int svc_get_success_code();
int main(void)
{
return svc_get_success_code();
}
こういうのと違うからな >>216
ほとんどの環境で 0 を正常と解釈できるからマジックナンバー扱いでなくてもいいだろって言う判断を奥村晴彦氏がしたってだけの話だと思う
>>217
途中でreturnせずにmain()の最後まで到達したら0を返す(これは言語仕様)という話と返された0が正常終了とみなすかどうかは別の話
> 0又はEXIT_SUCCESSの場合,成功終了
と主張するなら規格のどこで規定されてるのか書いてくれ 5.1.2.2.3 プログラム終了処理
main 関数の返却値の型がint と適合する場合,main 関数の最初の呼出しからの復帰は,main 関数が返す値を実引数としてもつexit 関数の呼出しと等価とする。main 関数を終了する}に到達した場合,main 関数は,値0 を返す。
7.20 一般ユーティリティ<stdlib.h>
EXIT_FAILURE
及び
EXIT_SUCCESS
は,整数定数式に展開され,それぞれホスト環境に失敗終了状態又は成功終了状態を返すために,exit関数の実引数として使用することができる。 >>217-218
すまん今規格見たら確かに書いてあったわ
OpenVMSとかは処理系で変換してるんだろうな
>>219
それは単にアホが意味不明な名前付けしてるだけ
そんなレベル低い話はチラ裏にでも書いとけ >>222
スペルを変えるだけでは無駄ってことだよ
どこから出てきたのか、何から導いたのかが示されていなければ同じことだ >>223
何わけわからんこと言ってるんだよ
EXIT_SUCCESS がわからないならプログラマ辞めちまえよw は? EXIT_SUCCESSの意味を英語で理解しろとか言ってきたのおまえさんだぜ
NO_PROBLEMなんてオレオレマクロでもおまえさんは満足なんだろ
どうりで規格票もロクに読まねえわけだ
プログラマ辞めちまえをそのまま返すぜドスカタン > は? EXIT_SUCCESSの意味を英語で理解しろとか言ってきたのおまえさんだぜ
EXITもSUCCESSも英語だから英語「を」理解しろって言ってるんだが?
英語の前にお前は日本語を理解できるようになならないと駄目だなw 知らねえやつがまずいない英単語でドヤってて恥ずかしくねえの? ちょっと神経わからんなw
Cを使う以上はISO/IEC 9899に書かれていることが前提だからこそEXIT_SUCCESSというスペルの意味を知っているべきだが
おまえさんが露呈したアレこそがプログラマにあるまじき姿だろうがよ シェルスクリプトスレの名物キチガイコンビみたいだなお前ら >>227
> 知らねえやつがまずいない英単語でドヤってて恥ずかしくねえの?
どこを見たらドヤッてるように見えるんだよ…
> ちょっと神経わからんなw
そもそもドヤるという神経がわからんわw >>229
どこを見るってPCのモニタだがw
1たす1は2なんだぞ〜ぼくすごいだろ〜みたいなお気の毒な姿 規格票は英語で書かれているわけだが
読んでないのは誰かさんだったね(プークスクス >>230
> どこを見るってPCのモニタだがw
わー、おもしろい
これで満足かな?w スルーすれば逃げられると思っているようなのでもう一度言ってやる
Cを使う以上はISO/IEC 9899に書かれていることが前提だからこそEXIT_SUCCESSというスペルの意味を知っているべきだが
おまえさんが露呈したアレこそがプログラマにあるまじき姿だろうがよ 露呈したのはEXITやSUCCESSでドヤられたとか思うお前のレベルだろw なんだか香ばしいですね‥‥
>>218
完璧な回答ですね‥‥ main以外の関数だと、成功失敗の値は特に決められてはいないんですよね? >>236
うん、決められてないよ
まあユーザ的には0を成功としておけばいい雰囲気だけど
システムコールに近づくとだいたい0が失敗になってくよね
0っつーかぬるぽっつーか (s)scanf() の戻りは渡った非引数への変換に成功した数ですし ケースバイケースですわね >>236
規定はないけどある程度の習慣はあって、おおざっぱにまとめると
・関数が受け持つ機能が副作用であり、
返却値は成功or失敗のみを通知すればよいときは 0 を成功値とする
・関数が意味のある値を返すときはありうる値の範囲ではない値を失敗値とする
(0、ヌルポインタ、負数、無限、NaNなど)
・入力値 (関数の引数) が正しい限り失敗がないことを見込めるときは
不正な入力があった場合を未定義とする
(呼出し前にチェックされているか、ロジック上正しいことをプログラマが保証することを期待する)
という感じだと思う。
あくまでも標準ライブラリやそれを踏襲した習慣をまとめるとこんな感じだろうという私なりのまとめなので
常に正しい選択というわけではないということはことわっておくが、
標準ライブラリを全く使わないようなプログラムもないだろうし
標準ライブラリを真似ておけば全体として一貫性が出て綺麗なんじゃないかな。 >>234
それでexitやsuccessの意味を知らないと証明したつもりになっているアホを
じゃあドヤる以外のどんな表現をすればいいんだ? >>243
> それでexitやsuccessの意味を知らないと証明した
どこからそんなアホなことを言い出したんだ?
またPC画面からかな?w exitなんかで終わらしちゃダメでしょ
returnで終わらせないと どこから終わっても良いのか?それとも出口は一つにすべきか? >>249
どこからでも return してよいのか?それとも return 文の記述は一箇所に限定するべきか? 一つの関数内でreturnは一つにするというコーディング規約があったときは
gotoの使用が増えてましたっけ Cなので仕方がないな。他の言語のように例外処理が try ... catch とかで使えれば gogo なくしても見易く書けるだろうけど。 出口を1つにしたほうが達成感がある
だがreturnお前はだめだ goto なしでやる方法は色々あるが、30年ぐらい前に何も参考にせずに俺が考えついたのは for (;;) のブロックに入れて途中で条件により break する方式。 >>255
最後のbreakを忘れたらそうなるのでそれだけは注意が必要 ま、しかし、今はそういう例外処理的なやつは躊躇せずにgoto使うけどね。そうしないと見づらいし分かり難くなるから。 gotoを上手く使えないのは自制心がないやつだけだ
俺みたいに自制心のある人間はgotoとはマブダチになれる >>245
あ、じゃあ違うんだな?
> EXIT_SUCCESSがどういう意味かもわからないなら英語からやり直せよw
規格票もロクに読まないからEXIT_SUCCESSがどういう意味かわからんやつが
英語がどうたら言うのは確たる根拠もなく言ってた戯れ言てことだな
PC画面に映ってるアフォはオモロイなwww まずマジックナンバーの話なのか規格の話なのかはっきりさせようか…
あと「〇〇がわからないなら□□しろ」と言うのは「〇〇がわからない」と言ってる訳じゃないぞw 証明も承認もされていない前提で何かぬかして
それを肯定して欲しがるのは二重質問だろアフォ 証明とか承認とか、仮定法に全く関係なくて笑える
肯定とかに至っては全く意味不明w 前提を間違ってるのをどんなに言い訳しても無駄だよ
,,-―--、
|:::::::::::::;;;ノ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|::::::::::( 」 <仮定法仮定法仮定法仮定法・・・・
ノノノ ヽ_l \______________
,,-┴―┴- 、 ∩_
/,|┌-[]─┐| \ ( ノ
/ ヽ| | バ | '、/\ / /
/ `./| | カ | |\ /
\ ヽ| lゝ | | \__/
\ |  ̄ ̄ ̄ |
⊂|______|
|l_l i l_l |
| ┬ | なんの前提も置いてないのに前提が間違ってると言い続けるしかないポンコツBOT並みの知能だからねぇw > EXIT_SUCCESSがどういう意味かもわからないなら英語からやり直せよw
前提: EXIT_SUCCESSがどういう意味かわからない
主張: 英語からやり直せ
該当者がいないんだが
あ、1人いたな規格票読まねえやつがw >>257
for (;;) するくらいなら do {} while (0); 選ぶかな こんなのもわかんねーなら会社辞めちまえまえ!
って言われて会社辞めるアホやな
まあ辞めた方が会社にも本人にも良さそうだけどw >>274
同意
無限ループは for(;;)
途中脱出は do {} while(0) を使うな >>278
for(;;)
ウォーニングが出ないからこちらを好みます while(1)だとどのツールでどういう警告が出る? Warningって読み方ウォーニング?
ワーニングじゃないの? >>282
Star Wars
×スターワーズ
◎スターウォーズ
って覚えてね >>280
cl -W4 while.c
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
while.c
while.c(5) : warning C4127: 条件式が定数です。 >>280,281
うーん、手元の cygwin gcc 10.2.0 では while (1) も while (42) もウォーニングは出ませんね、コメントありがとうございます‥‥昭和は遠くなりにけり >>282
アメリカ人だと ゥワーニン って言ってた
インド人(会話は英語)は ウォニング ってグまではっきり言ってた
こっちから言うときは片仮名で「ワーニング」って言っても余裕で通じた
まあエンジニアどうしで通じりゃ適当でいいんだよ >>282
グーグル翻訳に発音させてみたらどちらともつかぬ半端な発音に聞こえる。 >>279
つーかマジックナンバーがないのが魅力
# 組み込みでは無限ループがないほうが珍しい >282
「ア」と「オ」の発音の違いは曖昧。
…というのをトリビアの泉でやってた。 while( 条件式 )
そもそも条件式には、実質的なブール値・真偽値しか使えない。
MISRA-C 違反 whileの括弧の中は制御式な
== と != は等価式
不等号は関係式
条件式はいわゆる三項演算子だぞ >>295
等価式と関係式の意味的違いがよく分からん >>297
・ 優先順位が違う
・ 関係演算子は複素数型をオペランドにとれない 結局は成り立つか成り立たないかってことでしょ
その2つを厳密に分ける意味はなに? 算術式 関係式 論理式 という分類は聞いたことがあるが>>295みたいなのは初耳だなぁ。 >>300
条件式 (conditional expression) については C99 なら 6.5.15 に記述がある。
制御式 (controlling expression) という言葉は当たり前のように出現して
明確に定義を与えているらしい箇所がみつからないんだけど
仕様では >>295 の意味で使われていることは自明。 文法定義上の用語だよ
区別する最大の意義は演算子優先順位の定義
>>293が不用意に「条件式」と書いてしまったばっかりに本質的でないツッコミが発生しただけ >>302
構文規則としては
等価式:
関係式
等価式 == 関係式
等価式 != 関係式
と書いてあるからその考え方でも間違いとは言い切れないけど
それを言うなら
シフト式:
加減式
シフト式 << 加減式
シフト式 >> 加減式
だからといって 加減式 ⊂ シフト式 と言ってしまうと (日常的な感覚としては) ちょっと違和感があるし、
このへんの言葉はシンタクスを定義する上での便宜的な概念 (BNF で書くとそうなるってだけ)
だから、演算子の機能上の意味付けとは分けて考える必要がある。 >>301
>>295の意味というのがよくわからんけどcontrolling expressionって例えばswitch( )のカッコ内もそうだから等価式と関係式だけじゃないよ >>303
>区別する最大の意義は演算子優先順位の定義
まさにそこが疑問なんだけど、優先順位ごとに全部「△△式」って名前を付けて区別するのは見たことない。 >>304
日常的な話をしてるのか規格の話をしてるのかはっきりさせてからレスしてくれ
規格の話をしてるのはあんたともう一人だけだとも思うぞ
※ >>305のツッコミは別にして… >>307
違う話が混ざってるのは意図的。
レイヤが違うものを混ぜて考えるとおかしいよねという話なんで。 6.8.5.1 while 文 制御式の評価は,ループ本体の各実行の前に行う。
6.8.5.2 do 文 制御式の評価は,ループ本体の各実行の後に行う。
6.8.5.3 for 文 文
for ( 節1 ; 式2 ; 式3 ) 文
の動作は次のとおりとする。式2 は制御式とし,ループ本体の各実行の前に評価する。 条件式なんてオレ用語はwhileの括弧の中で比較だけが許されると思いたがるバイアスの顕れだろ
いいか、もっぺん言うぞ バイアス >>308
要するに荒らしたいと言うことか
ウザいけどこう言う奴は言って聞くわけ無いしな if ( 条件式 )
Ruby では、条件式にオブジェクトを書いても、
偽になるのは、nil, false の2つだけだが、
他の動的言語では、各型に偽がある。
空文字列・空配列・空辞書、0, 0.0 など
あまりに、バグの組み合わせが多いために、
実質的なブール値・真偽値しか使えないのが普通
それで、TypeScript みたいに型チェックが流行るようになった。
C も同じで、型チェック必須言語
これらが無いと、バグが多すぎて、製品レベルの品質基準にならない ループを制御するための式だから制御式というんだろうけど、
制御式のなかで
例えば
while(i++==10)
なんて出来たとしてもそんな書き方しないだろうし >>314
昔は
while((*dst++ = *s++) != '¥0');
とか定番だったけどね >>316
ノンノン!
while (*des++=*src++)
; >>313
勝手にレビュー落ちてろ
俺らには関係ない プログラミング言語C 第2版 (いわゆる K&R) に載っているくらいなので C では珍しくないのは確か。
日本語版の 129 ページあたりに「こうした慣用法はマスターすべきである」と書いてある。 K&Rは古典なので現代において参考にするようなものではない あらたに書くときに使うべきではないと思うけど古いコードがあるのも現実なんやで。 ++, -- は、バグが多いから、Ruby から排除された
Go でも、単独文でしか書けない。
組み合わせることができない
これらを組み合わせると、MISRA-C 違反。
MISRA-C に則っていないものは、製品レベルとして使えない
Andrew Koenig のC Traps and Pitfalls「Cプログラミングの落とし穴」、
組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド、2006、MISRA‐C研究会
こういう本を読んでいないだろ 書いてはいけないが、読める必要はある。
目を背けるな 「おやつは300円以内」のようなくだらねえことが延々書き連ねてある
ツッコミどころ満載なやつ馬鹿馬鹿しくて相手してらんね >>324
いろんなスレでNG推奨と言われてることから目を背けている奴に何を言っても無駄だろう プログラミング以外のところでも「俺様が知らない言葉を使うな」という痛いやつがいるのと同じ >>327
IOCCCのルールを守っていないからだろ >>327
何をやっているのか努力しないと読めないのが辛いです、そういう曲芸を仕事でやられたらボロクソなのも仕方がないとおもいますね >>327
型キャスト使わなくても型を合わせばいいのに。
ループ変数がcharってありえないでしょう。 >327
単純にソースの目的がわからない。
バイトオーダ(エンディアン)の確認?
{{ ... }/*コメ*/}というコーディングもなんかキモイ。 レスありがとうございました。
>>327は、
https://medaka.5ch.net/test/read.cgi/prog/1625843192/
というスレで、初心者の1が質問を投げるとこから始まります。
入力された文字を逆順で表示したいという内容です。
それで1が貼ったコードを巡り、いつしか省力化の流れになって、
そして投下されたのが>>327です。 なるほどなあ
とりあえず文字列としてしか使われない領域に意味ありげにint配列使ってるのと、バイトオーダーに依存している、の2点が最大のクソポイントか >334
>{{ ... }/*コメ*/}というコーディングもなんかキモイ。
Chromeのせいか?
なんか変な文字化け(変換?)起こしてるっぽい。
>char len,i;
が char len、i; ってなるとか。
FireFoxで開いたら正常表示された。
>335
>入力された文字を逆順で表示したいという内容です。
把握
>327
>Stdin
>abcdefg
7文字ってことは
>printf("%c%c%c%c",...
の最初のループの1文字目は "\0"が出力されてるのかな?それでいいのか?
int t[25];が0クリアされてるならいいけど、
ゴミが残ってると正しく表示されないんじゃないか? バイトオーダー決め打ちなのと
sizeof(int) == sizeof(char) * 4 前提にしつつ 4文字づつパックで処理してる工夫なんだろうけど
わざわざ難しくしてってのおふざけ暴走が生んだ結果だな >>327
それって入力した文字をただ出力したいだけ?
なんでそんなに複雑に書いたの? あ、逆順に出すの?それにしても複雑怪奇だなあ。どうしてそうなった? >>335
そっちのスレにまともなやつのURLを貼っといた。 わざと複雑怪奇に書く遊びはC使いの古来の文化だよ
有名サイトだけど
https://www.ioccc.org/ char型のiをわざわざintにキャストしてるのは何か理由があるのか
最初からintでiを定義しておけばいいのに 8ビットを、32ビットに変換するのは汎整数拡張
実際のCPU でも、8ビットでは処理できないので、
32ビットに変換してから処理して、8ビットに戻す
つまり汎整数拡張は、ほぼ無害 処理系によってcharがunsignedだったりするから
ライブラリのポーティングでえらい目にあったりするのよね MISRA-C でも、単なるchar 型は使用禁止。
-128〜127 か、0〜255 か、どちらか分からないから
signed char か、unsigned char を、明示して使わなければならない。
または、int8 か、uint8 char「我をたたえよ」
「チャー!」「チャー!」 あれは「チャー」って叫ぶのか?「キャー」じゃだめなの? 語源というか原形は character でその綴りを縮めたのだと考えれば、
(そしてあえて発音をカタカナに当てはめようとするのであれば)
キャー、もしくはキャラが順当なんじゃないかな。 欧米人なら letter を使いそうなものを、それを character(=象形文字系統)としたその心が知りたい‥‥どうでもいい話ですみません characterはcharと略せるけどletterは略せないとか?
一文字でも縮めることにやっきになってたみたいだし
charは「きゃら」だけど、enumを「いなむ」って言っちゃう
enumerateは「あにゅむれい」なのに 性格,性質,気質,特質,特性,特色,人格,品性,高潔さ,正直さ むこうの語感的にletterだとアルファベットだけで数字とか記号を含めないかもしれない >>358
letterだとletになりそうだから嫌ったんだろ いっそのこと単に byte とでもしておけばよかったのかもしれない。 >>364
char8_t ですね
bool が int も無駄が多い 歴史的に char と byte はどっちが先なのかな >>368
もうずいぶん昔だけど「キャラクター」とか「インテジャー」とか省略しないで呼んでたぞ
今は「チャー」なんか >>359
enumerate の頭の音はグーグル翻訳だとエに近い発音に聞こえるけど
weblio だと明瞭にイに聞こえる。 >>371
英語設定でググってみるといいよ
チャー派とカー派がいてチャー派が優勢のように見える。
reddit見るとお前ガンダム見たことないんか?シャーーー!とかlisperが混乱するだろがってコメントがあってワロ プログラムを書くのに読み方なんて意味が通じればどっちでもいいやん 初心者です、stdio.hの保存場所が知りたいです
Visual Studio Communuty 2018を使っており、標準ライブラリはインクルードディレクトリに指定された場所にあるということでした
プロパティでインクルードディレクトリを確認したところ、以下のようになっていましたが意味が分かりません
$(VC_IncludePath);$(WindowsSDK_IncludePath);
変数になっているようですが、どこかで確認できるのでしょうか? 間違っていたらごめんなさい
その $() で囲まれた文字列をコマンドプロンプトから
echo %文字列%
として表示される文字列はどうでしょう その値のところをクリックして<編集...>を選べば評価された値が見えると思う
その画面の右下の「マクロ>>」ってボタンを押せば使われてる変数の値も見える
上の構成がDebugかReleaseかで値が違う変数もあるけどIncludePathはたぶん同じ
2019で確認したから微妙に違うかもしれない echo で確認する方法は、その環境下でなければ
なので、別にコマンドプロンプトを起動してではダメですね >>378
>>379
ありがとうございます、確認できました!
Visual Studio実行環境でこれらの環境変数が追加されているイメージなのですね VSインストールすると環境変数セットするバッチファイルが入って来たと思うが、今は違うのか?
古い知識で済まん 実は VisualStudio は初心者向けじゃない visual studioが覇権取ってからプログラミングが嫌になりました・・・
プログラミングが嫌というかvisual studioの設定とか使い方とかそういうのを覚えるのが・・・
LSI C+メモ帳で良かったのに・・・ LSI C(試食版)は16ビットコンパイラでしかもSmodelしか作れないから
64ビットWindows環境で動かすのは無理じゃない? ……Visual Studio Community 2018なんてあったっけ? vs2019 と cuda の相性が悪かったが治ったのなら起こしてくだしあ 素朴な疑問でprintfでdouble型を表示させようとしたとき%lfでなく%fにする理由なんですが、
floatを引数とするとdouble型にキャストされるので、printfではfloat型もdouble型も同じ%fと記述すればいいことになっている
と言う理解で合ってますか? >>390
あってる。
printf ではというか可変長引数では既定の実引数拡張のルールで float は double に拡張されるから区別しようがない。
よくわかってないやつが %lf って書いちゃうから C99 から仕様に入れることになったみたいな話だったはず。
(逆に言えばそれまでは無かった。)
でも引数に double を与えるつもりなら意味的にそれがわかるにこしたことはないので、
人間が読み書きする都合を考えるなら積極的に区別したほうがいいと思う。 >>387
64で16bitモード使えないのは単なる嫌がらせ
技術的に本当はできるのに拒否してる
必要ならVM使うといい
過去バージョンは↓で入手できる
https://winworldpc.com/library/operating-systems >>394
なかなかオモロイサイトだね
спасибо! >>390
>>392
整数の基本型がintであるように、小数の基本型がdoubleだから。
そもそもdoubleっつー名前が良くないと思う。いまのdoubleをfloatにして、いまのfloatをsingle floatとかshort floatにすれば良かったのに… 年代的に元々floatが標準のつもりだったんだろうな >>396
倍精度ってのを表したかったんだろうな。 >>396
>小数の基本型がdoubleだから。
その理由は%fがdoubleだからというトートロジーでない? 計算自体は倍精度でやっていて、floatの場合結果を丸めてるの? そもそも
> 可変長引数では既定の実引数拡張のルールで float は double に拡張される
って言うのがよくわからん
普通にfloatはfloatのまま渡しゃいいじゃんと思うんだけどなんか理由あったのかな? 引数の受け渡しにスタックを使う場合でもレジスタを使う場合でも
ワードサイズより小さい型はどうせそのワードサイズに調整して積むことになるので切り詰める意味がない。
(ワードにたくさん情報を詰め込むことも出来るといえば出来るけどかえって非効率になる。)
だから int より小さい型を int に調整するというのはハードウェア的
な都合が反映されていると思う。
昔は浮動書数点演算ユニット (FPU) は CPU の外に持っているのが普通だったんだが
その時代でも FPU のレジスタは大きめなサイズを持っていた。
double が収まるレジスタがあるなら double で受け渡すほうが都合が良かったんだろう。
※ この場合の「ワード」は2バイトという意味ではなく各アーキテクチャにおける基本サイズという意味なので注意 ん、8087由来のサイズになってるのはlong doubleだろ long double って表現がもう頭悪いよね・・・ %lfはどう見てもlong floatだね
%dはint用にしちゃってるから仕方なかったのかな >>405
ダブロン って表現だとゲンが悪すぎるだろ・・ >>403
>その時代でも FPU のレジスタは大きめなサイズを持っていた。
80bit でしたっけ、そのうち仮数部が何ビットだったかは思い出せません 符号部1ビット+指数部15ビット+仮数部64ビット Rustのメモリ安全性はボローチェッカーによって担保されているが、
Nimと比較してRustはタイプ量が多い事により限りなく低い生産性と
C++のような高い難読性、超巨大なバイナリ生成性能を兼ね備えています
Nimはバージョン1.5.1でRustのボローチェッカーに似た「View types」が実装されれば、
GC無しのView typesで参照の有効性を検証することによってメモリ安全性を保証しつつ
限りなく抑え込まれたタイプ量で高速化したCのソースコードを吐き出せます
Nimソースコード ==nimコンパイラ==> Cソースコード ==Cコンパイラ==> バイナリ
なので、nimコンパイラが通った時点でメモリ安全性が担保されませんか?
Nimの実験的特徴
著者: アンドレアス・ルンプ
バージョン: 1.5.1
http://nim-lang.github.io/Nim/manual_experimental.html
Nimは限りなく抑え込まれたタイプ量で高い生産性とPythonのような高い可読性を実現し
ているにもかかわらず、高速なCのソースコードを吐き出せるのでC言語でリモートワーク
されている方は割り振られた仕事が早く終わっても終わってないふりをして怠けることができる
「怠け者とはこうあるべきだ!」と言うとても大事な事を Nim は我々に教えてくれます pythonを可読性高いという時点で眉唾だな・・・ char *b = "0123456";
printf("%x\n", 3[b]);
// 33
これって、どうしてこういう書き方 3[b] ができるんだっけか
シンタックスシュガーとかじゃなく、明確な理屈があって出来ちゃうんだよね? >>412
いやあ、それ、シンタックスシュガーでしかないと思うが。
[の左側+[]の内側で計算した結果をポインタ扱いにするってだけなので。 >>413-414
ありがとうなるほどそーいう理屈なのか
素晴らしいです。 全てを理解していきます 標準でもそのまんまだなぁ
> A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object.
> The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
> Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero). 余計なお世話になるが
printf("%x\n", 3["0123456"]);
これでもいいんだよな 脱線するけど、そもそもCでこの書き方できたのか
printf("%x\n", "0123456"[3]);
なんかできないと思い込んでた。 Cはなんでもできるんだな IOCCCの黎明期ならマウントとれたネタだね
今ドヤるやつはプークスクスされるだけ stack領域で確保したポインタをfreeしたらどうなるんですか? >>419
> printf("%x\n", 3["0123456"]);
はともかく
> printf("%x\n", "0123456"[3]);
は実用でもそこそこ使うだろ
4bitの数値を16進数に変換する時に
"0123456789abcdef"[i]
ってやるとかは定番 >>421
酔ってるからかもしれないけど、質問の意味からして分からない
実装によるだろうけど、動的に確保されるオブジェクトはヒープに確保されるだろうし
黙ってれば確保したメモリへのアドレスを保持するポインタはスタックに置かれるし
実装によるけど >>422
定番って言えそうなほど使われているソースを見たことないなあ。 >>421
alloca()でメモり確保した場合のことを言ってるの?だとすればfree()しちゃダメだよ。やってしまった場合にどうなるかは使っているライブラリによるんじゃないかな。そういう呼び出しを想定していないライブラリだと落ちるかも知れない。 >>424
未定義のこと。
C における未定義は何が起きても構わないことを意味する。
あるときネットニュース上でそれを説明するやりとりがあって、
あらゆることが起こりうるという例として鼻から悪魔が出てくる
ことも含まれるというような言い回しが使われた。
https://groups.google.com/g/comp.std.c/c/ycpVKxTZkgw/m/S2hHdTbv4d8J
それが定着して未定義のことを鼻から悪魔というのが通例になっている。 >>426
ちょっとググればすぐに出てくるぐらいには使われてる
char hex_from_nibble(unsigned char n){
return "0123456789ABCDEF"[n & 0xf];
}
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13162097918 >>421
やってみろ
ほとんどの場合は何も起こらない >>421
スタック…と言うかmalloc(calloc/realloc)で確保したポインタ以外をfreeすると何がおこるか判らない(鼻から悪魔)。
実際の話だと、大抵の実装ではmallocは確保した領域に管理情報を埋めて返し、freeはその管理情報を見て解放処理をする。この場合、管理情報がデタラメになるのでメモリアクセス違反でプログラムが落ちる事が多い。 freeは何もしないことも許される、なんて言って呼び出しそのものを否定するやついたな昔 ほとんどの場合は、無人の荒野を爆撃するだけだろうが
いつかは住民が住んでいるところを攻撃するぞ 僕はc言語自体初心者だったのですが、stack領域で確保したポインタをfreeするというのは以下のコードを指すつもりで言ってました。
int a;
free(&a);
鼻から悪魔が出るというのは未定義動作になると言うのを言うんですね。また一つ勉強になりました。 ポインタでもないし、何をしたいかが分からん
この時空を破壊したいなら、もっと考えてからにして >>422
俺は愛を信じないので、そのコードはちょっと怖いかな
範囲内という前提があるだろうけど、なんかはみでそう >>435
ポインタとアドレス同じ意味で使ってます >>434
ちなC++触りだすとスコープ{}内で宣言したものはスコープ出たところで
勝手に始末されるちゅー理屈で実装することも増えると思う。
でかい一時配列とかスタックに置きたくもないしいちいちfreeとかdeleteのこと考えたくないから。
変な所でreturnとかしたらfree忘れちゃう。C言語だとその辺は厳格にしないといけない。
あと、ローカル変数のアドレスをあまり気安く使ってると、そのうち関数抜けて廃棄された
アドレスを参照してしまうバグをだしちゃうかも。一度位は通る道かもね。 >>433
中國のロケットの落下騒ぎを思い出したわ ポインタはアドレスを格納する変数
&aはアドレスだが変数ではないのでポインタではない >>442
いいえ。 ポインタ型の値がポインタです。 (See C99 6.2.5)
C の用語ではメモリ (ストレージ) を占めるものがはオブジェクトで、それを型で意味付けしたものを値 (value) と言います。
実体としては同じですがレイヤによって呼び方が変わる場合があり、アドレスとポインタの違いも同様のものと考えられます。 >>442
何年か前にも見た覚えのある言説だな。元は何だろう? int *p; // ポインタ変数またはポインタ
int a;
&a; // アドレスまたはポインタ
int b = &a; // bはアドレス値の入った整数
int *c = &a; // cはポインタ
こういうこと?
アドレスとポインタは明確に区別されてるの? int a;
int *b;
b = &a;
&a = b; >6.5.3.2 アドレス及び間接演算子
>単項&演算子は,そのオペランドのアドレスを返す。オペランドが型“?型”をもっている場合,結果は,型“?型へのポインタ”をもつ。
だからアドレスとポインタどっちでも良いんじゃないの &aはint*型のアドレス値(右辺値)で、変数ではないから代入は出来ない。
言葉の厳密な定義は知らんが、自分はポインタは型に紐付いたアドレスと理解してる。
組み込みなんかで
uint32_t a = 0x4020000;
...
*(int*)a = 1;
とか書くけどa自体はただの整数値だしね。 >>448
int a=51; // 中山美穂の年齢
&a; // アドレス
(int*)&a; // ポインタ
*(int*)&a; // 中山美穂の年齢 アドレスも年齢も表現の対象
ポインタとintが型の名前 ageMipoとioDirectionがアプリケーションハンガリアン
iMipoとpDirectionがシステムハンガリアン 言語仕様の文面の上ではアドレスとポインタの区別ははっきりしないので同一視してもかまわないとは思う。
少なくともポインタという用語がポインタ型の変数を指すという主張には賛成できないというだけ。
ただ、言語仕様の範囲内ではそれでいいんだけども言語仕様の範囲外というか実装上の理屈では区別している場合がある。
言語仕様上はポインタの比較は同一の配列 (または集成体オブジェクト) 内の要素を比較した場合や
ヌルポインタとの比較についてしか定義されておらず、それ以外は未定義であると明記 (C99 6.5.8 参照) されていて
関連のない場所のポインタの比較であることが静的に把握できるときは定数に置き換える最適化が適用されることもあるんで
アドレスを比較した通りの結果になるとは限らない。
https://wandbox.org/permlink/SqW5wzZM3fD912Nh
そんなわけでポインタが素朴なアドレス (実体が整数値) だと思っていると思わぬ結果を生むことも有る。 気持ちだけは、俺も昔そう思いたかったことがあるけど
JIS X3010ではそうなっていないので、その気持ちはきっぱり捨てた int a; のときに &a+1 とかやると sizeof(int) 進むのね!
マジかよ知らなかった!
じゃあこの &a はほぼポインタだと思っていいのかな? いいの? >>456
int a;
と宣言されているとき &a の型は int* で、これを「int へのポインタ」という。
定義上ポインタとされているものに合致する。 aはint型の変数
&aは変数aをアドレス演算子&で評価した値
得られた値の型はintへのポインタ型int* >>456
例から少し外れるけど*(&a[0])に対して*(&a[0]+1)がおかしな場所指すと嫌だしな。 ポインタ型の変数→ポインタ、ポインタ変数
ポインタ型の値→ポインタ、アドレス
アドレス演算子の結果→ポインタ、アドレス
こういうことか そして配列 int a[5] から a は何者? 引数に渡すとどーなる? という深淵な所へ >>459
&aはアドレス演算子と左辺値からなる式
式が生じる結果には値と型がある > int b = &a;
ポインタ型の値を整数型の値に暗黙に変換して代入 >>464
gccでやったら注意された。g++でやったらガチギレされた。 >>465
g++なら
int &b = a;
でヨシ(良くない ポインタを整数値として変換した際、その値が int の範囲内に収まるかどうかは環境でまちまちやでねぇ >>467
厳密にはintptr_tだけど、大抵intで足りるでそ?
コンパクトモデル?知りませんなぁ
>>468
すまん、茶々でした わかってないのに短絡で int は危ないけど
LP64 やら LLP64 やら ILP64 やら
自分のがどうなってるかわかっててやるか、ポータビリティを鑑みて気を使った書き方するか ポインタのビット列を格納しきれる整数型が必ず存在する保証って箇条どこだっけ >>469
いまや大抵の環境でintじゃ足りないだろ。大丈夫か? >>471
6.3.2.3 では「結果は何らかの整数型の値の範囲に含まれているとは限らない」とあるし、
7.18.1.4 では intptr_t は省略可能であるともあるので保証はないと解釈すべきだと思う。 >>473
なるほど
これで (int)&a はダメなんてドヤってるやつは根拠を失ったなw >>474
馬鹿なの?主要pfのintサイズも知らないのかよ よしてくれ
直接的な罵倒語で話す次元のやつと一緒にすんな >>358
レターは文字の集合。キャラクターとしたのは文字として認識していない記号等を含めたため。 文字のことをキャラクターと呼び始めたのはC言語じゃねえよ。
13年前にできたCOBOLですらキャラクターと呼んでんだぜ? 俺に聞けって言われてもな
なに聞いたらいいかわからん
変に言語のマニアックな知識つけるより、アルゴリズム沢山知ってた方がいいと思うから言語や開発環境についてはvalgrindとかcmakeとか基本的なことを身に付いてればそれで十分だと思ってるわ
だからすまんけど聞きたいことはない C言語が1972年、COBOLが1959年
こういうことを言いたいのでは無いか? 子供の英会話聞いてるとletter aとか頻出するが、まだキャラクターは出てこないな。 キャラクターの本来の意味は文字じゃないんだぜ?
あたりまえなんだぜえ? >言いたいのでは無いか?
ここの「無い」に漢字を使うことに違和感感じるのは漏れだけ? 「〇〇ではないのか。」の「ない」は形容詞。
ただし、これは形容詞を代用した言い回しなので、「無い」とはっきり形容とわかる使い方以外の場合は、日本語のおかしさが出てしまうので違和感がある。
そもそもわざわざ「ない」を「無い」と書く必要がない。戦後教育では漢字で書かなくてもわかることは仮名で書くと決めて、学校では漢字で書かないよう指導しているのに、漢字で書くやつはそれをすっかり忘れているだけだ。 割とどうでもいい話だな
国語教育スレにでもうつってそこで続けてくれ >>499
それもネチネチ30年以上も言われたが、単に字面が醜いという話で終わった。
覚えるも感じるも同じ意味で使っている。日本語は同じ漢字が続くときれいに見えないので変えたくなる。 無いと言えばこの前ドイツ語の映画で Nein って言ってる時に日本語字幕に「無い」と出ていて一致していて笑った。 >>501
否定の言葉の発音がNで始まるのは人類共通 人類が言葉を話す前の拒否を表す叫びが言葉になったのだろう。 >>501
「無いん」ならもっと良かったw
>>502
韓国語だと、YESがネーでNOがアーニョ 離散データを連続データのように見せかけるフィルターを作りたい。
アルゴリズム名を教えてください。 >>502
フランス語には何故 pas があるの? >>510
neの発音が小さくて聞き取れないから付けることになった ( ・∀・) | | ガッ
と ) | |
Y /ノ 人
/ ) < >__Λ∩
_/し' //. V`Д´)/ ←>>514
(_フ彡 / 投稿するスレッドを間違えてしまったかもしれません。>>507
それ以後、いろいろ調べつづけましたが、
どうやら内挿法とか補間法とか呼ばれていることが分かりました。
そのためのアルゴリズムを探してみます。
ありがとうございました。 離散的なデータのプロットから滑らかな曲線を得たいのですが、
ベジェ曲線を使う必要があるため、それも計算する必要があります。
ではこの辺でさようなら。 与えられた離散的な点を必ず通る曲線なのか適度に近いとろこを通す曲線なのか >>522
必ず通るようにしたいです。最小二乗法のようなものじゃないです。 代入時など左辺に&をつけない理由って、元々左辺の変数はその変数のアドレスを示しているんですか? 左辺にアドレス値を書いても、そのアドレスに格納してくれるわけではない 変数は(多くの場合)メモリ上に置かれる
a=bの式をコンパイラは「bのアドレスのメモリにある値をaのアドレスのメモリにコピーする」と解釈する
でもそれをソースコード上で&a=&bと書かせてもお得なことはないよね
言語上では「a, bは(抽象化された)変数」で、その変数への代入は「a=b」でいいよね >>527
C++だと参照型が近いけど、あれはあれで窮屈ながらも、便利っちゃ便利かもな。
でもポインタ幅きかせてるCであえて拡張したい記法かといえば微妙よね。
void func(char &c) { c *= 2; }
みたいなのね。 皆さんありがとう
scanfで変数に&を付ける理由はいろんなとこに書いてあるんだけど、
それならなんで普通の代入の時に&を付けないんだ?
って疑問に思ってました void f(int *p)
{ *p = 1; }
….
int i;
i = 0;
printf("%d\n"); // 0
f(&i);
printf("%d\n"); // 1 scanfに限らず、関数に変数を渡すと、その関数は、
渡された変数の値を受け取れるだけで、
変数の値の書き換えは出来ません
書き換えて欲しいときは、書き換える場所を関数に教えます
普通の代入の時は、その変数を直接操作できるので
あえてアドレス表記する必要が無いです memcpy(&a, &b, sizeof(a));
なんてことを、昔々構造体の変数の代入が出来ないCのサブセットのコンパイラでやったことがあったような気がするが、もはや記憶も曖昧になるぐらいの大昔。時の経つのは早いものぢゃ。 サブセットつーか、そもそもK&R Cは構造体代入できないね >>531
int c;に対して&c = 100という記述はだめなのって疑問かな?
代入演算子は左辺に変数を置いて値を書き込む特別な演算子だけど、
それをその変数の型を含むアドレス値を左辺に置いてそのアドレスに
書き込むという定義とするわけだ。
定義自体がややこしいし、
アドレス全面押しにする理由がない(むしろ遮蔽したい)、
頻繁に用いる演算子ゆえタイプ数が増えたりするのは好まない、
などメリットがないのだろうね。
=と==を=にまとめてしまって、代入時は&付けるという方向は
あるかも知れませんが、コード中代入のが多いでしょうから、
代入をシンプルにしたのではと。 int c;
*(&c) = 1;
ていうのなら出来る。
コンパイラは何の警告も出さずにコンパイルするかも知れないが、結局 c = 1; をやっているのと同じコードが出力されると思う。 代入演算子の左辺に現れることが出来るのは変更可能な左辺値 (modifiable lvalue) で、
>>539 の例はその条件を満たす。
>>527
たとえば
int c = 1;
a = 2;
というのは C では有効なコードだけれど、変数を評価すると格納されている値になるというルールを
そのまま適用すると
1 = 2;
になってしまっておかしい、左辺は「場所」でないといけないという感覚はとても良い感性なのだけれど、
左辺がアドレスということにしたとしてもアドレスはポインタ型の「値」でしかないのでそれはそれで
なんだか変なことになる。
結局は特別な規則を導入必要はあって、 C においてはそれが lvalue という概念というわけ。 わざとやってるのか知らんけどコードくらいまともに書けよ >>531
C++は面倒なことになったな
#include <iostream>
using namespace std;
int main(int ac, char **av)
{
int a = 3;
int &b = a;
cout << a << b << endl;
return 0;
} >>532
誤>printf("%d\n"); // 0
正>printf("%d\n", i); // 0
いまさらですが、第2引数が欠落していました
失礼しました 副作用をポインタを経由して呼び出し元に伝播する ポインタ渡し
引数変数への代入がそのまま呼び出し元の変数に反映される 参照渡し(C言語には無い) 関数の壁(呼び出し元と 呼び出された関数内の記述)を超えるときに & を使って壁を越える工夫をする
同じコード内の変数への代入ならば不要 C の仕様では引数は一貫して値渡しで、その値の型がポインタ型のこともあるという理屈になってる。
(仕様の理屈はともかくポインタの活用の仕方としてポインタ渡しと呼ぶことを否定するわけではない。) ポインタ渡しだとポインタ変数限定みたいに捉えてしまいそうだなw 「アドレス渡し」の方がアセンブラに近い
ただしポインタ型のサイズで加減するアドレッシング機能付き
「ポインタ渡し」はPASCAL由来やろ
あと配列のサイズも一緒に渡す機能は付いてたらよかったのになーともたまに思う ポインタには型があるから、オブジェクトの大きさも、structへのポインタなら、各メンバへのオフセットや大きさやら… カーニハンは辛辣なPascal批判の論文書いてるね >>556
論文って開いてみたら、タイトルクソワロタ。 アドレス私って、
b = a;
c = a;
とかやってて、a=0にすると、bもcも0になるってこと? それは参照だ
C++のな
Cでやるなら
#define b a
#define c a >>557
Matz の論文は I hate C++ だぞω >>556
性能重視の部分は考え方の違いだな。UNIXを作るにあたって不要な部分を取り除いた結果がC。 >>560
メモリのアドレスを直接、渡すから、呼び出し元の領域をそういうふうに直接、触ることになる。 Delphiは昔使ってたな。拡張しまくったPascalというかなんというか。 アセンブラのようなことができた方がいいというのが出発点だからなあ 今でこそ C は低レイヤ寄りと見做されるけど「高級言語で OS を書きたい」というモチベーションから作られている。
おそらく当時の感覚からすればむしろアセンブラ的な世界からの脱却だったんじゃないかな。
歴史的経緯はある程度は記録を辿れるけど時代を背景にした「感覚」というのは現代人からはなかなか掴みづらくてあくまでも想像だけど。 おおざっぱに言うとアセンブラの見た目を変更したのがC アセンブラの無駄のなさと、高級言語の移植性の、両取りを狙う試みだね それはどうでしょうか‥
turbo c の asm 文抜きのいきなりインラインはよく使っていましたが、そんな turbo c でもキャリーフラグを直接使えなかった気がします、そんな記憶がふつふつと ローテート命令はキャリーありの9bit循環とキャリーなしの8bit循環があるから
そこまで言語では面倒見きれなかったってだけ
ステータスレジスタを陽に記述すると移植性なくなるが
そんなことしなくても当時のUNIXの95%を記述できたしな #ifdef flagresister取得可能(ならば)
専用式
#elseif
~ みたいな専用式を言語仕様に含めたやり方も出来たかもしれん
当時の演算能力内でwrite once,RA かつアカデミック感目指してomit しちゃったんかな Keep the language small and simple. >>571
そもそも世の中にはキャリーフラグなんてないプロセッサもあるから
俺の知る限りキャリーフラグを扱える高級言語はTL/1しかない >>576
そうなんですね、なんちゃって多倍長をやっていて、ここでローテート&キャリーが使えればなぁぁぁ、とつくづく >>576-577
TL/1 はあくまでも演算子がキャリー/ボロー付き演算の命令にそのままコンパイルされるってだけなんで、
配列アクセスなどのときに勝手にアドレス計算でフラグが設定されてしまうといった意図しない影響があって
あまり使い勝手は良くない。
あまり詳しくないけど LLVM はキャリーフラグを扱う方法があって
かつレキシカルな伝播として記述できたはずなんで、
たぶん LLVM IR でならなんとか記述できるんじゃないかな。
LLVM IR を高級といえるかどうかはたいへん微妙な話だが……。 >>578
例えばこんなを高級言語って言う?
define i32 @main(i32 %argc, i8** %argv) #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i8**, align 8
store i32 0, i32* %1
store i32 %argc, i32* %2, align 4
store i8** %argv, i8*** %3, align 8
%4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0))
ret i32 2
}
>>579
ごめん、意味分からん
単なるVTL (Very Tiny Language) の話にしか見えない >>580
そこから様々なターゲットの機械語を生成しうるという意味では
ハードウェアにベッタリと紐付いているわけではなくて
LLVM IR を低水準言語と呼ぶのはなんか違うなって思うけど、
だからといって日常的に人間が直接書くことを前提においてるわけでもない
という点では高級とも言いにくいかな……という意味で「微妙」と評した。 シリコンバレーで働いて気付いた「技術力向上」だけに固執するエンジニアのダメさ【Sansan CTO 藤倉成太】
https://type.jp/et/feature/9402/
DeNA×メルカリ×サイバーエージェント人事担当が面接で必ずする質問とは?「技術力だけアピールしても内定は出ない」
https://type.jp/et/feature/10236/
DeNA・メルカリ・CA人事が証言! スキルはあるのに“面接で落ちる”エンジニアに足りないもの
https://type.jp/et/feature/10402/ >>582
> そこから様々なターゲットの機械語を生成しうるという意味では
> ハードウェアにベッタリと紐付いているわけではなくて
Javaのバイトコードを高級言語って言うの? >>584
JVM のバイトコードは言語ではないと思うから高級言語とは言わないけど、低水準でもないでしょ。 低水準の話はしてないから
> 高級言語とは言わない
でFAやね >>580
特定CPUのアーキテクチャに言及してないな 宣言と定義についてなんですが
int a; // 宣言
int b = 1; // 定義
宣言と定義ではどちらもメモリ(スタック)は確保されているという理解であってますか? >>592
変数宣言のうちメモリを確保するのもが定義。
その2つは両方とも宣言であり定義でもある。 >>592
いいえ
定義では格納場所を確保しますが、宣言では存在のみ指示しても格納場所は確保されません、私は気が向けば宣言には extern をつけるようにしないわけではない、という感じかな
なおその例は少し変で、代入を伴えば定義というわけでも、代入がなければ宣言というわけでもない、というのが個人的感覚です、詳しい人の解説を希望します
例外は、リンカが頑張って格納場所を作ってくれる例の何とかとかいうキーワードがあったのですがおもいだせません、今日モデルナを射った後転んで頭を打ってしまった、結果、いっそう馬鹿になってしまいました‥‥ >>592
宣言か定義か、という問題は、単一モジュールでプログラムを構成している段階ではあまり気にしなくてもいいと思います
複数の c ソースを分割コンパイルし、最後に得られたオブジェクトをライブラリともあわせて結合する、という作法に進めば自然に理解できるようになりますのでご心配なさらなくともいいでしょう
私も昔は「extern は要らない子!」とか馬鹿をいっていましたが、これは撤回します、extern がどうしても必要な場面に遭遇したのです
まあそういうわけで一度にいっぺんに賢くなるのは私には難しいことのようです >>598
たとえば
int a;
printf("%d\n", a);
なんですが、この場合のaは定義されているということですか?
代入式があるのが定義だと思ってました
宣言と定義の文脈はコードによって変わるということなんですかね 簡単に言えば宣言はその名前をコンパイラに伝えるもの
定義はその実体を確保するためのもの
>>592の例は両方共に宣言であり定義でもある
C言語では定義のみすると言うのはできないと思う
宣言のみはexternとか前方参照のためのstruct xxx;とかで使われる ..>>597
「下位概念」という言葉をあてるのは不自然な気がするけど、C言語において定義は宣言のサブセットだよ。
>>600
その2行がコンパイルできる文脈に置かれているなら、 a は定義されている。
(初期化されていない自動変数になるので後続の printf での読み取りは未定義動作になるけど。)
「宣言と定義の文脈はコードによって変わる」は意味が分からないので否定も肯定もできない。
同じ int a; といった記述が宣言か定義か文脈によって変わる、ということならありえる。(構造体メンバの宣言とか。) >>601
>>603
メモリが確保されているかどうか?という点で定義か宣言か判断すればいいということですね
printf()で参照している場合はaはメモリが確保されているのでaは定義されている状態
printf()で参照しない場合はaはただの宣言になると >>604
レスの後半はいらないよ
参照されるか否かは関係ないよ
int a;
で定義は完結してるから >>604
> printf()で参照しない場合はaはただの宣言になると
違う、参照の有無に関わらず領域は確保される
最適化とか鼻から悪魔のコードだから確保を端折るとかはあるけどそれはまた別な話 >>605
>>606
理解しました!
int main(void) {
int a;
return 0;
}
↑のaは定義されていてメモリが確保されている状態ってことですね
また定義は宣言のサブセットだから、この状態を宣言と呼んでもいいということですね aは定義されている、でよいと思います
ちなみに、自分は宣言とか定義とか「言葉」は意識しないです
ただ、ここにオブジェクトが実在するのか、他のどこかにあるオブジェクトを使うのかは明確に意識しなければなりません
int main(void) {
int a;
extern int x:
return 0;
}
ここで xは、関数外のどこかで定義された int型のオブジェクを参照します、という宣言 >>607
そうですね
それに、そのコードは関数 int main(void) も宣言かつ定義していますね
関数の場合は、関数の中身が書いておれば宣言かつ定義、関数の呼び出され方だけしか書いていなければ宣言、とすぐにわかるので、キーワード extern は省かれる傾向にありますね
詳しい人に解説いただき私も感謝します 質問
externを関数内で宣言したとき、有効範囲は次のどれになりますか?
1.宣言した関数のスコープ内で有効
2.宣言したソースの後続行で有効
3.宣言を書いたソースの全体で有効 通常の変数と同様に、ブロック {} で括られるかと JISX3010:2003 の 6.7 から抜粋
> 宣言は、幾つかの識別子の解釈及び属性を指定する。
> 識別子の定義 (definition) とは、宣言のうち次のものをいう。
> ・オブジェクトに対しては、そのオブジェクトの記憶域を確保する宣言
> ・関数に対しては、関数本体を含む宣言
> ・列挙定数又は型定義名に対しては、その識別子の(唯一の)宣言 関数の中とか{}ブロックの中とかで
#include とか #define 出来れば良いのにと思うことはある
(いや出来ることは出来るけど) >>610
>>611
2だったような
1の方が合理的だが // foo.c
#include <stdio.h>
int f(void)
{
extern int glob:
return glob + 1;
}
int main()
{
printf("%d\n", f()); // 124(次行がないとき)
printf("%d\n", glob); // エラー
return 0:
}
// bar.c
int glob = 123;
でした
勘違いだったらごめんなさい int f(void)
{
__{
____extern int glob:
__}
__return glob + 1; // glob undeclared
} extern の変数をスコープ内に書きたい場面ってあまり思いつかない。
ヘッダファイルに書くのサボりたい時くらいしかそんな書き方しないな〜 >>620
>>608だけど、(関数スコープ内の)宣言のうまい例を思いつきませんでした
自分でもこのような記述はしたことがないです
>>614
ブロック内でも、#includeや#defineは使えるには使えるのでは
使ったことはないけど
ただし、#defineは同じスコープ内で #undefで閉じておかべきだけど
リーダブルコードという本で、define〜undefの例を見たような >>620
俺はそのスコープでしか使わないなら普通にスコープ内に書くけど? >>614
「できるにはできるけど」と、ちゃんと書いてありますね
大変失礼しました、ごめんなさい!! ひょっとして、#define も関数内で記述すると
そのスコープ内で有効になるのかな? #includeとか #defineとか、プリプロセッサが処理する時点では、スコープとか、C言語の文法すら関知しないかも
トークンの
識別くらいで こんな #define 見たくないけど・・・
---------------------------------------
void func() {
#define A 100
}
int main() {
int i = A;
}
---------------------------------------
gcc -E prepro.c
---------------------------------------
# 1 "prepro.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 384 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "prepro.c" 2
void func() {
}
int main() {
int i = 100;
}
--------------------------------------- namespaceが欲しいのにC++を使わないのが逝けない娘
太古の昔、Cにクラスが無いのが逝けない娘だと思った人とは行動力が違いすぎるな CはCのままで良い。他の言語で実現出来ているんだし。その機能を使いたいならそちらの言語を使えば良い。
それでは何かが足りないというのなら新言語作れば良い。
自分では作る技術力がなくても仕様を考えてネットで公開しておけばやがて暇と技術力のある誰かが作ってくれるだろう。 >622
型を間違えてもエラーにならないから全くお勧めしない ミスする可能性が上がるから各コードでexternせずに必要ならヘッダに書いてもらえってことじゃね?
そもそもexternなんてextern "C"以外滅多に使わないけどな >>633
前スレより
975 デフォルトの名無しさん (ワッチョイ b363-19dE) sage 2021/06/21(月) 23:06:35.04 ID:jHz8GYW10
// b.c
int b[] = {123, 456};
// a.c
#include <stdio.h>
int a[] = {123, 456};
int main()
{
extern int *b;
printf("val b\n");
printf("%d\n", *(b + 1));
// printf("val a\n");
// printf("%d\n", *(a + 1));
return 0;
}
こういう分割ソースをコンパイル、リンクして実行すると、何も表示無しで終了する
デバッガー使って実行してみると、SEGVになってる >>634
>ミスする可能性が上がるから各コードでexternせずに必要ならヘッダに書いてもらえってことじゃね?
そうそう、extern による宣言と定義とが食い違うとエラーがでますから、そのためのヘッダの分離ということですね
>そもそもexternなんてextern "C"以外滅多に使わないけどな
関数の宣言は extern 省略可能ですし、ライブラリ側で共用のメモリを確保することは滅多にないです私は >>635
これは関数のスコープに書かなくても(ファイルスコープでも)同じじゃない? >>635
これってリンク時にエラーにする方法はないのかね….
あればとっくにやってるんだろうけど… >>637
同じですね
そもそもexternを明示的に書く必要がある状況って、
あるソースで定義されているグローバル変数を他のソースに公開して使えるようにするために、
ヘッダにextern int a;のように書いておいて、他のソースにはそれを#includeさせる
(すると他のソースでは余計な領域が確保されない)
のパターンが基本だと思っています
だからそもそもブロックスコープでexternするのってなんで? 覗き魔? って思ってしまう ブロックスコープ内でexternはK&R C時代の名残で今は完全に無意味 関数原型でのexternは単項プラスみたいなもん
staticじゃないよと強調する反対語 >>639
>ヘッダにextern int a;のように書いておいて、他のソースにはそれを#includeさせる
「他のソース」でないソースも、そのヘッダを #include しておけばダチェックにもなるし >>639
ヘッダに実体がある糞コードで
でも直すなって言われて仕方なくexternすることはあった // b.c
char a[] = { 0, 1 };
// a.c
int main()
{
__extern int *a;
__printf("%d\n", a[1]):
__return 0;
}
不勉強でした
上のコードは警告もなしにコンパイルが通りますね
実行すると segmentation fault ですが
リンク時はデータ型はチェックされず、名前だけで参照を解決してるのですかね……
古い仕様で、今さら変更はできないんでしょうね、チェックができたとしても 型システムを持たずラベルの綴りのみを手がかりに参照解決するリンカを操るツールの1つだからねCは
リンカにあれもこれもと機能を持たせるのはメインフレームのファイルシステムにあれもこれも持たせようとしたVSAMの再来だ
インフラ的なものにアプリの都合を無闇に押しつけるべきではないことを歴史から学ぶべきだぞ C には「プロトタイプ (関数原型) を持たない関数宣言」があって、
関数の型が曖昧なまま関数が存在することだけを宣言できる。
プロトタイプ (プロトタイプ宣言) がある場合にはその関数を呼出すにあたって実引数と仮引数の間では代入と同じ規則
で (可能な場合には) 暗黙の型変換が適用されるが、プロトタイプがない場合には
既定の実引数拡張 (可変長引数に実引数を渡すときと同じ規則) が適用されて実引数と仮引数の辻褄が
あってないときは未定義という扱いになる。
更には C89 は暗黙の関数宣言という規則があって (C99 では廃止されている)
関数を呼出そうとした時点で関数が宣言されていない場合には実引数の型から一定の規則に基づいて
関数の型を推測し、関数が宣言されたかのように振る舞うことになっている。
なので関数宣言が存在しなくても二度以上の関数呼出しの型に矛盾があれば検出はされる。
もちろん関数定義の実体と辻褄があってなかったらそれは未定義だけど。
このあたりのクソみたいな規則は「C++ では採用しなかった仕様」として D&E でちょっと触れられてる。 > 実引数の型から一定の規則に基づいて関数の型を推測し
func(1);
↓
int func();
func("string");
↓
int func();
こうなるだけで推測なんて気の利いたことはしないよ プロトタイプ宣言は C++からの逆輸入だからな….
その昔の Cったら >>647
あ、ほんまやな。
仕様上のルールは「extern int func(); が書かれていたものとみなす」というだけで、
具体的なチェックをどこまでするかは処理系次第 (たぶんあまり真面目にやってなかったと思うけど) だな。 >>648
> プロトタイプ宣言は C++からの逆輸入
そうなの? The C programming language (いわゆる K&R 第一版) の
APPENDIX A 8.3 Declarators を見る限りでは
引数リストが空の形式しかないように見える。
関数であるということは宣言できるが型チェックはガバガバっぽい。
D&E の 2.6 静的タイプチェック の項では
> C with Classes のシンタクスとルールはその後 ANSI C の規格にも採用されたが
> C with Classes の最初の実装の時点ですでに完全な形をしていた。
という一文があるので C の型チェックは C++ (の前身である C with Classes)
からの影響ということで間違いないと思う。 >>644
そのコード、仮に a.c で
extern int *a;
ではなくて
extern char *a;
であってもセグフォが出ると思います、試してませんけど‥‥
なにか二重に勘違いしてませんか?それとも私が二重に勘違いしているのか? >>655
配列として定義したものをポインタとして宣言するのは間違いだな。 >>655
ありがとうございます
はい、char と char でもダメですね
データ型がことなれば、リンケージできないのではと思い実験してみました
定義側でメモリに配置されているのは値で、extern宣言で参照する側が期待するのはポインタが配置されていることなのでうまくいきませんね(違うかな) >>638
変数に対しても型情報付加したマングリングするぐらいかねぇ? >>661
アセンブラがリンクできなくなるからヤダ >>657
thx a lot !
日本語訳は太古の昔から有名どころ、ただし C89 の話だったかも http://www.kouno.jp/home/c_faq/c6.html#0 >>658
ほとんどプロの人‥‥完璧なアマは私くらいですか COFF フォーマットを見てるんだが、
関数が返す値の型を格納するところは有っても引数の型については無いみたいだ。
http://delorie.com/djgpp/doc/coff/symtab.html
ヘッダファイルで型情報をやりとりする前提なんだな。
ELF だとたぶん詳細な型も入れられそうな雰囲気があるんだけど複雑でようわからん……。 もしかしてc言語って新たにブロック文つくったら構造体の二重定義って可能になるんですか?
試しに
{
struct a{};
{
struct a{};
}
}
ってcompiler explorerで打ち込んだらcompile通りました。
こんなの初耳です。
ちなみに同じブロック文で二重定義したらcompile errorが起こりました。 >>659
今回の例でもわかるように、無節操にバンバン extern 宣言を複数の C ソースファイルのあちこちに混入させるのは非常にマズイので、
普通はサブモジュールの extern 宣言だけを別のファイルにまとめておいて、そのサブモジュールを使用するソースで #include するのが標準的です
この extern 宣言だけをまとめたファイルを特にヘッダファイルと呼びます
https://ideone.com/rdbae2
実体を定義したサブモジュールもヘッダを #include するようにしておけば、ヘッダの誤りも検出することができます
なにかこういう基本文法を終えた後に位置するべき基本的な作法集をまとめたアドバンス教科書、みたいなものはないものでしょうか? >>667
ありがとうございます
>>659 == >>621 です
621にもあるとおり、僕もこのような extern宣言を使用したことがありません
他に変数の宣言の例が思いつきませんでした… >>666
使い道はわからないけれどもできるようですね‥‥無名構造体・異ネスト同一識別子で試してみました
https://ideone.com/eXiadC >>669
レスありがとうございます
確認してみましたが
この例でなされてるのはdeclarator中の構文要素であるidentifierの例であって、>>666でなされているようなstructトークンとleft-braceトークンの間にあるidentifierを同じのを二度使っている例にはなっていないとおもいます。
僕は後者の仕様は、同じ変数名が複数ソース上にあるとき現在の位置から見て最も内側のブロックで宣言されたものの方で解決するという当たり前の規則だと認識してます
僕にとって謎だと感じるのは前者の仕様です。cの規格のどこからきているのか気になります >>670
すみません。
このレスの前者は後者に、後者は前者に読み替えてください
間違えました >>670
https://ideone.com/ORzF28
もう、結論はお出しになっているかと‥‥考えます
規格の話は苦手なのでごめんなさい >>670
> 同じ変数名が複数ソース上にあるとき現在の位置から見て最も内側のブロックで宣言されたものの方で解決するという当たり前の規則だと認識してます
その「当たり前」の規則は変数名に限ったものじゃくて構造体タグ名についても同じ規則が適用される。
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
6.2.1 Scopes of identifiers
> A label name is the only kind of identifier that has function scope. ...
>
> Every other identifier has scope determined by the placement of its declaration (in a declarator or
> type specifier). ...
> ...
> ... the scope of one entity (the inner scope) will end strictly before the scope of the other
> entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the
> inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
ただし変数名とタグ名とでは名前空間 (name space) が異なる。 {
int a;
{
int a;
}
}
とやってることは同じ >>666
二重定義じゃなくて、入れ子構造の中での定義にすぎないからでは?
イメージとしては、コンパイラとしては、外側の構造体は
struct XX_a {}
内側の構造体は
struct X_a_a{}
みたいな感じで管理してコード展開してるだけ。 >>673
出典出してくださってありがとうございます
declarator内かtype specifier内かどっちかで現れたかにも関わらず識別子には同じような規則が適用されるのですね
この知見を趣味のコンパイラづくりに役立てたいと思います
ありがとうございました int a = -4 % 3; // -1
int b = -3 % 3; // 0
int c = -2 % 3; // -2
int d = -1 % 3; // -1
int e = (-4) % 3; // -1
int f = (-3) % 3; // 0
int g = (-2) % 3; // -2
int h = (-1) % 3; // -1
これは仕様ですか?環境依存ですか? C90は実装による
C99は被除数と同じ符号 ((ISO/IEC 9899:1999) の 6.5.5 見ろ)ってwiki に書いてあったけど
6節の (a/b) * b + a % b === a と
整数化に際しての丸めの方向から結果的にそう解釈すればいいってことなのかな まあ環境依存だと割と困ってたので
C99でIntelの実装にあわせただけなんですけどね >>677-678
C89 で符号が確定して欲しいときには div 関数があるよ。
これの符号は C89 のときから C99 以降の / や % の挙動と同じ。 配列から数個おきに取得するとき、なにかアルゴリズムとかライブラリ関数みたいなものってありませんか?
↓みたいなコードです。nが大きく、物凄い時間掛かっていて...
for(i=0; i<n; i++) a[i] = b[i*3]; >nが大きく、物凄い時間掛かっていて..
オンメモリーで扱えていなさそう a書とb読で互いにページ追い出されてスラッシングみたいになってんのかねえ 皆様ありがとうございます、Cだとなかなか難しそうですね...
データは数百MBくらいの画像で、mallocで確保した領域にあります。
RGBRGBRGB・・・からRだけを取り出す、みたいな処理で、
頻出しそうだし何かうまい方法あるんじゃないかと思ったんですが。 >>686
ちょっと試してみた
a[] 100MB, b[] 300MB の配列確保して、
配列bを適当に初期化したあと
a[i] = b[i*3]; を実行してみた
それしかしていないが処理は1秒程度だった
64bit環境でメモリ16GB、i7 6700k skylake 4GHz
手持ちのコンパイラは Microsoft(R) 32-bit C/C++
Optimizing Compiler Version 16.00.40219.01 for 80x86
参考になるかな 8ビット無駄になるけど、RGBを 32ビットの整数として、>> と & では? 単純な方法でもいうほど遅くなるわけない
最速を目指すならSIMDでやれ >>686 の説明文で触れてない重たい処理があるのかもしれん ループ内で他の事をすると格段に遅くなったので(コンパイラの最適化の関係でしょうか?)
他の処理はすべて外に出して、書いた処理だけにしてる状況です。
ちょっとした実験に使いたいコードで、装置からの出力がだいたいGByte/sくらいなので、それに追い付く処理速度が理想なんですが...
並列化勉強しないと無理ですかね...
>>687
テストまでありがとうございます、こちらでもそれくらいのオーダーでした。
環境のせいではなさそうで安心しました。 他の事したらキャッシュの効率落ちるわな
GByte/sってSATA3の速度超えてる
リアルタイムに加工するのはまだまだ無理なんじゃ サイズが全然違って参考にならないかもしれないけど、以前テスト用の音声データのサンプリングレート落とす時に似たような事やった時は、a[i] b[j]でi++,j+=3みたいにやった方が早かった記憶。 >>692
コード見てないからなんとも言えないけど、本当にそのループだけで1秒ってのは時間かかりすぎじゃないかな。
このコードでgcc 最適化オプションなしでも0.3秒、-O2なら0.000002秒。
5年くらい前のCore i7 3.3GHz メモリ16GB
勘違いしてないか心配だけどコード。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
int count = 100*1024*1024;
unsigned char *a = (unsigned char*)malloc(count * sizeof(unsigned char));
unsigned char *b = (unsigned char*)malloc(3 * count * sizeof(unsigned char));
clock_t t = clock();
for(int i = 0;i<count;i++){
a[i] = b[i*3];
}
t = clock() - t;
printf("%f\n",(double)t/CLOCKS_PER_SEC);
return 0;
} >>687 だが、正確に測定したわけではない
>物凄い時間掛かっていて...
こういう質問だったので、そんなにかからないよという程度の返事
ものすごい時間が掛かると言う処理の内容が分からないとこれ以上は・・・ もしやコードとかアルゴリズムの話じゃなくて、ミリ秒単位を長いと感じるかどうかってことなのか >>699
volatileつけてM1macで-O0で0.25秒、-O2で0.05秒位だな。普通に間に合いそう。 まったく自信がないのにチャチャ入れるようで申し訳ないのだけど、volatile を書く位置によっても結果がことなるかなと
おそらく a の * の左側に記述したのだと思うけど、動的に確保したメモリに対して有効なのかな…
誰か詳しい人いませんか? ・ volatile で修飾された変数 (メモリ領域) は初期系にとって未知の方法で更新されうるというプログラマから処理系に対するヒント
・ (未知の方法で更新されていても) 言語仕様で定めるところの抽象計算機の動作に厳密に従わなければならない
という規則なので volatile の修飾先が変数 a であってもポインタ a が指す先であってもこの場合は結果的に最適化は抑制されると思う。 ありがとうございます
おっしゃる通りのような気がします >>686
画像だけならopenCVにsplitというのがあってrgb に分割された配列を返してくれるんだけど、後のレスから察するにどんどん流し込まれて来るみたいだからそのまま使えるかわからないです。
そのsplitではインデックスの計算にOpenCLを使っていますが、もちろん他の処理にも使えるから、ソース読んでみて損は無いと思います。 工夫するにしてもマルチスレッドで分割するぐらいしか思い浮かばん
領域を n分割し nスレッドパラに走らせて複製 >>705-706
volatile の修飾先によってどこの最適化が抑制されるかが異なるので結果も異なるだろう。 すみません、マジの初心者で申し訳ないんですけど、
今サンプルコードを写したりしながら勉強しているんですが、
毎回#includeとかint main(void)とかって書かなくて済む方法
ってありますか?
visual studio 2019を使ってます。
良ければ誰か教えてください。 今後数千行、数万行のプログラムを書いていくことになるんで、int mainを自動入力させたいなんて気持ちはそのうち自動的に消えるので安心してください >>712
ありがとうございます!
元々それらを使っていたのですが、今使っているサンプルコードが書かれている本が
コマンドプロンプトで実行することを想定して作られているのか、
よく途中でscanfを使って入力の読み取りをするのですが、オンライン上だとそれができないのです。
visual studio 2019で、テンプレを自分で作っておいてそれを
読み込むような技があれば教えてほしいです。 自力で調べて解決できました。
ありがとうございました。 C言語初学者です
for文を使って1からnまでの総和を求め、
さらに答えを例えばn==3なら
1+2+3=6と表示したいのですが、この表示の仕方がわかりません
ご教授お願い致します int i.n,x;
n=3;
x=0;
for(i=1;i<=n;i++){
x+=i;
printf("%d",i);
if(i!=n)printf("+");
}
printf("=%d¥r¥n",x); >>719
基本的には不要。
・ 改行を表すものは (C の規格の範囲内では) 文字であるかのように扱う
・ テキストモードでの入出力ではホスト環境の都合に合わせて変換してよい
ということになっていて、改行を2バイトの符号で扱うホスト環境では \n という一文字を
その2バイトに変換するのは入出力関数の仕事。
ただし、標準出力をバイナリモードで開き直している場合だとか、
改行を1バイトの符号で表すホスト環境で2バイトの符号で表す環境のために出力したい
といった事情で改行を \r\n と書くことが無いとは言い切れない。 質問です
入力された文字列と文字数を表示するプログラムで
Enterキーのみが入力されるまでループして入力要求をするようにしたいのですが
1〜4文字の入力はループするのですが5文字入力するとループが終わってしまいます
どうなおせばいいでしょうか?
よろしくお願いします
/*************************************/
#include <stdio.h>
#include <string.h>
int main(void){
char str[] = "Hello";
fgets(str,sizeof(str),stdin);
while (str[0] !='\n'){
if (str[0] != '\n'){
printf("文字列%s\n",str);
printf("文字数%d\n",strlen(str));
fgets(str,sizeof(str),stdin);
}else{
break;
}
}
}
/*************************************/ >>721
>1〜4文字の入力はループするのですが5文字入力するとループが終わってしまいます
設問として、何文字までの入力を受け付けるようにし、
それを越える文字数入力された場合はどうすると指示されてます? >>724
言葉足らずですいません
5文字までの入力で6文字以上の入力は考慮しないとなっています
>>723
大学の課題です >>725
5文字までの入力を保証するには、配列サイズがたりません
入力最後のエンターキーまで含めるなら、7文字は必要じゃ無いかな? ・str配列を大きくする
・fgetsした結果のstrに改行文字が含まれてない場合は次の改行文字までstdinを読み飛ばす
等 >>726
配列の箱増やしたらループするようになりました
ありがとうございます
あと1つ問題が残っていて文字列表示のあとに改行が無駄に1つ入ってしまいます
どうにかできないでしょうか?
現状
abcde
です
したい表示
abcdeです >char str[] = "Hello";
とにかくここが気持ち悪い・・・ >>728
入力の最後に改行がある前提で表示を行うか、
文字列最後に改行がある場合は切り詰めるか、
どちらかで処理すると良いです >>728
切り詰め方はこんな感じで
if (str[strlen(str) - 1] == '\n')
str[strlen(str) - 1] = 0;
↑全角空白は適当に置き換えて Hello!って!付ければいいよ。元気が足りない。
さらにこれfgetsの動作の理解を問う良問なんだから、無駄な改行なんぞ気にする余裕があるならfretsのドキュメント読んだ方がいいぞ。 >>733
偉そうに言ってスペルミスですね。fgets です >>732
ご親切にありがとうございます!
>>730頂いてから調べててまたわからないことが増えたーって思っていたところでした笑
上の問題は無事解決しました
ありがとうございます
>>729
スマートな初期化方法があれば教えて欲しいです >>733
正しく書き直せた場合の実行結果に改行が入ってなかったので気になりました汗 >スマートな初期化方法があれば教えて欲しいです
バッファサイズをちゃんと決めておくぐらいか?
ギリギリのサイズじゃなく余裕をもって(最大文字数+1(終端NULL)かつ32bitOSなら4バイト、64bitOSなら8バイト単位とか)。
定義後すぐにfgetsに渡すなら初期化も要らないと思うけど、念のためにやるなら
char str[8]="";
か
char str[8]={0};
かな。 >>731
そうやって初期化した str[] の内容を後で書き換えるのは普通ではないと思う。
可能だが気を付けてないとバグの元になりそうだしね。
似たようなのに char *p = "hoge"; があるが、これはコンパイラによっては文字列をリードオンリーになるようにコード作って *p = 'A'; なんて後でやるとOSがプログラム停止させたりする。
しかしCの文法としては間違いではないのでコンパイルエラーにならない。 >>721
>char str[] = "Hello";
>>738
> str[] の内容を後で書き換えるのは普通ではないと思う。
私は「配列であるかぎり」それを後から書き換えるのは、初期化方法に関係なく文脈・表現として違和感なしと感じます 大文字→小文字への変換等の文字列長変わらない題材は
str[] で初期化しそうだわ 初期化のときだけ [] をキッチリポインタと区別するc の仕様がちょっと気持ち悪い
って感じかな externや二次元配列でも区別しとるじゃろうが
元々違うものを区別されたからちゅうてガタガタぬかすなや
同じと思いたがるのが間違っとるんじや char **hoge;
char *hage[];
好き嫌いが判れるな そもそも初期化の*と演算子の*だって違うものだからな…… 関数の引数のary[]はポインタだって言ったじゃないですか if ((ss == 0) || (ss == 5) || (ss == 10) || (ss == 15) || (ss ==20) || (ss == 25) || (ss == 30) || (ss == 35) || (ss == 40) || (ss == 45) || (ss == 50) || (ss == 55)) {
hogehoge();
}
だいぶん無駄な書き方だと思いました
一桁の値が0が5の時に実行したいです
アドバイスお願いします >>752
int ss;
int sss = ss / 10;
if ((sss == 0) || (sss == 5)) {
hogehoge();
}
自己レス
こうですかね >>754
節子それ余りやない。ssss=ss-sss*10とかやらんと。
組み込みマイコンだと/,%なしで頑張る縛りプレーもあるで。自分がよくやるのは対応する値域を限定して、
掛け算と >> による割り算で計算する。それより難しいの頭がついてこん。 >>756
どうもありがとうございます
>>754って書いたけど
>>753が端的だったのでこれが楽ちんだと思って754は見直してませんでした
Arduinoで時計作りたくて触ってるところです >>757
ArduinoってUnoあたりは弱いマイコンなのにadafruitのサンプルとか浮動小数点演算してたり感覚おかしくなる。
1秒ごとの処理なら、1秒ごとにカウンタ増やして5になったら何かするって処理でもいいと思う。
使ってるマイコンが除算回路持ってるかは調べといたほうがいい。32bitマイコンでも割り算は省略されたり。
まぁ動きゃいいので効率や速度も捨てるのも、それが能動的な選択なら構わないとは思う。
ちなArduinoのスケッチは、古めのC++だったりするので、たまCで見慣れん文法が出て来る。 if(++ss &5 && ss+=11) {....}
minutes=(ss &5)+ss/16*5; minutes=(ss & 7)+ss/16*5; >>759
難しそうで理解できないです><
>>758
mmが2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57の時に実行したい
int mm;
if (mm = 2) || (mm = 7) || (mm = 12) 略 {
hoge();
}
こう言った場合はカウンター使うんでしょうか? >>761
mmが上の条件でなおかつmmがpmmとは異なりssが0のときに動かしたいです >>753 これを応用して、mmから2を引いて5で割り切れたときですかね witch (mm) {
case 2: case 7: case 12: case 17:
case 22: case 27: case 32: case 37:
case 42: case 47: case 52: case 57:
hoge(); break;
default: break;
} >>764
switchの存在忘れてました
ありがとうございます
やってみます if( (mm>1) &&
(mm<58 ) &&
!( (mm-2)%5) ) {.....}
かな? ((mm-2) % 5) == 0
!((mm-2) % 5)
(mm % 5) == 2
ふむ。 なやましい >>768
ありがとうございます
3つ目ですかねー 今から数年前はc言語マスターっていうコテハンがいたような覚えがあるんだけど今は見る影もなくなっちゃったな
今でも覗いているのかな
いなくなったらいなくなったで寂しいもんだ あと片山博文って奴もいたがあいつはtwitterで元気にやってるね
すっかりtwitterのit畑に馴染んでいる #include<stdio.h>
void main(void){
puts("Hello world.");
}
Cの基礎。 >>773
mian の返却値を void にすんなよ。 どこでも出口
exit(EXIT_SUCCESS); 人が減ってる?
それじゃ俺も参加するか
よっこらC(セックス) 「初めてのC」ってタイトル見たとき、ちょっとドキドキしたw >>774
異常な執念で噛みつくやついるよな
void mainに親でも殺されたのかって感じ ふんばっても何も出なかったからそのまま出てきたわ。 なぜC言語は「言語」までつけて呼ぶのでしょうか
PASCAL言語とかFORTRAN言語とかPython言語とかいう言い方は聞いたことがないので気になりました
一文字で語呂が良くないから? >>784
仮に「F」なんていう言語があったとしたら、それには「言語」は付けないのが自然なんですかね アルファベット一文字なら言語ってつける
Goだけなんか例外的なだけで 普通に短すぎる識別子の弊害だろ
言語付けとけば>>777のレスは無かった 日本語ではC言語で検索しやすくなるが外国はどうしてんだ?
C lang とかで検索してるのかな? アセンブリ言語って自分的には違和感ないけど業界的にはどうなの? 普通だね
アセンブラ言語でもどっちでも
しょせんカタカナだし
ドヤるとバカっぽいから放置 もう英字一文字の言語は飽和状態だからこれからは平仮名一文字とか漢字一文字の言語名にした方が良いな。 >>784
日本語(外来語含む)の音韻は音節ではなくモーラ(=拍。俳句の数え方)で数えるべきで、
C(しい)もGo(ごお)も2モーラ
>>785>>788
F(えふ)も同じく2モーラ
まあ、別に2モーラ以下なら「言語」を付けるという規則性もなさそうだけどね
Java(じゃば)やLua(るあ)も2モーラだし >>801
普通英語で検索するよね?
c languageとかgolangとか luaって調べたら月の画像が出てきてめちゃくちゃ怖いぞ 月を怖がる人ってたまにいるけど
前世とか今世で悪いことでもしたんかね >>806
欧米では、月の光は人を基地外にする、とかいうそうですよ
確か狼男も満月だったっけ、いや、それは送り狼だったっけ? >>811
地球も太陽も怖いです
あと小惑星も怖い
あと月の裏側もマジでこわい 冥王星の最新画像見たけどめちゃくちゃ怖くて直視できなかった NHK-BSプレミアム『グレートネイチャー』の宣伝臭が鼻につくくらいで
扱っている題材は台湾の自然、どこがグロなんだ? >>820
地球の中心コアへの旅っていう関連動画がグロい lu分解をc言語でやりたく、次のようなコード(1部分になります)を書いたのですが、y0の値が0.8になるはずなのに全く違うものとなってしまいます。原因が全くわからないのですが、どこを改良すればよいのでしょうか。
for(int n = 1; n <= M+1; n++){
t = n*dt;
for(int i = 0; i <= N; i++){
x[i] = 0.0;
}
/* Ax = uを解く */
/* Ly = u */
y[0] = u[0]/l[0][0];
for (int i = 1; i <= N; i++){
y[i] = (u[i] - l[1][i]*y[i-1])/l[0][i];
}
/* Ux = y */
x[N] = y[N];
for (int i = N-1; i >= 0; i--){
x[i] = y[i] - m[i]*y[i+1];
}
/* 更新 */
for(int i = 0; i <= N; i++){
u[i] = x[i];
}
} x, y, l, m, u の宣言で添え字のとりえる範囲分はちゃんと確保してる?
(lu分解として正しいかどうかはおいといて)ループのコードから
x 0..N まで → 最低限 double x[N+1];
y 0..N まで → 最低限 double y[N+1];
u 0..N まで → 最低限 double m[N+1];
m 0..N-1 まで → 最低限 double m[N];
l [0][0]..[1][N] まで → 最低限 double l[2][N+1]; 最初に宣言して確保してるので、大丈夫だと思うんですが、、
いちおうx,y,l,m,uをそれぞれ出力してみたのですが、yだけ間違えた値になってしまいます。
ループの順番とかがおかしいんですかね? 最小限再現できるコードを書いてもらわんと指摘することはできんねぇ
(そして最小限再現にシェイプアップする過程でやらかしを見つける) >lu分解
java版?なら見つかった。
ttps://qiita.com/edo_m18/items/1d67532bed4a083cddb3 小学生の頃から知ってたことばかりでウルトラつまんねえ番組だ int main() {
return 0;
}
いきなりこれの意味がわかりません。解説によるとゼロを返して正常終了する。
とかなんとかなんですが、どういう意味でしょうか。
オンライン上にゼロの意味の解説が見つかりません。 大抵の解説では「OSに返す値」となってる。
プログラムが正常終了したら 0。
異常終了や目的の処理が出来なかったときには0以外を返すのが慣例。
Linuxならシェルで echo $?
Windowsならコマンドプロンプト/バッチファイルで echo %ERRORLEVEL%
で確認できる・・・らしい。
0以外を受け取ったからとOSが何か特別な処理をするわけではない。 >>834
エラーで終了するときは0以外で帰しておくと
数年後の未来の自分を助けることができるぞ! この段階では
0をかえす
そして
正常終了する
ぐらいの認識でいいんじゃないの?
別にどんな整数を返しても正常終了するわけだし >>834-835
厳密にいえば、言語仕様上では
・ 0 又は EXIT_SUCCESS の場合は成功終了であることを処理系定義の方法で返す
・ EXIT_FAILURE の場合は失敗終了であることを処理系定義の方法で返す
・ それら意外の場合には返される状態は処理系定義とする
という規則になっている。
どのように解釈されるかは言語仕様の側でははっきりとは決めずにホスト環境 (普通は OS のこと) や処理系の都合次第なので、
言語よりは OS の資料にあたるほうがわかりやすいかもしれない。
言語仕様として確実に保証してるのは少なくとも成功したのか失敗したのかだけは返せる (受け取るかどうかは知らんけど) ってだけだね。
POSIX (Unix 系 OS) では exit status と呼んでるけど、
Windows では error level とか exit code と言ってる。 単独で使う場合は関係ないけど
シェルとかバッチファイルから呼び出す場合にエラーや望まない結果だったら処理を中断とかしたい場合に
ちゃんと値を返しておくと便利になる >>839
呼び出したプログラムが返してくる値を使うプログラムとしては make がありますね… >>834
補足として、CのAPIにも失敗時に0を割り当てる場合と、成功時に0を割り当てる場合がある。
エラーの要因なんかを意識したい体系では後者も普通に使われるが、同じコード内で前者と
混在せざえるをえない事もある。マクロなんかを使った記述を意識しないとハマるぞw >>843
・E_OKで成功、それ以外でエラー
・0以上で成功、負でエラー
・常に成功
・void
・なんかのポインタで成功、NULLでエラー
無理やり分類したらこんな感じ? >>834-835
個人的には
int main()
で引数無い状況ならOSのことは想定してないんだろうから
void main()
で良いだろって思う
組み込みとか >>846
リンクされるスタートアップが返り値の存在を前提にしているというのに、main() ごときが返り値の有無を指定するなんて傲慢じゃないですかぁぁぁぁ! main の型を変則的にするくらいなら main をエントリーポイントにしない
(エントリーポイントの関数を別の名前にする) ほうが好ましいと個人的には思う。
言語仕様の外 (処理系定義) で定義された方法を使おうとしていることがわかりやすいので。 実行開始点は◯◯関数とドキュメントのどこに書こうか悩まずに済むならそうしたい ただの慣例なんですね、ご回答ありがとうございました。 C言語初心者です。sleepを使って一文字ずつ
2秒ごとに表示したいのですが
Windowsの端末だとうまくいくのですが、
Ubuntuだと8秒後にまとめてHelloと一度に
表示されてしまいます。ubuntuでも
windowsのように一文字ずつ表示させたいのですが
できないのでしょうか?コンパイラはGCCです。
#include <stdio.h>
#include <unistd.h>
int main (){
printf("H");
sleep(2);
printf("e");
sleep(2);
printf("l");
sleep(2);
printf("l");
sleep(2);
printf("o\n");
return 0;
} >>852
printf('A'); fflush(stdout); はいかが? printfとsleepの間に↓
fflush(stdout); >>853
>>854
ありがとうございます。うまくいきました。
fflushの使い方調べてみます。 >>852
どちらの挙動も言語仕様的にはアリ。
ストリームが対話型装置を参照していると判定できて、かつその場合に限り完全バッファリングすることになっていて、
逆に言えば対話型装置 (この場合はコンソール) に繋がっているときはラインバッファリングかもしれないし、
バッファリング無しかもしれない。
フラッシュを明示的に指示するのでもよいが、 setvbuf 関数でバッファリングをしないように設定することもできる。 >>856
書き間違えた。
対話型装置を参照していると判定
↓
対話型装置を参照していないと判定 低レベルの出力関数使ってバッファリングを回避してみる、とか >>851
int main(){
int a=0;
return a;
}
と
void main(){
int a=0;
}
をそれぞれ asm 付きでコンパイルして比較してみ
判ったら次は a=0; を inline にしてみ >>859
コンパイラが細かくチェックするようになったから lint の出番がなくなった。
gcc や clang なら -fsyntax-only オプションを付けると文法のチェックまでで段階を止める。
必要な警告オプションを付けた上でこれを使えば古い時代の lint より厳しいくらいだと思う。
(ちなみに -Wall や -Wextra を付けても全ての警告が有効になるわけではない。) >>863
>(ちなみに -Wall や -Wextra を付けても全ての警告が有効になるわけではない。)
私は -W -Wall で妥協します 最近のコンパイラはミスタイプすると
「contが見つかりません、もしかしてcountのことですか?」みたいなことまで言ってくるもんなあ
グーグルかよ 入門サイトで勉強しててこんな感じのコードがエラーになって
{
int a = 100;
printf("数値:%d アドレス:%x", a, &a);
}
gccのエラーをコピペで検索すると、&aはポインタだから、アドレス:%pだと回答がヒット。
コンパイラやバージョンによって挙動が違うのでしょうか? >>867
言語仕様で未規定や処理系定義としている場合があって、
そういうのは処理系や実行環境の都合に合わせて決めていいことになってる。
そして「未定義」とされている場合は何が起こってもいいことになってるので、
暴走するかもしれないし、 OS が止めてくれるかもしれないし、しれっと意味不明の結果を出力するかもしれない。
たぶんそれは未定義に該当すると思う。
C の可変長引数は型チェックをゆるゆるにすることで実現されていて、
処理系の内実をわかってる人は言語仕様上の保証がない (けど実態としては問題がない) コードを書くのは普通にある。
パソコンで一般的に使われている呼び出し規約 (関数を呼出す機械語レベルの挙動の規則) だと
ポインタと (レジスタの幅以下の大きさの) 整数は同じ方法で渡すので問題にならないんだけど、
言語仕様では保証がない。
可変長引数の型チェックはゆるゆるなんだけど printf は頻出するからコンパイラが特別扱いで
少しチェックを厳しくしているのでエラーになることもあったりする。
まあ基本的には保証されてないのでやらないほうがいいよ。 >>868
詳しい説明ありがとうございます。
実際にターミナルに出力されたのはerrorではなくwarningで、試したらそのままでも実行できていました。
用心しながら学習続けていこうと思います。 逆に完全に言語仕様に沿っていても警告になる場合もあるし、
(基本的には警告が出ないようなコードのほうが綺麗ではあるが)
言語仕様的に OK なのか NG なのか、
とりあえず自分の実行環境で OK なのか NG なのかを正確に把握するのはかなり分かり難いと思う。 >>867
まず、エラーと警告の違いを
次に、エラーとill-formedの違いを
憶えよう 0から100までの整数のうち、17の倍数となる数の合計を求め、かつ途中の加算処理を出力するプログラムをつくったのですが、うまくいきません。 うまくいかないのは過程を出力する処理の過程なのですが、どうしたらよいですか。
コードは以下です。
#include <stdio.h>
int main()
{
int i,sum=0;
for(i=17; i<=100; i=i+17) {
sum=sum+i;
printf("途中計算→%d\n", sum);
}
printf("合計=%d\n",sum);
return 0;
} >>873
「17の倍数」とは「17で割った余りが0」のこと
Cで割った余りを計算する演算子は「%」 17から開始で17ずつ増やしてるだろ
0は17の倍数じゃないそうだが >>873
何がどううまく行かないの?あってそうに見えるけど >>869
昔のソース(コンパイラ)は %x で通るのが多い
今から勉強するなら %p の方が良いし新しい教科書使った方が良い >>873
printf("途中計算→%d, %d, %d\n", i / 17, i, sum); >>867
伝統的にポインタはintと同じメモリサイズなので昔はそう書いてた
そうなんだよな最近のコンパイラはprintfのフォーマットと引数をチェックしてるんだよな
もう慣れたが最初不思議な気がした
組み込みだと自分でprintf関数作ったり(標準だと使わない機能が多くて重すぎるから)するけどそんな時はどうなるのだろうとか 64 ビット環境では LP64 や LLP64 (int とポインタの大きさが違う) が標準的になってしまったから
古いコードをそのまま持ってきたら通らないってことは割とよくあるよね。 long と int (及び char *)を全て32bitとして扱っていて、辛うじてコンパイルは通るが決してまともに動かない
プログラムがあったので、しょうがないから gcc の -m32 と32bit用ライブラリで何とかした。何せ量が膨大で、
人力で直してたら多分何人か死んでたと思う。 俺が出向いた、とあるクライアントでは人海戦術してた >>884-886
far near 修飾があたりまえな世界から来た私にとっては、なんで今更なことしているの?と疑問におもっていました >>889
hage モデル、もとい huge モデルにはバグがある、とのもっぱらの噂でしたが実際どうだったんでしょうか… ていうか、8086のHugeみたいなものはバグ作り込んでしまいそうで怖いよな。ポインタ絡みで。
違う値が同じアドレスになる事あるし。 当時300kを越える配列を処理したくて使いました
使うというか、複数のセグメントに分割して割り当て、
自前で配列インデックスを計算してアクセスしただけですが 違う場所が同じ値になるような場合があっても言語仕様が保証している範囲ではちゃんと仕様通りだったりするんだよな。
というより保証が可能な範囲をうまいこと言語仕様にまとめたって感じなんだと思う。 >>888
Windowsが64bit主流になっていく頃にも一騒動あったよ >>891
さらに年寄りの繰言を続けますが、
>違う値が同じアドレスになる事あるし。
というのは far ポインタでも同じです、far と hage じゃなかった huge の違いは、オフセットの繰り上がりがセグメントに反映されるかされないか
私は余計なことはしてほしくないので、繰り上がりがない far を愛用していました、huge はいまいち信用できませんでした >>897
パディングの状況に依存するコードを書くのはよろしくない、というのが一般論だったかと
ファイル入出力で問題になりますが、私はもう、ちまちま fwrite() fread() で「1 byte ずつ」やるしかない、とまで諦めています
環境がバッファリングしてくれますし 未規定であるしパディングの大きさに依存するようなコードは避けるのが行儀のよいコードであるのは間違いないけど、
対象にしている処理系での挙動がはっきりしていて移植の可能性もない (または移植のコストをかける覚悟がある)
のなら依存するコードを書くことはそれなりにあると思う。
マクロで切り分けて configure (とか cmake とかのメタビルドツール) で各アーキテクチャの都合に対処することは可能だし。
良くはない。 良くはないがそういう良くないことも出来るのが C ってもんなわけで。 昔、構造体の扱いで失敗した事がある
あるサイトで構造体を引数にして削除処理を行う関数を提供されたが、
実際に使おうとすると引数エラーを返されてしまい途方に暮れた
構造体メンバーには仕様書通りに必要な値をセットしている
しばらくして原因が分かった
関数側は引数が正しくセットされているかを、
処理対象の領域に格納されている同一の構造体と比較しチェックしていた
その比較に memcmp を使っていた
呼び出すこちら側は、構造体を自動変数として領域確保していた 構造体の比較をmemcmpでやるの本当にバッドプラクティスだと思うわ
横着せずに比較関数作れと 横着したくなるというか識別子増やすの躊躇させる言語仕様が招く面倒ね
メンバメソッド系はオブ臭く棲み分けに反し今更入れる必要ないと思うけど
一層にぶち撒かず妥当なルールでツール類で拾いやすいサポートネームスペース括りみたいなのがあれば
void bossy(struct *a);
bool bossy.supporter(struct const*a); バブルの頃に努力?修練?ぎやはははだっせー
と言ってたのが結局、日本の致命傷になっちまったな
それを今まだ言ってる堀江みたいなぶっ飛んだキチガイもいるし
どーすんだこれ >>905
何の話?
日本は米国植民地なので戦後から終わってますよ… 植民地支配がどんなに恐ろしいことか知らないようだな
朝鮮半島に先進国並みのインフラを作ったり
狭い島国に世界最大のメガロポリスができるのと
フィリピンのバナナ農家が受けている仕打ちの違いわかる? 君はここに来なくて良いから、その代わりに
半島に行って自慢して感謝されてこいよ c++のネームスペースさんはadl とかテンプレート混じりでsfiane とか
使うつもりがなくても簡単に誤爆する罠のせいで妥当な実装ではないね >>909
アングロサクソンのやることはえぐいですね…
でも半島の話はやめたほうがいいですよ、むしろ台湾の話をしたほうがいい(親中派だったら無理かもね) >>910
うわー 整然と整列された弾薬を蹴飛ばして地雷原と言っちゃう手合いか
c言語でGUIの作り方教えて >>914
WIndowsAPIはC言語で使うのが正解でC++では使わないっというのを別スレで見たんですが、そうなの? C++でも使う事は出来るが、普通はクラスライブラリを使う
最初はMFCだったかな
>>914のサンプルを試したあと、
C++とクラスライブラリ使って同じ事をやってみると良いカモ >>915
補足すると自前でC++を使ってやる方法も win16 初期には見られたが、
https://www.aa;mazon.co.jp/dp/4774100544/
結局みんな MFC ばかり使うようになりました、もうひとつのメーカー製の OWL ですら滅びたようです
MFC の使い方の本は私は持っていない… >>913
http://w;isdom.sakura.ne.jp/system/winapi/win32/index.html MFCはWin32 GDIの極薄すけすけのラッパーだ
俺なんかMFCから憶えてそこから多くを知った WinUIとかもいいけど、MFCに代わるちゃんとしたCなGUIライブラリを用意して欲しかったわ >>927
では win16 時代の本
https://www.a;mazon.co.jp/gp/product/4774100501/
でも何かしら得るものがあるってことですね、最近ちょっと元気が出てきたから買おうかな、やすいし
913です。
みんなありがとう!! >>930
本が100円でも送料が300円以上だったりするので、古本は要注意。
メルカリで送料込みで安いやつ探した方が良いかも知れない。
(但し、300円以下はあまりない。理由は自分で出品してみると分かる) 47氏こと金子氏はMFCでWinnyを作ったんだな >>933
winny2 は BCC/OWL だったと聞いた気がします >>934
金子氏の書籍より、VC++ から C++Builder に GUI の変更を目的に変えた、との記述を見つけました
Borland C++ Builder 4.0, および 5.0 であれば OWL5.0 をサポートしていますが、VCL の可能性のほうが高いですね Windows上で編集してLinux上でコンパイルしたいんだけど
そういうのに適したIDEでお前らが使ってるおすすめを教えて Ruby on Rails では、WSL2, Linux, Docker, VSCode(Remote Container, Remote WSL)など、
本物のLinux(CUI)で開発できる。
MSYS2/MinGW みたいなWindows でコンパイルした、日本語でバグるものを使う必要もない
Dockerを使わずに、日本人が作った、バージョンマネージャーのanyenv で、
rbenv, nodenv, pyenv など、多言語を統一的に扱う事もできる
組み込み用mruby の本には、Virtualbox, Vagrant を使う。
WSLはサポートしないと書いてあるけど、WSLでも使えるかも?
Webで使えるmrubyシステムプログラミング入門、近藤宇智朗、2020/11
宇宙開発などの組み込み用、MicroPython, Lua, Squirrel の代替になる。
Ubuntu 18.04, C99 対応
人工衛星イザナギ・イザナミで、使っている >>940
キヤノンが打ち上げた光学衛星が夜間撮影に成功したそうです。
夜間撮影が出来るとなると、もはや立派なスパイ衛星。
何を撮影しましょう。 実用的なところで夜間に移動する北のミサイル発射トラック追尾。
個人的希望でgoogleカーの追尾。 頭頂部が日に日に薄くなっていくような気がするから
その辺のチェックを毎日やってほしい >Linux上でコンパイルしたい
Linuxのシェル上でコンパイルしたいという意味?
それともGCCを使いたいという意味? そう言えば以前 Windows で動く IDE で Linux で動くプログラムの編集をしてそのまま
リモートで Linux 側でコンパイルして更にリモートでデバッグまでできれば良いなと
思ったが、どうやらそれができるものはなさそうなので諦めて Linux 上で IDE を動かした。
まあでもクロス開発というか、リモートデバッグというか、そういうのが出来ると便利だよな。 >>944
Linuxにインストールしてあるgccでコンパイルしたい
ビルドボタン押したらssh経由でmakeできたら素敵だが
使ってるgccのバージョンがちょっとどころじゃなく古いので
できればMinGW gccとかじゃなくて現物のgcc使いたい感じ 上でも書いたけど vs code ではダメなの?
ターゲットが WSL、コンテナ、ssh 接続関係なく
Win 環境から編集、コンパイル、デバッグ一通りなんでもできるよ。 そこまでおっしゃるのなら、試してさしあげてもよろしくってよ? >>945 を昨日書いたが、さっきこんなの見つけた。有料だけどな。
JetBrains、リモート開発機能と軽量IDE「Fleet」を発表
https://japan.zdnet.com/article/35180131/ 漏れは、Ruby on Rails, WSL2, Ubuntu 18.04 で、
Web Socket など、Railsで使う各モジュールがネイティブコンパイルされるけど、
build-essential とか入れておけば、
Rails のインストール時に、勝手にコンパイルされる
build-essential には、
gcc(GNU C compiler), g++(GNU C++ compiler), libc6-dev(GNU C Library), make などが入っています
パッケージ: build-essential
https://packages.ubuntu.com/ja/bionic/build-essential
43.0 MB のアーカイブを取得して、165 MB のディスク容量が使われます VS2022に昔のプログラム持ってったら
isspace()とかに80h以上の文字入れると例外になるけど
いいのかこれ
テーブルで処理してて80h以上は負だからテーブル外になるって理由はわかるんだけどさあ
昔のはなんとかうまくやってた気がするんだけど >>954 それ char で負の値を渡してるんじゃね? >>954
int isspace(int c)
ですよ、ちゃんと int の正の数で渡してます?char をまんま渡してたらまずいっすよ
>>956
「unsigned char にキャストして、暗黙の型変換(プロモーション)に頼る」ってかなりアクロバットに見えますね char が符号付か符号無しかは処理系定義で、
符号無しであるような処理系では char が int に拡張されたときに負数になることはない。
(考慮する必要はない。)
C にはそういう処理系定義とか未規定とか未定義がもりだくさんなので
ある処理系の定義では未定義を踏まずに済むプログラムでも
別の処理系では (処理系定義のコンボで結果的に) 未定義に引っかかることはよくある。
C のプログラムで完全に処理系定義や未規定を避けるというのは困難な話だし、
(可能なら環境依存を避けるように意識するのは良い作法ではあるけど)
違う環境に持ってきたらその程度の修正は必要なものだと思って諦めるしかしょうがない。 未規定を避ける必要はない
未規定のブレ幅以内に収まるように書いてあるプログラムは適格
そうでないプログラムは不適格で未定義の動作となるだけだ 違う。
たとえば
int f1(), f2();
int a = f1() - f2();
のようなことをしているとき、
f1とf2の評価順序は未規定
f1とf2の評価順序によりaに入る値が変動する場合は未定義の動作だ 未規定って処理系毎に好きに実装して良いんでしたっけ? 処理系が好きに実装してよいし, ひとつの処理系の中で一貫している必要も, ドキュメントに明記する必要もない >>962
未規定な動作を含むプログラムは正しい。
あり得る動作の内のどれかにはなる。
未定義はどんな保証もない。
未定義の挙動を含むプログラムはプログラム全体がどんな動作をするかわからん。
全然関係ないと思う箇所でわけわからん動作になることもあるし、
未定義を踏んでる箇所より前に問題が表れることもないとはいえない。
>>963
処理系定義は「未規定の動作のうち,各処理系が選択した動作を文書化するもの。」ということになっている。
つまり処理系定義は未規定の一種という扱い。 >>962
処理系どころか同じソースでもコンパイル毎に変えることすら許される >>961
> f1とf2の評価順序によりaに入る値が変動する場合は未定義の動作だ
これは嘘じゃね? >>968
いやあってる
演算子の結合規則・優先順位は、あくまでも複数の演算子があったときにどの演算子を先に処理するか、に過ぎない
オペランドを二つ持つ演算子一つに限れば、どっちのオペランドを先に評価するかは処理系依存だったと思う
これは関数の引数についても同じ >>969
だれも結合優先度の話はしてないと思う。
> f1とf2の評価順序は未規定
これについては未規定で異論は無いんだよ。
> f1とf2の評価順序によりaに入る値が変動する場合は未定義の動作だ
でも、こっちは嘘じゃね?という話。そんな規定文面確認できない。 C17Draftのpp.65 6.5 1では?
> If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
> If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings. >>971
複数の関数呼び出し先にある評価同士、あるいは呼び出し元と呼び出し先にある評価同士は
indeterminately sequenced となり、 unsequenced にはならない。
6.5.2.2 Function calls p10
> ... Every evaluation in the calling function (including other function calls)
> that is not otherwise specifically sequenced before or after the execution of the body of the called
> function is indeterminately sequenced with respect to the execution of the called function. 96)
...
> 96) In other words, function executions do not “interleave” with each other.
>961 の f1, f2 は関数なので、 f1() - f2() の結果が未規定だからといって未定義動作にはならない。 >>972
OK, 関数呼び出しを噛ませたことで評価順序が未規定ではなく不定(一方が他方の後(先)であることは保証される)になるので, 呼出先関数で副作用があっても(結果は未規定だが)未定義動作ではない, と
確かによくある a = i++ + ++i; みたいな例が適切だったか >>973
あともう1点念のため。
その例 a = i++ + ++i は未定義動作になる例として適切なんだけど、未定義動作になる理由は >971 の規定であって、
>961 の「評価順序によりaに入る値が変動する場合」というような理由じゃない。
例えば a = (i = 0) + (i = 0) は、どっちの i = 0 を先に評価しても a に入る値は 0 で変動しないけど、未定義動作となる。 自作ライブラリのヘッダと標準関数のヘッダの読み込み順って
なにか決まりごとはあるの?
#include "jisaku.h"
#include <stdio.h>
ってやってたらキモイって言われたんだけど、これなんかおかしいか?
インクルードガード利いてるし順番なんてどうでもいいだろ っていうか
だったら自作のヘッダが先に来るべきだろ って思うんだけど >>975
たとえば assert.h を #include する前にマクロ NDEBUG が定義されていると assert が無効になるといったように
動作の切り替えをするマクロというものが存在する。
標準ではそういうマクロは下線で始まる名前になってることが多いから自分のコードの中の名前がたまたま衝突するということは
そうそうないんだけど、各処理系やライブラリに固有の切り替え用マクロが雑な短い名前だったら意図せず影響を与えるかもしれない。
単なる習慣としてもプロジェクト内のヘッダは後に書くのが定着しているね。 ユーザー先だと、標準的な関数やdefineが定義済みになって不具合が出るかもしれないし
一般的な方から読み込んだほうがいいのでは? なんか本の著者は自作モジュールを先にインクルードするって言ってたな
理由はそのほうがコンパイルエラーが早くなるかららしい >>976-978
なるほど
若い時分なら「そんなの間違ってる! 俺が世界を正す!」って言ってたかもなぁ
とりあえず自分ヘッダは後ろで読むようにするわ >>977
標準ヘッダを後に書くと
衝突したとき標準ヘッダ側がエラーとして表示されるからな くだらねえ
単に依存関係ってだけのことだろ
一概にどっちが先であるべきだなんて押しつけは糞食らえだ 以前のサイトだと
標準ライブラリ
業務共通ライブラリ
個別ライブラリ
の順にインクルードしなさいと決められてた まぁ、これも他のスタイルと同じで、どっちがいいというよりは単純なルールで統一されていることが重要なものと思ってる。 押しつけはやる気と引き換えだ
そのコストに見合う理があるべき ヘッダのインクルードは全て .c の側でやる (ヘッダ内でインクルードしない) という流儀もある。
既にほとんど滅びた流儀だろうし、現代的ではないと断っておくがこの考え方を取るのであれば
インクルードの順序は重要になる。
// foo.h
struct foo{};
// bar.h
// ここで foo.h や stdint.h をインクルードしない
void bar(foo, uint32_t);
// bar.c
#include <stdint.h>
#include "foo.h"
#include "bar.h"
void bar(foo x, uint32_t y) { printf("bar\n"); }
// main.c
#include <stdio.h>
#include <stdint.h>
#include "foo.h"
#include "bar.h"
int main(void) { struct foo x; bar(x); }
メインの側で適切な順序にしないといけないから抽象不足だが、
インクルードガードしてても読み込んでプリプロセスの手順を通すという処理は発生してしまうので
それすらも最低限であるのが好ましいなどの思惑があるのだと思う。
(いまどきのコンパイラではインクルードガードのパターンを検出して
二度目にはファイルを読むことすらしないものもあるらしい。)
まあリソースをケチるのが正義だった昔の話やね。 レジスタから「値を読みだす」というのは「値をコピーする」と同義ですか? なんか違和感ある言い方だな
「読む」とはCPUへの入力、「書き込む」がCPUからの出力で
たとえばメモリリードはメモリからの出力、メモリライトはメモリへの入力を意味する
「コピー」はそれで合ってる
「ムーブ」になる場合は必ずそう断るから >>990
たとえば
int a = 1;
int b = a + 2;
この「a + 2」の「a」の部分はメモリリードしてるということですよね
このとき計算のためにCPUに値を入力(コピー)しているという理解で合ってますか? レジスタからの読み出しは読み出しという操作自体に副作用がある(レジスタに対する読み出しを検知してデバイスが何かを行う)場合があるので, 必ずしも同義とは言えない >>991
>CPUに値を入力
レジスタはCPUなのかメモリなのか
int a = 1;
int b = a + 2;
これがアセンブラだと
mov ax,1
add ax,2
mov ptr[b], ax
メモリに書き込んでるのは3行目しかないが >>995
アセンブラよくわからないんですが
mov ax, 1 // axレジスタに1をコピー
add ax, 2 // axレジスタの値に2を加算
mov ptr[b], ax // axレジスタの値をptr[b]にコピー
でしょうか
ptr[b]っていうのはなんですか? 最適化で変数aがレジスタに充てられてるんだな
最適化を抑制すれば
mov ax,1
mov ptr[a], ax
mov ax, ptr[a]
add ax,2
mov ptr[b], ax
とかになるんじゃね int main(void)
{
printf("good-bye 157\n"); このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 180日 0時間 29分 20秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。