C言語なら俺に聞け 158
レス数が1000を超えています。これ以上書き込みはできません。
考え方によるのでどれが普通ということはないと思う。
たとえば C は古いシステムの保守のためと割り切るなら C89 にこだわる理由になるが、
C++ との連携を考えるなら C17 を選択する理由になる。
(C++20 が参照する C の規格は ISO/IEC 9899:2018 のことなので。)
私自身は C99 を基本としつつ C99 がどうしても使えない事情があるなら C89 を選択することはありうるが、
C99 で問題ない場面であえて C89 を使ったりはしない。
C11 以降の機能が各プロジェクトで特に有用で処理系やツールチェインに不安がないならそれを選ぶこともある。 C++が使えるならC++でいいと思うんだがな。
C99以降が使えるけどC++が使えない|使っちゃダメなシチュエーションてのがあまり思いつかない。 個々のプロジェクトのポリシーとしてならそれこそPLの好みでいくらでもあるだろうけど。
でもLinuxてC99使ってた? C99か。。。。
変数を途中で定義できたりforスコープは有難いんだけど
そういうのはC++があるからCにはあんまり求めない
わざわざCなときは枯れたところを使いたい
すると半ば無意識にC89になってる 1/6までc magazineが1冊55円でセールやってるぞ。 アマゾンにあるな。55円か。俺のアマゾンポイントが56なのでポイントで1冊ただで買えるが。うーん。どれを買うか。 >>15
いや、これ、税込み55円のようだよ。本体50円で消費税5円なのではないかな。
更にアマゾンで Kindle unlimited の人は全部0円。 全部セットで1万ぐらいで買えたりしたら一々選ばんでいいのだがな。
全部読み切れないとは思うが。(てか今となっては読む価値のない記事が多いかな・・・) まだ読んでないkindle本あるのに・・・16冊購入(´・ω・`) 検索していたらこんなページ見つけた。しかしここでの販売は6冊単位で600円なので1冊100円。
C Magazine セット販売
https://tatsu-zine.com/magazines/cmagazine C MAGAZINE 2005・2月号 特集2 グラフ理論入門 質問
#include <stdio.h>
int main (void){
char str[100];
int i,j,n,m,a,b;
char A[100];
scanf("%d %d %s",&n, &m, A);
for(a=0;a<n;a++){
j=0;
for(b=0;b<m;b++){
scanf("%s",str);
for(i=0;str[i];i++) {
if(str[i]== *A) {
j++;
}
}
}
printf("%d\n",j);
}
return 0;
}
っていうコードを書いてみたんだけど、思うような出力が出ない
どうすればいいか教えてくださいお願い
以下問題
https://i.imgur.com/6TnIX9K.jpg なんで、N, M, KのKを文字列として受けてるの? >>26>>27
paizaの問題って公開しちゃいけないと思ったが、その問題は大丈夫なのか? >>26
これって入力は全て数値だから scanf() のフォーマットは全て %d で良い筈だが、何故文字列として受け取ろうとしている個所があるのか? >>27
公開しても良い問題だったね。しかも問題のURLをコピーしたりも出来る。
だったら画像貼ってないで素直にURL貼った方が良い。スマホでWi-Fi使わず見てたりしたらパケット余計に使うことになるからね。(だから専ブラではいきなり画像をダウンロードしない設定にしてあったりして、見られる率が下がる)。
URLはこれな。
https://paiza.jp/works/mondai/c_rank_level_up_problems/c_rank_for_boss とりあえずfgetsとstrtok_rを使って、
一行まるごと読み込んで、読み込んだ一行分の文字列を空白で分割して表示するだけのプログラムを書いてみたらどうかね >>30
俺の地元のルールだと、
22 22 22 ...(25回22を選ぶ)
みたいなピックしてkが2だと50ポイントもらえるルールだったから文字列として扱わんといかんかとおもてた 3[山田、山田、佐藤、田中、・・・]
7[・・・]
12[・・・]
というような表を作っておけば良いのでは? >>35
ソートするだけだよ。
まずは入力を配列変数に貯め込んでそれに対して並べ替えをする。
ソートする部分を自作するのが面倒なら qsort() 使えば良いんじゃないかな。
(この辺はC言語使わない方が楽かも知れないが) 入力データの1行目を読みデータ件数を取得する
データ件数にあわせて配列を確保する
(予めMax値の配列を用意するのでも構わない)
2行目から最終行まで順に読み込み、配列に格納する
問題文の財産評価ルールに従いデータをソートする
並び変わったデータを出力する 文字配列なんですが
char str[] = { 'A', 'B', 'C' };
↑のstrにはnull文字は付加されないという認識で合ってますか? >>40
合ってる
境界調整の結果として'\0'のように見える
詰め物が入る可能性はあるが騙されてはいけない >>41-43
そうなんですね
ありがとうございました >>40
付加されない。
"ABC" と書いた場合に char 四個ということになるのと違ってその場合には要素が三個の配列と解釈されることが保証される。
つまり str の型を言うなら char[3] ってことね。
ちなみに
char str[4] = {'A', 'B', 'C'};
というように書いた場合 (初期化子に書かれている要素が配列の要素数より少ない場合)
は足りない分は 0 が補われたかのように動作することが保証されるので str[3] には 0 が入ってる。 分かって使うのは良いけれど
そのまま文字列処理関数に渡すと
困った事が起きるんだよな プログラミングで y = 1 / (1 / x) ってやったらどうなるの?
https://mi.5ch.net/test/read.cgi/news4vip/1641823457/
1 名前:以下、5ちゃんねるからVIPがお送りします 投稿日:2022/01/10(月) 23:04:17.072 ID:expyRxlYa
頭のいいコンパイラなら y = x にしてくれるのか?(機械語にするとき)
あっ、ちなみにインタプリタ言語やLLでは普通に t = (1 / x) を計算して y = 1 / t にするだろうそりゃ
うちは自動車メーカーだからな、使ってるのはC言語で、コンパイラは GHS MULTI っていうお前らが知らないコンパイラだよ xが整数ならしてくれないよね
浮動小数点数なら
if (x==0) y=NAN; else y=x;
にしてくれるのかなぁ 0除算とかオーバーフローはプログラマが考慮してくれるんじゃないのかな? gccなら-ffast-mathを付ければy=xになるはず
ieee754準拠なら変形しない 整数型なら0除算が未定義動作だから変な最適化がかかるかもしれん
x==0 で未定義動作
2回目の割り算で x!=1&&x!=-1で未定義動作
signedなら最終的にy=xになりうる
unsignedならx=-1がありえないのでy=1になるかもしれん 整数前提
カッコついてるから (1/x) まで評価してソレを整数化とり得る値は符号付きで-1,0,1,<0割未定義>
その評価値が分母に 分子が 1 の演算で 符号付きで 1,-1,<0割未定義>
ほとんど0割未定義を踏みそう ものにもよるがだいたいはダメだな。
printf()で%.3sみたいなフォーマットにするとかstrncpy()で文字数指定するとかなら大丈夫だろうが。何れにしてもプログラマーが意識してないといけない。 ぐはっ
リロードしても出てこなかった書き込みが沢山出てきた C言語学び始めたんだけど今のところJavaで自動でやってることをCは明示的にやってるって事くらいしか分からん
Cはガベージコレクタが無いからアルゴリズムを学ぶには最適って聞いたんだがいまいち理解できん
メモリの確保と解放を任意にできることで他と違って何ができるようになる? 何で?
確保した資源を解放するという当たり前のことを
自動でやってもらうことの何がそんなに大事なの?
当たり前のことがどうなっているのか把握するほうが大事だと思うけど 別に何も
Cはよく高級アセンブラと言われるくらい低級なもの
JavaはVMで動かす高級なもの
高級なものは低級なもので実現されてるのよ int __cdecl main(int argc, char** argv)
この時二つの引数はどの時点で突っ込まれるのでしょうか?
引数とかって言われてもこのくらいしかわかんないです。
int add(int a,int b){return a+b;}
int main(){cout<<add(1,2);}
__cdeclあるときはmainの中身が実行される前にmain内にある二つの引数を・・・
すみませんよくわからないので教えてほしいです。 >>60
そりゃmain()が呼ばれる時だけど
何が疑問なのかよくわからん
そのadd(int a, int b)もadd(1,2)と呼ばれた時にaに1、bに2が入る
それと同じ
>>59
>58は>56への応答だよ >>61
ありがとうございます。
c++やり始めたばかりで、初めて__cdeclというものに出会い、
main()に引数が指定されるのも初めて見ました。
__cdeclを調べてみたのですが、よくわかりませんでした。
https://docs.microsoft.com/ja-jp/windows/win32/winsock/complete-client-code
ここのコードに出てきたやつです。
argc, argvこの二つにはどこから来た値がどのタイミングで入るのかがよくわかりません。
サーバー側の方でそれぞれの構造体や関数は一応ですが、調べました。
(ディスクリプタが良くわかんなかったけど部品の形状みたいな感じで覚えました) main関数が一番最初に読み込まれる関数という風に思っていて、
includeやdefineを済ませた後に一番最初にmainが実行されるのなら、
argc, argvこの二つの変数の値がどうやって決まるのかわからないのです。 今更なのですが、mainを実行するときにmainの中の
ローカルな空の変数(?)を宣言するだけ宣言しといてるとかですか? >>63
OSから引き渡される。普通はコマンドラインの引数をシェルが加工して渡してくる。
OSのない組み込みのようなやつの場合はそのmain()を呼び出すプログラム次第になる。 >>64
何を疑問に思っているのかよくわからないが、Javaとか他の言語とほぼ同じでmain()に限らず関数は呼ばれたらそのブロック内でローカル変数のメモリを確保する。(ただしCの場合は宣言だけだと初期化されない)。 >>65
ありがとうございます。
OSからもらってくるのですね。
謎が解けました。 >>57
>>58
自分でメモリの確保と解放を行う事でメモリの仕組みを知れるのは大事なのは分かる
ただgcが動かない事でアルゴリズムとどう繋がるのかがイマイチ分からん
連結リストはメンバを参照して動的配列実現してるけどgcは関係ないと思う
gcが動かない事で何かメリットないん? 純粋にアルゴリズムを学ぶことが目的ならC以外のぬるい言語のほうが良いのでは?
ただ、考えたアルゴリズムを誰よりも早く動かしたいならCは役立つと思うよ 純粋に、なら pascal でしょう…
pasca から C へは機械的に書き換えられるから C でもいいでしょうが
それ以上の高級言語になると、例えばソートアルゴリズムの「インプレイス」の概念も有耶無耶になってしまうので、初等アルゴリズムくらいは C で勉強したほうがいいですね メモリーリークなどは、痛い思いをしてでも学ぶ価値はあると思う
根性論ですまん >>68
プログラマの望むタイミングでGCができるというメリットがある
GCが動くとどうしても遅くなるので
その遅くなると時をプログラムで決めることができる rustがCの代替になる理由がメモリ関連のバグが減るからってのはどう言う事? オブジェクトは複雑に依存関係が出来る場合もある。
参照 (C 的に言えばポインタ) が残っているのにオブジェクトの寿命が尽きていればダングリングが生じてしまう。
C では寿命の管理をするのはプログラマの責任であって、無効なポインタを使った結果は未定義。
そういうのを静的にチェックしてエラーにしてくれたらありがたいなぁというのを実現したのが Rust 。
そのかわり制約の記述がちょっと面倒くさくはあるんだが、どちらにせよ依存関係の管理は C でもやってたことではあるからね。
Rust で制約を書けないようならたぶん C でもちゃんとメモリ管理できてない。 Ubuntuのgcc9で
size_t i = -100;
printf("%ld\n", i); // -100
と出力されたんですが、なぜsize_tで負数が扱えるんですか?
stddef.hでは
typedef long unsigned int size_t;
になってました
怖いです >>76
扱えていない。
printf の書式指定と実際の型に不整合がないようにするのはプログラマの責任で、
それができていないときにどういう挙動になっても知ったことじゃない。 >>77
あと
size_t n = -100;
if (n == -100) {
puts("-100");
}
これが真になるのは-100がsize_tに暗黙的にキャストされてるせいですかね >>68
gcって思考放棄だろ
資源管理の中でメモリだけ後片付けを特別扱いできたからって何ってこと
資源管理にはアルゴリズムがいらないと思うのか? >>76
-100は32bit 2の補数表現で0xFFFFFF9Cになる。
これはunsigned longで4294967196に相当し、符号なしのiにはこの値が入ってる。
ただprintfの指定が%ldと符号付きになってるので0xFFFFFF9Cを符号付きで表示したらやっぱり-100になる。
>>79
-100がsize_tに変換されるのではなく、どちらの値域も含めることができるように両辺がlong long intに拡張される。 >>79
signed longかsize_tかどっちかに暗黙的にキャストされる
-Wallすると警告出るだろうけど サイズがおっきい側にあわせて拡張されるけど
拡張の際に符号付で拡張されるかは、拡張される側の型による でいいのかな?
左辺が size_t で 右辺が (__int16)-1 と (unsigned __int16)0xffff とで変わってくる >>81
なるほど、わかりました
ありがとうございます
>>81-83
比較の計算のために型を合わせるってことですね
納得しましたありがとうございます >>80って>>57?
よく分からん話し方が似てる #defineの効果を全体に適用させる方法は無いの?
書いてあるヘッダを取り込まなくても >>87
ヘッダに書かないメリットは何?
暗黙の効果があると全体の見通しが悪くなるだけだと思うんだが gcc -DUNKO
とかでコンパイル時分岐させるのはよくやる
これで "#define UNKO" 相当 >>90
細かいツッコミだが、
> これで "#define UNKO" 相当
"#define UNKO 1" 相当な %rbp の値を pushq でスタックに退避して他の処理をやって popq で下ろしてきてるから最初に入ってた 0 が出てくる >92
なんか80286〜80486時代に見たアセンブラと違うorz
適当にググった予想
;レジスタ %rbp、%rbx の値をスタックにコピー
pushq %rbp
pushq %rbx
...
popq %rbx
popq %rbp
;コピーしておいた値を%rbx,%rbpに戻す
呼び出し前と同じ値になるだけだね。 >>92
0の入った%rbpをpushqして最後にそれをpopqして%rbpに戻しているから。
pushq, popq の数は合っているので他の値にはならない。 >>89
ライブラリの中なんで書き換えるのはちょっと マイコン系のやつでヘッダのインクルードする前に
マクロ定義すれば使うピンを選択できるようになってるはずなんだけど
当然ながら別にコンパイルされるソースの中には効力がないと 「マクロ定義すれば使うピンを選択できるようになってる」メーカー提供の何かを使った
自前のライブラリで なんとかしたいと?
それライブラリの設計ミスじゃね? ライブラリはコンパイル済みだから#defineしても無駄だろ >>75
Rustは間違いがあるとコンパイラが色々指摘してくれる点でいいよね
例えばこの部分にこういうメモリの安全でない使い方をしていますよ、とか
ここにこんなデータ競合が発生していますよ、とか メモリ管理って言っても大層なことしないけどな
単一コンテキストなら対照的にctr/dtr置けばいいし、複数コンテキストならリンクリストに繋いでrefget/refputでいいし
まあメモリ上限やフラグメント、メモリプールとかやり始めるとなかなか面倒になってくるけど… Cのサーティファイ3級の問題集で
int main(void){
int i,j;
for(i=3, j=10;i-->0 && j-->0;);
printf("iは%d.jは%d\n",i,j);
return 0;}
でiが-1 jが7になるのはどうしてでしょうか? >>103
i-->0 && j-->0が偽になるのはi==0, j==7のとき
iはi--で-1になってjの方は短絡評価でj--が評価されずにj==7のまま 課題や問題としてはアリなんだろうけど、こういうコードはキモいよなぁ ルールを知ってるか?という問題に
実用上どうのと言ってるやつ
わからんから負け惜しみにしか聞こえんぞ 条件に副作用がある式を書くと糞コードになるよ、って例かな >>104
ありがとうございます!大先輩! _(._.)_ 関数ポインタを使っただけで糞コードと言い出すやつと変わらんな 偶然だけどRustがCから唯一受け継がなかったのがfor(;;)文と前置/後置の++と--だね
Rustではfor(;;)の代わりにもっとわかりやすいイテレータを使うfor inになって
イテレータ利用で++と--を使う場面が激減したため +=1と-=1で十分となった #include <stdio.h>
void main(){
int a[5];
printf("%d\n", &a[0]);
printf("%ld\n", &a[1]);
printf("%d\n", &a[2]);
}
結果:
1860819792
140735054207828 ←★
1860819800
1860819796になるところがprintfで%ldにすると★のようになりました。どうして? %dはint、%ldはlong
LP64環境(Linux等)なのだろう
ってか、ポインタを%dや%ldで出すのが変なんだけどね
%pで出しましょう 挙動がわかっててやるのはともかく
なんで?になるのはギルティだな
担当教官が >>114
大昔はコンパイラが直訳だったからね
今はコンパイラが賢いからx++でもx+=1でもx=x+1でも同じ結果
さらにアセンブラ側もレジスタを介すinc命令ではなくメモリ上に直接add 命令で1加算とか
そもそもポインタの++なら対象の型が8/16/32/64bitに応じて1/2/4/8をaddとか
だからアセンブラは今は関係ないし言語としても++がなくても影響なくなってしまってる ポインタから次々読んでいく場合
a=*(p++);
のほうが便利 一種のイディオム化しているがふつうその括弧はつけないな。 まあ、あっても悪さしないし心配なら付けるのは正しいと思う
>>118の言う通りよく見るイディオムになってるので違和感はあるけど char *src, *dst;
while(*dst++=*src++);
みたいな書き方はよく見るけど
最適化とか存在しない古いコンパイラのための書き方だよなといつも思う 最適化だけの問題ではないぞ
while(*dst=*src){dst++;src++;}
では変数名を変更する必要が出た場合2ヵ所づつ書き換えねばならない
→ミスにつながる
それにループが終わった後でdstとsrcは最後の要素を指しているので余計なインクリメントが要るかもしれない 初心者や他言語ばっかりやってた人の誤読回避は考慮する? この頃発見した printf() のフォーマット
% の後に # を付けると x 変換の時に頭に 0x を付けてくれると知り、早速こう書いてみた。
printf("%#x\n", 0xab);
0xab が出力される。
これはいい、と思い16進4桁出そうとしてこう書いた。
printf("%#04x\n", x);
すると 0x は付いたがその後が2桁になった。どうやら 0x の部分の桁数も含めなければいけないようだ。仕方がないのでこう書き直す。
printf("%#06x\n", x);
やった!できた!
しかし幸せは長くは続かない。やがて x に 0 が入った状態でここを通過。以下の出力を得る。
000000 Cは初心者向けではないし、可読性は考慮していない
やりたい事をさっとコード化出来る人に向いている言語 >>124
そんなフラグ初めて見たけど、仕様見たら確かに0以外の時に0xを付加するんだな
いまいち使いづらい 文字列のエスケープシーケンスでバイナリ直接したんだけど、例えば"\x10"の後に"a"という文字を続けようとして"\x10a"って書くと値が大きすぎるってエラーになる。
"\x10" "a"と分割するしかない? Cはプログラマを信頼する言語だ
悪いことをさせない制限より
自由度を優先させている
怠けるやつより進歩する者を優先するのもしかり >>127
> "\x10" "a"と分割するしかない?
それしかなさげ
8進表現は最大3文字となってるから "\0123" は '\012' と '3' になるけど16進表現には桁数の制限がないので "\x10a" を1文字に解釈しようとしてエラーになる
char * の文字列は2文字、wchar_t の文字列は4文字までにすればいいと思うんだけど >>129
ありがとう。やっぱりそうなのね。
ESCシーケンスが書きにくくてしょうがないわ。 >>131
わざわざ調べて頂いてありがとうございます。
#define ESC_UP "0x1b" "A"
のようにマクロで逃げることにしました。
使う側では
printf("今からUP" ESC_UP "UP完了");
と少し気持ち悪いですが。 ESC しか使わないなら
printf("今からUP\033AUP完了");
とかでもいいかも
今更8進数かよって感じもするけど…
もしくは
#define ESC(c) "\x1b" #c
printf("今からUP" ESC(A) "UP完了");
くらいかなぁ ごめんなさい高校のc言語の課題で乱数とじゃんけん対決をして結果と手を動的配列に格納して最後にまとめて結果を表示するというやるをやってるんですが
whileループで代入した結果とその後のforループでカウントしながら表示している値が違うみたいでずっとプログラム見てても何が原因なのか分からないのでわかる方いたら教えて欲しいです.
https://github.com/unko-c/kadai/blob/main/kadai.c >>134
scanfで表示出力は出来ません。分けましょう。
printf("times: "); scanf("%d",&j);
しかし、それでもまだ問題がある。 44: どっから配列が出てきた
デバッガ使えばプログラムの動き見るの捗るから使え
使えないなら怪しそうなとこにひたすらprintfを埋めろ (&janken->man)[i] = man;
printf("man:%2d ",(&janken->man)[i]);
構造体配列のメンバーアクセス方法が間違ってる
case 0:
countDraw++;
この直後にはbreak;を入れること(全てのcase文に適用)
while(i<=j && man<=2 && man>=0) {
ここにmanを入れる意味は?
入力範囲チェックを意図するなら、ここではなく
scanf直後に、範囲外ならcontinueさせる方が良い
無駄もあるけれど、この辺を直せば動くんではないか? >>137
ありがとうございます
break;忘れてたので実行結果変でしたね
ポインタとかは最近やり始めてまだよく分かってないのでちゃんと勉強しておきます >>136
一応whileの直前当たりでかろっくで配列確保してます 44: (&janken->man)[i]
janken->man は配列ではない。
jankenは配列とみなせるポインタだが関係ない
たぶんコンパイルを通すためにこの形になってるんだろうけど
janken[i].man とするべき ソケット関連の質問です。
この前ドメイン名取得してきたのですが、(練習のため)
webブラウザにurlを打ち込んだ時に自分のパソコン内のサーバーソケットにつなげて
htmlで”HelloWorld”と吐き出したいのですが、ドメイン名IPアドレスの紐づけ
ってどの段階でやればいいのでしょうか?
ソケットを作るときにするのかなと思っているのですがそもそもこの考え自体が間違っているでしょうか? 名前-IPを関連させる(D)DNSの話であって、ほぼソケット関係無いような >>141
> ドメイン名IPアドレスの紐づけ
紐づけと言うか解決はgetaddrinfo()でやる
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/getaddrinfo.3.html
文字通りの紐づけなら>>142が言うようにDNSの話だからシステム管理者なりに聞いてくれ
てか、まずOS書いてくれ >>140
ありがとうございます
構造体のポインタを宣言してるのでその表現が正しそうですね
以前の課題だと構造体のメンバのポインタに配列を割り当てていたのでそれと同じように何も考えないでアロー演算子でアクセスしちゃってました >>142>>143
ありがとうございます。
Windows11とVC2021でc++です。
DNSもっと調べてきます。 >>134
33行目と34行目は入れ替えないと構造体の配列のメモリ確保が一つ分少なくなる。 >>141
ソケットで connect() する前には接続先アドレスが分かっている必要があるが、
そのアドレスを調べるのは connect() 前のどの時点でやっても良い。
というか後々ソケットのconnect()で利用するかどうかとは無関係に調べて良い。 このスレの猛者が書く>>134の課題ってどんなコードになるんやろ? VisualStudioをつかっています。
_MSC_VER
これって(マクロ?)VSのバージョンを表す定数を返すと言うことで間違いないでしょうか? #if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
これの意味がよくわからないのですが
(_MSC_VER)というマクロが使えて
かつ
その値が1200以上であるなら
#endifまでをコンパイルする。
# pragma onceはこのコードが乗っているファイルと同名のファイルが
既にインクルードされているならこのファイルをインクルードしないと言うことで
合っているでしょうか? 合ってる
https://docs.microsoft.com/ja-jp/cpp/preprocessor/predefined-macros?view=msvc-170
VisualStudioの1200以降の環境ならごにょごにょするって時に使う
アンダーバー+大文字で始まるマクロ(変数も)はコンパイラ側で定義するので
勝手に定義してはいけない ありがとうございます。
メンタルやられて退職してしまったので、のんびりとブースト読んでいきます。 自前でユニークな識別子考える必要のないインクルードガードがあるなら
そっち使ったほうが間違いないしね ヘッダファイルの先をたどって行ってよくわからなくなったのですが
ヘッダファイルが全部コメントアウトされているのですが
これはインクルードするときにコンパイラに無視されますよね?
boost/config/user.hppをインクルードするときに最初にインクルードしますって
コメントして書かれてあるんですけど、使うかもしれないから一応置いておいているのでしょうか?
それとも//を外してコンパイルすることが出来るのでしょうか? もしかしてその名前のファイルがインクルードされているかが重要で、
インクルードする中身は関係ない的な感じでしょうか? C言語において配列のリテラルはchar型(文字列)以外存在しないのでしょうか?
例えば以下のようにchar型ポインタを初期化すると、リテラル値"test"の先頭アドレスがstrに格納されると思います。
char *str = "test";
ですが、これを次のようにint型にするとエラーになってしまいます。
int arr = {10, 20, 30};
これは{10, 20, 30}が配列を表していないということでしょうか? 初期化は普通の代入と違ってプログラムを書き易くするために特殊な表現になっていることがあると覚えておいた方が良い。
で、その int 型の初期化だが、{10, 20, 30} は int の配列変数に対する初期化ではないからエラーになる。
int arr[] = {10, 20, 30}; ならエラーにならない。 ごめん。間違えた。
> {10, 20, 30} は int の配列変数に対する初期化ではないから
↓
> {10, 20, 30} は int の配列変数に対する初期化だから >>159
一応はコンパウンドリテラル (複合リテラルとも言う) というものがあってこう書けなくもない。
int *arr = (int []){1, 2, 3};
だけど文字列リテラルの生存期間が常に static なのに対してコンパウンドリテラルは
それが現れる場面に応じて static な場合と automatic な場合があるのでちょっとわかり難いね。 配列型のリテラルは、char型のみ使用できる特殊な形と言うことですね。
ありがとうございました。
>>159の下の文のarrは*arrの間違いでした。失礼いたしました。 文字列リテラルはアドレスを持つので左辺値ですよね?
いま読んでいる参考書に右辺値だと書いてあるのですが… というか、右辺値と左辺値の違いってアドレスを持つか持たないかの違いだと思っていたのですが
違うのでしょうか? え、右辺値と左辺値の違いってイコールの左辺になりえるかどうかじゃねーの? >>164
左辺値です。「アドレスを持つか」という分類でだいたい間違いないと思います。
>>166
「イコールの左辺になりえるかどうか」は語源の話としては正しいですが、現状の語義は違ったものになっています。
規格の "lvalue" に対する脚注でも「オブジェクトに対する "locator value" を表すものと考えたほうがよいだろう」とされています。 >>167
すみませぬ。
アドレスを持たないってどういうのを言うんですか。 >>164
配列は lvalue だが、ポインタに変換する規則が適用された後は lvalue ではない。 >>168
たとえば数値リテラルや算術演算子の結果など。これらに対して "&" でアドレスを取ることはできない。 >>168
仕様上の理屈ではアドレスをもたないものが右辺値 (rvalue) なんじゃなくて右辺値がアドレスを持たないので逆なんだが……。
たとえば
int a=1;
a=2;
というように変数に代入できるが、
1=2;
という式がおかしいことは感覚的にわかるだろう。
a には 1 が入っているんだから a を評価すれば 1 になるはずなのに 1=2; と同じではない。
このとき a は a に入っている値のことであると同時に場所としての性質を持つ。
アドレスを持たないのが右辺値であるのとは対照的にアドレスを持つ (場所としての性質を持つ) のが左辺値だ。
左辺値は現れる文脈によって「値 (右辺値)」に変換される。
左辺値が値に変換される場合とされない場合が上手く使い分けられているから代入が成立するわけ。
一例をあげると以下のような式の途中経過として現れる一時的な値は右辺値であるので、
単項 & を適用できずにエラーになる。
#include <stdio.h>
int main(void) {
int a=1, b=2;
printf("%p\n", &(a+b)); // a+b の結果は rvalue なので & を適用してアドレスを知ることは出来ない
} >>168
int a;
&a //OK.これがlvalue
&1 //NG. これがrvalue
const int b = 1;
&b //OK.これもlvalue
b = 1; //NG. lvalueには書き込み可能でないものもある 164です、ありがとうございます
以下の内容で理解しました
場所としての性質を持つのが左辺値、持たないものが右辺値
左辺値は場所としての性質を持つためアドレスを持つ
参考書には文字列リテラルと配列はアドレスを持つ右辺値だと書いてあります
誤植かもしれませんね
ちなみにですが関数も左辺値でしょうか?これもアドレスを持つ右辺値と書いてあります >>174
関数については関数指示子という概念があらたに登場するのでちょっとややこしくなる。
「関数そのもの」は C では値として扱うことができないので左辺値でも右辺値でもない。
式中に関数名を書くとそれは関数ポインタに型変換されて、その関数ポインタは右辺値。 ついでの補足しておくと、
普通の関数呼出しも (言語仕様の理屈の上では) 関数ポインタに変換されてから解釈されている。
有名なネタとして
(**********printf)("hello,world\n");
というように * をいくつ付けても問題なく通る。
関数指示子が関数ポインタに (暗黙に) 変換されるという規則のせいで結局は関数ポインタとして解釈されるので。 C++だと関数も左辺値とされていて、そのことで互換性の問題が起こったりしていないので
性質の面で関数指示子は左辺値と大差無かったりする。 宣言された関数(のポインタ)はconst左辺値の認識でいたけどC言語だと違うのか?
typedef double(*functype)(double);
functype f;
f=sin; // 可能
sin=f; //不可能 関数は左辺値
ただしsizeofと代入を除きポインタに変換され
そのポインタは右辺値 関数についてまとめると、
関数そのものは右辺値でも左辺値でもない、式中の関数名は関数ポインタに変換されて右辺値になる
(C++では関数は左辺値である)
初心者なので誤植があるとパニックになりますね…
どうもありがとうございました C言語の範囲内なら用語に惑わされず振る舞いだけを考えれば
そこまで混乱することはないんじゃなかろうか (>>176 の例のような変態的なのはおいといて)
C++ の ムーブセマンティクスがなかなか なかなか https://www.toyokawa.jp/
初心者すぎる質問なんだが、C言語系のループは目的に応じて1始まりにする
必要があるとブログ記事で読んだんだが、実際はどちらが良いの?
このブログにように九九を計算して配列に入れる場合に九九だから1始まりで計算して、配列へのアクセスは−1する。
今までやっていたようにゼロからループして、計算するときに+1して、配列にはそのままアクセス。
現場だと何も考えずにゼロからループし、目的に応じてオフセットさせていたけど特にコードレビューで突っ込まれた経験も無いので。 プログラミング初心者なんやが、まずC言語の何からすればいいんや。
初歩的な質問ですまない。 プログラミング初心者なんやが、まずC言語の何からすればいいんや。
初歩的な質問ですまない。 >>182
あと、比較するときも無意味だから<=や>=は使わずに<、>を使えば良いって指示は受けたことがある。
for(i=10;i<=20; じゃなく
for(i=10;i<21; とすれば文字が少なくなり間違えが減ると言ってた。
ただ、ブログをみると、21と言う数字は唐突なので10から20までループさせるのなら <=20を使うべきと書かれている。
どちらが正しいのか? それC言語の仕様じゃなくて現場の慣例に従うべきだろ 変数を定数と比較するなら変数を右辺にもってこいとかの
文法外のコーディングルールは郷に従え としか >>184
とりあえずHello world
これがなにか分からない場合は
カーニハン&リッチー著のプログラミング言語C
という本を何とかして手に入れろ
文庫本サイズの小さな本だが
Cの発明者が書いている本で
基本はこれでOK C言語の構造体ってメモリーの割当って全てで保証されているのだろうか?
ビッグエンディアン、リトリエンディアンで異なるのは分かるのだが
全てリトル、Windowsで動くとして同じなのだろうか?
昔、アプリケーションの保存データを一つの構造体に収納し、それをそのままバイナリーとして
ディスクに出力していたのだが当時から気持ち悪く思っていた。
公式ドキュメントで保証でもされていれば良いのだが。 実行ファイルがそのままで、実行環境のOSのを行き来するならまず変わらんだろう
ソースをコンパイルしなおした結果として同じ配置になるかどうかは使ってるコンパイラ次第
ソースを別のコンパイラでコンパイルした時も同じ配置になるかどうかは使ってるコンパイラ次第
どんな場合においてもなんとかポータビリティを維持しようとするとテキスト化する羽目になる まあ
{
char ch0;
int int0;
}
みたいになるときは
{
char ch0;
char dummy[3];
int int0;
}
って入れてるよ俺は [3]というマジックナンバーがイヤ
詰め物の不定がイヤならmemsetでゼロクリアすれば済むこと エンディアンを合わせて読み書きなんて朝飯前だし
構造体を渡された関数は中でfread/fwriteを1回じゃなきゃいけないなんて縛りはナンセンス
構造体の中に構造体があるときは、その構造体の読み書きも関数化しておけば何も問題はない パディングの距離、何バイトでアライメントされるかを制御したいとなると
コンパイラ依存の #pragma に頼るわ >>191
10人規模のプロジェクトだったが、構造体のデータをそのままファイル出力してた。
特にパフォーマンスを求められる部分でも無かったので、自分でマッピングして出力したかったのだが、現状できているからと言うことで却下。
ただ、気持ち悪さは残る。案の定といってもよいが、Sun Sparkが混在したときは当然問題が出たらしい。
関係ないが、そのソフトハウスって、OracleにInsertした順序でselect出来るって信じているところもあった。
実際、そうなるが気持ち悪い。 C言語で冗長化と称して同じ内容を複数の変数に書き込みバックアップをするってプロジェクトが有ったが、意味有ったのだろうか?
今でも、変数ってプログラマが意図して変更しない限り値が変わることは無いし、仮に変わったとしたらもうプログラマレベルでは対処できない問題だと思う。
あと、そんな可能性があったらループ変数だってループ中に意図せずに変わると思うが。
(ハイレベルな一般的なアプリで、OS保護下で動くもの、DMAとか他ハードウェアとメモリを共有するような低レベルな話ではない) 昔、組込みやってた時は全部ではないけど特に動作中に変化すると致命的な箇所は同内容を複数の変数に保存していたことはある
製品評価でノイズ試験やサージ試験おこなっていると意外にマイコン内のメモリのデータはよく化ける >>197,198
素朴な疑問なんたが、それ不一致起こしてた場合どっちが正しいと判断してたんだ? >>190
言語仕様としての保証はあんまりないよ。
ABI (Application Binary Interface) と呼ばれる規格を作って同じアーキテクチャでは同じレイアウトにする通例はあるし、
既存のライブラリと組み合わせられないと不都合だからだいたいのコンパイラはそれに従ってる。
x86 (64ビットも含む) については歴史的事情で Windows はマイクロソフトが決めた ABI があって、
Windows 意外 (Linux とか BSD とか) はおおよそ System V ABI を採用してる。
で、自分が作るプログラムがターゲットにする範囲 (開発環境・実行環境) で ABI が共通ならそれでいいし、
違うなら適当に切り分けて対処するとかでも問題ない。
まあ結果的に問題なかったとしても検証せずにやってたんだとしたら良くはないけどな。 >>200
不一致が起きた場合はとにかく最優先でシステムを安全に停止させる
制御不能で暴走させることだけは何としても回避する
その後はソフトリセット処理を実行して再起動させていた PC でもデータが化けることは思ったよりも頻繁に起きているらしい。
データ破損を検出して補正する ECC と呼ばれる機構を持ったメモリもあるんだが、
コンピュータの値下げの圧力と信頼性の高い現代のメモリでは ECC は必要ないという論から ECC を付けてない機種が増えてきてる。
でもリーナスは ECC は要るにきまってんだろという感じの発言をしてる。
https://linux.srad.jp/story/21/01/05/0240202/
実際問題として化けるんだよ、化けたことを検出したり補正したりする機構がいたるところに入ってるから
アプリケーションからは気にせずに済んでるだけで……。 >>192
よく見かける手法だな。ただ、後からメンバー追加したのか以下のようなアホな事になっている件もたまにあるw
{
char ch0;
char ch1;
char dummy[3];
int int0;
} 「メルキオール (MELCHIOR)」「バルタザール (BALTHASAR)」
「カスパー (CASPER)」 という3つの独立したシステムによる
合議制をとっていた。 >>202
チェッサムやパリティビット的な用途なんか
なぜチェックサムを使わないのか……って聞くのは野暮?
>>192>>204
パックや共用体にしとこうぜ >>204
コンパイラによるけど警告レベル上げれば検出できるぞ >>200
3箇所の変数で多数決だった。3つ違う場合はアプリ終了。
ちなみにOSのメモリ保護された普通なプログラムです。
組み込みマイコンでも、DMAアクセスされるメモリーでも有りません。 >>203
>>アプリケーションからは気にせずに済んでるだけで……
なのでOSで保護された上で動くアプリケーションはデータの冗長化は必要ないのでは?
というか、データを冗長化するという方針で作られたシステムもいわゆる神経質という
設計思想があり。 データ認定?された物は3重化されて変数に保管されるが
ループのi,j,kや一時的にデータを取得するaと言った変数は多重化されていなかった。
仮に変数の冗長化が重要だと言うことになった場合。なぜデータ認定されたものだけ冗長化され
ループ変数は冗長化せずに単体で使うのかって部分に気持ち悪さを感じる。
どの変数も「平等に」食らう可能性はあると思うから。 >>201
「変数をバイナリーでファイルに出力する」と聞いてリーダーに求めたのは
メモリーマップ。当然、準備しているものだと思っていた。
ただ、メモリーマップなど知らないし意味も分からない、サンプルを見てくれ?
という指示だった。
バイナリーでのデータ交換をするのにメモリーマップを定めないことに関しては今でも気持ち悪さを感じている。 >>209
> OSで保護された上で動くアプリケーションは
OS では解決できない。 だからリーナスはインテルにマジムカという話。
変数を何か所にも増やすのが意味ないというのは、それはそう。
どうやったってどうにもならんので考えるだけ無駄。
職人技でどうにかできるような規模の小さな組み込み分野ならともかく、
複雑高度なコンピュータで低レイヤが信頼できないなら信頼できない箇所にコストをかけて改善すべき。 >>208
それなら気持ちは分かる
意味は解せぬが >>209
ハードウェアエラーが原因ならプログラムの実行バイナリも平等に化ける可能性あるよね >>204
そんなんテスト通るんか?
テストもせずに放置? アポロ計画だったか、3台のコンピュータに計算させて多数決で決めてたな それとCのようにロジックが追え、時間さえあれば
人でも答えが出せる場合ではなく、
AIシステムのようにブラックボックス化していると、
複数台による合議制もあるかも知れない 深層学習ってニューラルネットワークを多層構造にしたモデルなんだよね。
AI の仕組みの中に (重みづけされた) 多数決が既に組み込まれていると言えなくもない。 >>215
それなら分かる。計算結果を多数決専用のワイヤロジックで決め
また、3台の入力に戻して計算していれば。 >>213
そう思う。本当に冗長化するなら、ストアされているプログラムも
カウンタ変数も信頼性は平等だと思う。
レジスタに収納されてればより信頼性が上がると言われそうだが、
ループ変数だってメモリに退避されていることが多いから信頼性は同じだと思う。 >>220
この場合は出来るハードウェアもあるってのは反論にならないんだよ。
出来ないハードウェアが世の中に溢れてるってのが問題なんだから。 >>221
溢れてて何が問題なんだ?
リーナスは金持ってるかもしれんが世の中ECCマシンを買える奴ばかりじゃないんだし >>222
安ければデメリットもあるのもしょうがないといえばしょうがない話ではあるけどね。
デメリットはない (あるいは十分に小さい) と言い張ってインテルは ECC なし製品を推し進めたけど、
実際にはそうじゃないことがわかったとなれば文句を言いたくもなるだろう。 >>223
> 実際にはそうじゃないことがわかったとなれば文句を言いたくもなるだろう。
そうじゃないと言ってるけど実際どれくらいあるんだ?
仕事で上に書いたようなサーバーでシステム構築してたけどメモリーエラーなんて見たことないし >>210
WindowsでのBITMAPFILEHEADERとか主要なファイルヘッダの構造は全部構造体で定義されてるから気にしたことないなあ
ダミーパディング込みで
気になるなら定義部分を見てみるといい
余計なパディング入れないプラグマとかも使われているはず >>226
> それは、Microsoftは今調べているドライバの問題から、Windows XPのシステム・アプリケーションのクラッシュの主な原因がメモリの欠陥にあることを知ったからだ。
えっ?w リーナスもMSもECCメモリーがーって騒ぐ前にやることがあるだろw >>224
20年間プログラマをやってたが、勝手に値が変わっていたことは一度もない。
(全てOSで保護されたアプリケーションレベルの経験) 昔宇宙線だかなんだかがメモリデータを破壊するとかそんな記事を読んだ気がそこはかとなく(ry >>229
万が一書き換わってても気付かない事の方が多いだろ >>229
勝手に書き換わっているかどうかどうやって検証したんだ?
ICE とかでわかるもんなの? Windowsならメモリーエラーでブルースクリーンになるよな ならねえよ
「何となく調子悪い」PCがmemtest86で問題発覚はあるけどな 再現性がまったくないから
端子の接触不良か熱暴走で片付けられると思う Cで変数を分散するって話は人生で一回だけ。
それ以降は、どの言語でも意図して変更していなければ絶対に変数は変わらないという事を前提にコーディングしている。
でも、問題は無い。 >>231
ケースをシールドしたり、信号ラインを絶縁して対応していると思われる。 while(1){
a(&x);
if(x==1) break;
b();
}
ってコーディングを禁止している案件もあった。break文じゃなく、しっかりと条件式がfalseになるように書けとのことだった。
ただ、このやり方って入門書にも書いてある普通な方法だと思うけど。ループの中間くらいで抜けたいときはその後の処理をifで実行できないようにしていたので可読性は悪かった。
もちろん continue も封印されていた。
while(x!=1){
a(&x);
if(x!=1) b();
}
みたいに inline関数ならオーバーヘッドもないはずだしな
それで何が聞きたいんじゃ? 俺なら
a(&x);
while(x == 1){
b();
a(&x);
}
って書くかな 理不尽だと思われるコーディングルールも歴史があってそうなってたりするから
長いものに巻かれるしかない 俺なら嫌味のように
{
bool need_break=false;
while(... && !need_break){
//前半処理
if(!(need_break=...)){
//後半処理
}
}
}
とでも書くかな あと制御文の括弧前にスペース入れるのは少数派なんだろうか… 個々の場面で不適切でもチーム全員が適切に判断できないようなら
比較的マシそうな側に統一するルールにも合理性はある。
それとか「わからんかったらこうしとけ」みたいな口伝が
拡大解釈されていったりするのもありそうな話だ。 >>249
Google のガイドでは if や for の後に空白を入れる方針になってる。
私は入れないけど。 >>247
それが無限ループになるというのが読み取り難いからではないかな。
初期化やインクリメントの部分を省略したら単に何もしないのだろうと類推できるけど、
省略された条件式が真に判定されるのか偽に判定されるのかというのは例外規則として知ってなきゃわからない。
慣用句 (イディオム) と化してるので慣れてしまうと普通に読めるけど、
while(1) のほうが明示的な分だけわかりやすいのかもしれない。 関数っぽさをなくすためにスペース空ける方がいいと思う >>252
while文で無限ループを作れるにも関わらず
Rustではloop式を導入してる点が興味深いよね
loop文ではなくloop式なのでbreak 値; で値を返せて凄く便利 >>254
ループとしては無限ループにしておいて break で抜けるような構造は良くないといえばあんまり良くないんだけど、
そうは言っても存在する以上はその場合を明示的に表せるような構文があると便利ってのも確かで、
そのあたりは設計思想の違いとしか言いようがないよな……。 >>255
その構造が良くないというのは自分も昔はそうだったが単なる思い込みだと気付いたw
さらにwhileは先頭でif break、do whileは最後でif breakしているだけであるし
ある程度計算を進めてから途中でようやくif breakできないとwhileだと困ることもloop式で解決された
さらにループを抜けてbreakしたい時は値を返したい時が多いからloop文ではなくloop式が非常に便利 >>251,249
K&R2 では if や for, switch の後にはスペースを入れますね
私は基本的に K&R2 に沿って書きますが、関数の始まりを示す { は例外的に宣言に続けて書きます
int main() {
return 0;
} >>247
俺は使うよ
while(1) だと警告出るから >>260
こう書くとbreakやgotoが嘘つきに見えるな #define DEATH_MARCH for(;;) #define DISALLOW_BREAK for(;;)
#define FOREVER for(;;)
DISALLOW_BREAK FOREVER{
...
if(...)break;
} >>261
正規表現ライブラリとか使って、複雑な制御を見えなくするのも一つの手かも?
自分のところのbreak continueは嫌がられるが、他所なら見えないので。
結局機械語になれば、中でGoto(jmp)しまくっているわけなので。 jmp命令は構造化プログラミングで問題視されるgotoとは違うぞ ダイクストラは「高級言語では」という限定をつけてgotoを問題視していたのであって
アセンブラや機械語に出てくる分岐命令はあの議論の対象外だ >>267
だから >>264 は見えないところでやってる分には知らんって言ってるんだろ。 >>268
てことは結局何も言ってないのと同じだな
Cを使えばjmpが見えなくなるなんてくだらん話は
break continueを禁止する理由とは無関係だ K&Rでもgotoは醜いが使わないと余計な変数や不自然な構造が必要になるからねーとクギをさしてる コードが80x120に収まれば俺はgotoなんて気にしない >>271
そういうのもloop式導入で解決するから導入しよう 抜け出しgotoは分かる
飛び込みgotoはつらい 構造化プログラミングを盲信する気は毛頭ないが
それは違うぞ
抜けだしであろうが飛び込みであろうが
ループの端に設定された条件に従わない分岐は
ダイクストラが問題視する対象だ MISRA-C でも、制御パスを変える、
goto, 複数return, (多重脱出からの?)break/continue などは禁止。
だから、ループ内で、やたらとフラグを持ち回る
でも、Linux では、
早期return, goto でエラー処理をまとめたりするから、フラグを持ち回らない >>275
そんな無意味な制約を課しているとダメなプログラマーになってしまうね
>>276
MISRA-Cは本末転倒としか言いようがないね
結局その無意味な制約によって目的としたメモリ安全性などの成果を得られなかった
その長年の未解決だった課題はRustが全く別方向からようやく解決した >>277
おまえさんもダイクストラみたいに学会誌に投稿したら? switch以外のbreakは制御式にない条件での脱出
continueは違う グローバル変数禁止プロジェクトがあって、固定値が全てリテラルでばらまかれていたので、仕様変更でチーム員は苦労してた。
自分の担当箇所は謎関数を一つ作り、そこから値を得ていた。 >>282
グローバル「変数」と「固定」値がリテラルでばら撒かれてるのは全然違う話だが?
苦労してるのはお前さんの能力に問題があるんじゃ… マクロは使わんのか?
ただの素人のスパゲッティだな センス悪いやつがいるせいで
必要なものまで制限されるんだよな
ロクに精査もせずに横暴な制限を作るやつらも
センス悪いやつの一員 昔グローバル変数はなるべく使わないようにねってお願いしたら、グローバル変数が関数内のstatic変数になって返ってきて状況悪化させしまったことを思い出した…
依頼は正確でないとな >>287
望んだ改善ではないにしてもグローバル変数よりは関数内static変数のほうがマシで、悪化はしてないのでは? 必要なものが制限されるのは腹立たしいだろうけど、
現実にセンスないやつが今、現場にいる状況で比較的マシにしようと思ったら制限も已むなし。 int *just_function(void)
{
static int not_global_variable;
return ¬_global_variable;
}
struct common_variables
{
int fool;
int jerk;
int idiot;
};
struct common_variables *a_function(void)
{
struct common_variables cv;
return &cv;
} static struct common_variables cv;
だった
笑い処でミスってどうするw やりたいことは分割統治なんだよね。 プログラムを機能単位ごとに分割して部品にしたいの。
部品を束ねた部品があって、それを束ねて大きな部品にして……という綺麗に階層的な依存関係にしたいの。
色んなところからアクセスされるものがあるのが目に付くと綺麗に分割できてねぇなあと感じるという話であって
言語機能としての「グローバル変数」を使わないようにすれば綺麗になるというわけではない。 グローバル変数一つ新規に作るのに何枚も書類を書かないといけないプロジェクトがあって、
その時は一つだけ管理テーブルという名称の構造体を作成登録した。
その後は必要に応じて構造体にメンバーを追加した。
追加の場合には許可がいらない。 int型のグローバル変数が2つあればvoid*アドレスを分割して突っ込める
291みたいなstructへのポインタ突っ込んどきゃやりたい放題だよやったね! C++ の singleton クラスと
関数内static から戻ってくるのも 似たようなものになる?のか? ref class SampleCls
{
internal:
property int A[int]
{
int get(int n)
{
int value = n * 100;
return value;
}
void set(int index,int n)
{
}
}
};
SampleCls objを実体化させた後に
s = s + "n= " + obj.A[i]+ "\n";
を5回繰り返したら0,100,200,300,400になったのですが
0に100をかけると100になるのでしょうか? A[i]の値がどんなふうに決まっているのか知りたいのですがよくわかりません
どなたか教えていただければ幸いです。 すみません、解決しましたSet()とget()の動きをちゃんと理解していなかったことが
原因でした。 まず、自分が何の言語で書いてるか理解したらもっと早く答えが手に入ると思うよ… ダイクストラって名前を聞くたびに大工が屋根の上で仕事をしている姿が浮かんでしまう アルゴリズム系でかっこいい名前はダイクストラとラグランジュ malloc,freeを多用すると断片化でいずれOSが落ちるってのは
Windows11やLinuxでも起きる問題ですか? 正しく使っていれば問題ないということでOK?
なんか、正しく使っていても断片化が発生するみたいなのを聞いたもので 昔のCPUならともかく
MMUを使ってるOSなら断片化しないだろ MMUのページサイズとmalloc/freeの管理サイズは全然違うぞ >>308,310
断片化は発生するだろうけど、そのせいでOSが落ちるなんてことは最近のOSではたぶん無い。
断片化によるメモリ確保失敗によってアプリが落ちることはあるかもしれない。
「正しく使っていれば」という条件で質問されても何をもって正しいと言うのか示してもらわないと答えようがない。 1MiB以上と未満で挙動を分けているmallocはよく見かけるね >>308
実装を知っていれば意図的にフラグメントは起こせる、という程度で気にしなければ普通起きない >>310
32bit環境なら大きい領域は早めに確保するか、
あるいはmallocじゃなくAPIで確保したい領域のアドレスを逆方向から取得 >>308
普通のアプリ動かしているだけなのにOSが落ちるとすると、そのOSは何かおかしい。OSにバグがあるのではないか? 普通に車を運転してたら事故った
車に欠陥があるはず 九州のタクシー暴走事故はプリウスのせいだと思っている。 プリウスの制御プログラムを書いた人、ここにいませんか? >>318
それは今回の話には当てはまらない。普通のアプリを動かしていたらアプリが落ちた、だったら当てはまる。
今回の話を喩えるなら普通の車を運転していたら道路が陥没したみたいになる。OSの方が落ちたんだから。 そうか?
池袋事故では最後まで車の欠陥を主張してたぞ
普通にって表現は、あくまでも本人の主観だからな 上級国民は医師に運転を止められていた欠陥アプリなので、譬喩に用いるには特殊すぐる。 常に自分を疑え、なんて根性論めいた主張には興味ないし
弁護士に譲歩的なことを言うなと指示されて本当に思っていることと違うことを陳述するのもこの議論とは関係ない >>308
多用、ってのがおかしいな
一ヶ月も動かし続けてたらどうしても多用になる
それで落ちるようなことはWin95とかの時代の話だろ >>308
malloc,freeを多用すると
解放し忘れが多くなり
メモリが断片化して
新規メモリが確保できなくなってエラー吐いてんのに
エラーチェックもせずにポインターにアクセス
そしてプログラムが落ちる
さらにOSを巻き込んでPCごと落ちる
でも今時のOSは生半可なことでは巻き込まれない 解放し忘れ(メモリリーク)と断片化は別概念
16byteを4回確保した後に1回目と3回目で確保したメモリだけ解放すると、
合計32byte空いてるのに飛び地になってるから32byte領域として扱えない malloc/freeを多用すると解放忘れが多くなるものなのか? C言語ではなくスクリプトだが、
無限にSubdirを掘り続ける奴書いて動かしたら、OS落ちたな
XPだったが OS名はあえて書かないが
Visual C++のmallocで1GBを256回確保しただけで落ちたな Windowsは昔から落ちやすい印象
なんというか、OS自体もなんか少しユルい上にみんなして色んなドライバ作って組み込むもんだから余計に落ち易くなってんじゃないかな。 Win98で512バイトぐらいをいくつmalloc出来るかと試したことがあって、
10万回ちかくでNULL返した・・・いや、1万回だったかな?。
とりあえずOSもアプリも落ちなかった。 >>249
教えられてないし誰も知らないしwhile(1)で事足りるから
::printfとかもな
わざわざ使ってるやつはアホだと思う 一部のバカに対して言ってる
マジで::printfなんて使ってるやつなんて滅多にいない 誰も使ってない表記法使うアホのせいで改めて調べないといけなくなる
使われてないから敢えて教科書に書かれてないし教科書に書かれてないんだから知らないやつが多数派ってことがわからんバカ 知らなくて馬鹿にされたのかな?辛かったね、大変だったね。カワイソウニ(´;ω;`)ウッ… gotoラベル
構造体のtag名
構造体のメンバ名
それ以外
という概念のnamespaceならある
typedef struct A{int A;} A;
int main(){ A: return 0;}
で4種類のAを区別できるというだけで、ns::A とかの話ではないが ああ
それぞれで固有の識別子を記憶する空間があるから ぱっとみの文字が衝突しててもセーフ
という概念か
コンパイラ記述するときにめんどくさそうね
文意からこっちのテーブルを参照すべきとか 初歩的な質問ですが、
b = a++;
という式はbにaの値を代入してからaをプラス1しますが、
演算子の優先度を考えると、++が優先度高く、=は右優先です
優先度の高い++をしてから代入するように感じるのですが
そうならない理由をご教示ください a++が返す値は、aをインクリメントする前の値だからだよ b=a++;
のインクリメントが実行されるのは式を評価した後 返信ありがとうございます
演算子の優先度を調べると++が=より優先度が高いはずです
式の処理は優先度の高い演算子から処理されると理解しています
そうすると、++が先に実行された後で=(代入)が実行されてもおかしくないと
考えたのですが、どこに誤りがあるのでしょうか? そういう時のために
++i
i++
ちゃんと2種類の書き方が用意されてるんだよ >>351
> 式の処理は優先度の高い演算子から処理されると理解しています
これが間違い。演算子の結合優先度と式の評価順は別。 演算子の結合順位と副作用完了点の概念は別
というか b=a;a=a+1; を1文で書くためにa++ 周りのの仕様を特別扱いして実現してる 返信ありがとうございます
++、--の場合は、前置、後置で
式の評価順が通常と異なると覚えました
式の評価順を理論から理解していないので
忘れてしまって失敗するかもしれませんが、
そのうち定着すると思っています よくわからない場合や使うと分かり辛くなる場合は使わないで冗長な書き方した方が良いかも知れない。
使わなくても最近のコンパイラは最適化掛ければ適当にうまいことやって最終的に作られるコードは同じになる可能性が高いと思う。 b = a++;
の右辺を評価した結果は aの元の値で、副作用として aのアドレスにあるオブジェクトをインクリメントしているのでは
代入されるのは aの内容でなく、アドレスを持たない値で どっちも右辺値としないとまずい
int main(){
int a=0;
int* p;
p=&(++a); // コンパイルエラー
p=&(a++); // こっちも
} : BassClass(
std::format (IdPrefix, index, numBank)),(
std::format (NamePrefix, ++index, numBank))
ちょうどこんな感じのコンストラクタでラッパーするコード書いてたんだけど
インクリメントしてない方までつられて増えちゃうんだよね
C++のコード片でスマソン d = ++a + b-- + --c + a++;
この結果は
++a;
--c;
d = a + b + c + a;
b--;
a++;
だよね
実際はこんな書き方しないほうがいいがw >>362
> d = ++a + b-- + --c + a++;
> この結果は
++a と a++ とが順序付けされないので未定義動作。 両方未定義じゃね?
>>361 の方はちょっと自信ないが >>362 の ++a + a++ はダメだったような気がする 以下のような関数がインラインで実行されてるだけで、評価自体は++が先に行われてるんでないの?知らんけど
int inc(int* a) {
int ret = *a;
*a = *a + 1;
return ret;
} 未定義動作警察だ!
未定義動作の動作は定義されていないのでコンパイラは何をしてもいい
> d = ++a + b-- + --c + a++;
このコードの場合、
++a;--c;d=...; b--;a++;相当のコードを吐いてもいいし、
tmp=a;a=tmp+1;--c;d=...; b--;a=tmp+1; 相当のコードを吐いてもいい。
大抵は未定義動作がないことを前提に最適化をかけるが。
極端なことを言えば、d=42としてもいい。
この文の見た目の動作は定義されていないから fgetsのファイル終了・エラー時の戻り値がNULLなのはなぜですか?
他の入出力関係の関数の戻り値はEOFになっています
いま入出力の勉強をしてるんですが、関数の引数や戻り値が少しずつ違うので覚えるのが難しいです
使っていくうちに覚えていくものでしょうか? 細かな仕様はよく使うもの以外は毎度調べるよ
まあCの関数は数が少ないから全部覚えてるって人も少なくないかも よく使う関数の戻り値調べると面白いぞ
printfが何を返しているかとか、それは何故なのかとか
戻り値を使っている人を見たことがないけれど >>361
こういう場合については未定義ではないが未規定の動作が含まれる。
副作用完了点の間で同一のオブジェクトに複数回の書き換えが生じた場合には未定義の動作となるが、
書き換えが一度の場合はその書き換えがどのタイミングで起こるかわからないというだけで、
未定義の挙動にはならない。 >>368
fgetsの戻り値は文字列へのポインタであり
いっぽうEOFは文字(じゃなくてintだけど気分的には)なのだ 組み込みのソフトしていると
使わない関数が多くて忘れていきます <stdio.h>は使えないとして組み込み系って使える標準ライブラリあるの? 使える標準ライブラリを聞いたつもりなんだが
あと<Windows.h>はOS依存のライブラリな 標準っていっても何の標準かわからん。
ANSI CとかC89とかあるだろ。 ANSI C, C89〜C17 の規格で存在を要求されてるライブラリ
組み込みコンパイラだとそもそもC89かC99しかサポートしてないだろうし、
fileIOとかは欠けてるだろうから何なら使えるか聞きたい
組み込みの環境も多数あるだろうから >>373 みたいな人が普段どういう関数使ってるか気になった それぞれ組み込むシステムに付属してるだろ
一元的な名前はない
ひょっとしたらstdio.hという名前かもしれない 組み込みって言っても小さくても Linux 動いちゃうようなのもあるし、何とも言えんな。 C の規格は「規格合致ホスト処理系」「規格合致フリースタンディング処理系」を規定していて、
フリースタンディング処理系はライブラリとして float.h iso646.h limits.h stdarg.h stdbool.h stddef.h stdint.h の内容に限定している。
この範囲なら実行環境に左右されずに用意できるはずという判断なんだろう。 組み込み向けの最低限の規格があるのか
#defineとtypedefしかないが
なるほどこれなら環境がどんなにショボくても用意できそう ファイルディスクリプタを使ってEOFを知りたいんだけどどうしたらいい?
普通にreadすりゃ0になるからわかるし、そもそもファイルなら
求めたサイズより小さく読めるからわかるけど
ちょうどぴったりでreadしたあとに、つぎのreadをせずに知りたい
feofとかファイルポインタだで使えんがや unblocking modeでopenしたfdをreadして判定すれば ファイルのサイズを取得して、そこへseek するとか?
そもそも、ファイルを開いて、ファイルの終わりにseek できるかも。
元々、ファイルの追記モードもあるぐらいだから >ちょうどぴったりでreadしたあとに、つぎのreadをせずに知りたい
そもそもreadが終端まで来たらつぎにreadしてもファイルアクセスせずに0を返すから同じだろう >>372
よく分かりました
ありがとうございます >>387
後出し情報であれやけど
readしたデータをどこかに送信、最後のデータには最後フラグを立てる
みたいなやつなので、ぴったりのときに困ってたんよ
バッファを2面用意して、すぐ送信せず常に1回貯めて送信するのが
正解なんだろうなぁ・・・ まあいいけど ファイルサイズと読み出し位置から残りサイズ計算するぐらいか? >>389
ファイルサイズわかってるならlseek(fd, 0, SEEK_CUR) で現在位置調べりゃいいだけかと ファイルディスクリプタが0とか"/dev/stdin"という名前のファイルを考慮し始めたらそれはもう無理じゃ? なんかバグやセキュリティホールの温床になりそうだな。 キャッシュとか、同期・非同期処理とか、ブロックされる・されないとか、
ブロックデバイス・シーケンシャルかとか、リダイレクト・パイプとか、
共有の有無とか、メモリ内共有かどうかとか、
そんな事を考えだしたら、キリがない
なんせ、Linux API の7割は、IO の説明だから、10年以上掛かる 1バイト単位なら fdopen() しちゃって FILE * でバッファリングさせた方が楽だな。feof() も使えるし。
1バイト単位ではなく1000バイト単位とか、大きい塊でバッファリングする必要がある場合は自作して feof() みたいなチェックができるようにする。
(それでも FILE * でのバッファリングがあった方が遅いストレージにあるファイルなら読み出し効率上がると思うが)。 以下はライブラリバージョンが1より大きければ処理を有効する例です
#if LIBRARY_VERSION > 1
…
#endif
この「LIBRARY_VERSION」は何者ですか?
どこに定義されているのでしょうか? >>397
少なくとも標準仕様ではどこにも定義されてないです
説明のための例では? MSVC環境ならカーソル合わせてF12キー押せばいい
gccとかは知らん >>397
独習Cからの抜粋と予想して記載します
複数の開発環境で同じヘッダファイルを使用する際の
ライブラリバージョンの差異でエラーとなるのを防ぐための
テクニックです
各自が自分の開発環境に合わせて
#define LIBRARY_VERSION 1などと
定義する必要があります いえ、それはそのライブラリの作者(メンテナンスしてる人)が標準ヘッダ内で定義すべき内容です
ユーザーは>>397を自分のファイル内で使用してバージョンの差異を吸収できます >>398,400,401
説明のための例のようですね、失礼しました
あと、この定数が未定義の場合の値は0になるのですね
そのあたりを理解していませんでした
どうもありがとうございました コンパイル(リンク)時に、同じプロジェクト内の別ソースの関数などを呼び出せるのはなぜ?
インクルードして教えてる訳でもないのに、もしかして全ソースを探しに行ってるんですか? 全ソースから探し出すのがリンク
includeとかで関数宣言だけは見えるようにする必要はあるが。
main.c
-----------
char* func(int size);
int main(){
char* p=func(16);
}
-----------
funcという名前の関数は、
前方宣言(1行目)してるのでリンク時に探しに行く。
リンク時の解決用に定義した関数(とその実装)を.objファイルに一覧としてまとめる。
リンクという作業では、.objと.libと.dllから"func"という名前の関数を探し出す。
見つからなかったり2つ以上見つかったらリンクエラーになる。
古いCだと前方宣言がなければ int func(); 決め打ちで前方宣言扱いしたりする。 >>403
(古典的な)Cではアセンブラソースに変換してアセンブル→リンクされるが
通常の関数名や変数名はアセンブラのグローバルシンボルに変換され
リンク時に他のアセンブラソースから参照できるようになる
一方関数内のローカル変数やstatic宣言された関数や変数はローカルシンボルとして扱われ他のアセンブラソースからは参照できなくなる グローバル変数の修飾子の意味は次の意味で合っているでしょうか?
修飾子なし:変数の実体を定義
extern修飾子:定義済みの変数を参照する
static修飾子:変数の実体を定義して、その変数を他のファイルからexternさせない 適当にググって見つかったexternとstaticの解説
ttps://daeudaeu.com/extern/
ttps://daeudaeu.com/static/ >>408
そのサイト含めいろいろ見て、それをまとめたのが>>407です
念のためどなたかに確認していただこうかと思って書き込みました 自分で色々なパターンでコンパイルして確認しないのかな?って思う。 llvm-14 の、ソースツリーの外にcmake ディレクトリができる下品な感じ、なんとかならないの? >>413
cloneしたディレクトリの直下にbuildディレクトリ作ってそこでcmake 〜 ../llvmじゃいかんの?
今どきソースのディレクトリで直接ビルドしないのは下品というより上品ではないですか ソースツリーの中にbuildフォルダ作るのは上品なん? autotools でも out-of-tree build は出来るようにするのが一般的な作法。
あらゆるプロジェクトでそうしているというほどではないと思うけど、ごく普通にある。 https://llvm.org/docs/CMake.html を見るとソースフォルダの外でビルドしなきゃいけないような感じに書いてあるけど、
https://clang.llvm.org/get_started.html を見るとリポジトリ直下にbuild作ってそこでビルドすればいいように書いてあるから、llvmはお上品にビルドできるのですわ llvm-14
まだゴミw
色んなものがダメになるw char buf[256];
memset(buf, NULL, sizeof(buf));・・・(1)
memset(buf, 0, sizeof(buf));・・・(2)
(1)と(2)同じ事をしていると思うのですが、どっちで記述するのがメジャーですか? >>420
言語仕様に厳密にいうと前者で初期化しようとした場合に buf が 0 で初期化されることは保証されないし、
コンパイルエラーになることもありうる。
整数定数式の 0 がポインタに変換したときに空ポインタになることは保証されるので
NULL が単に #define NULL 0 として定義している環境もよくあるんだが、
仕様上の NULL は「処理系定義の空ポインタ定数に展開する」ということになっていて
整数の 0 を書ける文脈に NULL を書いて通るとは限らないんだ。
そんで「整数定数式の 0」がポインタに変換されたときに空ポインタになることは保証されるが、
定数式ではない文脈での整数の 0 は空ポインタになることは保証されていないし、
逆に空ポインタを整数に変換したときに 0 であるとも限らない。
if 文などの制御式としてポインタを置いても問題ないのは C の制御式は !=0 が補われたかのように動作するというルールのおかげ。 >>421-422
お早いレスサンクス
わかりました >>422
>整数の 0 を書ける文脈に NULL を書いて通るとは限らないんだ。
可変長引数にあるあるの最後に (char *)0 (なんで char * なんだ?)なんかがいい例ですね (ソースtt.c)
#include <stdio.h>
#include <math.h>
void main()
{
double d;
int a;
d = 1.234;
a = round(d);
printf("%d\n", a);
}
$gcc tt.c
/tmp/cc0NPwg6.o: 関数 `main' 内:
tt.c:(.text+0x23): `round' に対する定義されていない参照です
collect2: error: ld returned 1 exit status
こんな短いソースなのに解決できない。助けてー(´・ω・`)
OSはLinuxです >>425
古いコンパイラにはroundがないかもしれない。 gccなら -lmで動的リンクする簡易オプションがある、プログラム内だけで完結したいならコンパイラ付属のmathライブラリのソースも含めてコンパイル 動的リンクだとmathは浮動小数点の扱いが実行環境に依存するので静的リンク推奨 ありがとう
gcc tt.c -lm
でコンパイル通りました。 割とよく使う標準ライブラリなのに一々リンク方法をユーザーに選択させるという事の意義を考えるように、おまじないじゃないぞ roundかtruncかfloorかはたまたceilかもしれないrintとその一味のヤバいやつら
こんなもんさっさと追放しろよ 整数型で表せない整数をdoubleで表したい時も稀にある
どうせ前後の整数(±1)は表せない不連続すきっ歯領域だし、どう丸まろうが影響無い部分だよ、って意図の明示に 用途は思い浮かばないでもないが、適切に使われてないケースが多分99% GMPでそ
C++じゃないとちょっと使いにくいけど 多倍長整数とか言ってる人は意図汲めてなくね?
正確性も表現力も不要だけど、それでも整数に相当する巨大数が要るのは極を利用した求根アルゴリズム(方程式解法)とかでしょうよ
たとえば、求めたい関数fの根がその逆数関数1/fの極と等しい事を利用するとか
もしdoubleの範囲を多倍長整数/任意桁数演算で308桁を陽に扱必要があるけど、そもそも極判定は指数部のみで行えるわけで、各桁の数字を陽に保持する意味が無い
一方で指数が巨大なdoubleを生で足すのは悪手
丸めれば各々の積分経路での評価値は真値から一旦遠ざかるけど、一貫した丸めを行う限りは10000万回も足せば互いに相殺されて均される ちょっと拵えすぎたような設定だったかもしれないけど、300桁を陽に保持して、ハードウェアの恩恵も無しに一万回加算とか、向かないどころかあまりにも非現実的過ぎる例もある
という例程度に
あとdouble使ってればinfが返ってくる可能性があるのが最大の利点
もしinfを引き当てられれば、それを与正入力がその浮動小数点実装における最高精度の解だと理論的に保証される 訂正と補足
それを与正→与えた入力
(1/f)(x)→inf
と
f(x) → 0
と
fの根はそのx
は論理的に同値 INF見付かれば恣意的に収束/発散閾値を調整しなくてエレガントだよな
俺は素性の事前に分かってて留数定理使えるような関数くらいしか扱わないから、気にせずそのまま足しちゃうわ
積分経路は(楽だから)正方形に取り、均等に4分割して極のある範囲を再帰的に絞り込んでる、下手にニアミスしたりするとかえって桁落ちしたりして整数倍からズレる
±0.1くらいなら、きっと極を囲めてるものと想定
Cで数値計算入門みたいな本で勉強してるけど、浮動小数点の特殊値とかエラーの扱いとかの記述が一切抜け落ちてて困る 実質ハードの実装に収束(発散)判定任せて綺麗に見えてるだけだがな
しかし比較無しに符号、複素数なら東西南北まで得られるのは便利 20年くらい前、Windows98が使われてた頃なんですが
char s = ''; // ←シングルクォーテーション2個
っという書き方が許されてた記憶があるんですが、記憶違いかな?
今Linux上のgccでコレをコンパイルすると「error: empty character constant」になる あえてなのかバグなのかは知らんけど20年前のコンパイラがそういう記法を通してたってだけだろ >>445
冷静に考えてみたらコンパイラもOSも違うからそういうことだな NULL 「何もないよー」な意味をあらわす単語
空文字 長さ0文字の文字列のこと
この解釈でOK? 文字と文字列は違う 今話題に上がってるのは文字のほう 長さ0文字の文字列なら""(ダブルコーテーション)では? >>444
言語仕様にはそれを通す規定は見つからないな。
少なくとも一文字は必要であることになってる。
C89 ではすでにそうなってるし、後の仕様でも変更はない。
出来る処理系があったのだとしたらあくまで処理系の拡張。
「たとえば 'ab' などのように二文字以上を含む場合は処理系定義」という意味の規定はあるので
雑に任意個の文字を受け付けるようにしたらうっかり 0 個も通してしまったとか、
意図的ではない挙動 (コンパイラのバグ) だった可能性もあるし。 立方根を自作関数で求める方法教えてください、、、、、 >>455
要件次第だけど実装が一番簡単なのは log を使うことだと思う。 だからその
> 何も入っていない
は0から0xffのうちの何なのよ。
1 Byteの領域はあるんでそ。 一番簡単なのは挟み撃ちだと思うけどな
1の三乗は
0.5の三乗は
と1/2づつ狭めていく >>450
NULLはポインターに代入できる「無意味な位置」を表すアドレス だいぶんボケたことを書いてしまった。 (>>456)
式変形をする必要すらなく pow ひとつで良かった。
double cube_root(double x) {
return pow(x, 1.0/3);
} CPU設計だと情報学科なのか電子工学科なのか微妙なところ 普通は自作関数作りたいんですって言ったら
>>463みたいなアルゴリズムを求めてるだろ
何の用途かは知らんが >>471
素子の物理設計からなら電子工学
アーキテクチャからなら情報工学
じゃね?
まあ素子の物理設計なんてやってる学校があるかどうかは知らんけど CPU設計の半導体物性や加工技術は情報学科の範疇外だと思う >>457
精度を組み込み関数より高めたいのかな?
なら一回で十分だよ、ループする必要も収束を確かめる必要もなくて、
y-=fx / f'x
だけで数桁精度が上がる たぶんニュートン法を使いたいけどアルゴリズムを実装できないだけだと思うな simulink coderが便利すぎて手打ちする気にならない件 >>444
許されていないよ
char *ss = “”;
char ch = ‘a’;
の記憶違いでしょう char ch = NULL;
という書き方ならよく見かけた
これはもちろん間違いなのだが '' が使えるかどうかはコンパイラ次第なのでは?
文法的にダメだろうがなんだろうが使えるようにコンパイラ作られたらそれまでだし。
そういやGCCにも void * の変数に ++ とかの計算が出来たりして衝撃を受けたことがあったなあ。
他のコンパイラでコンパイルしてエラーになって発覚。 void *型のインクリって一体何バイト進むんだ? >void *型のインクリって一体何バイト進むんだ?
codepad のC言語 → 1バイト
codepad のC++ → エラー
ISO C++ forbids incrementing a pointer of type 'void*' compilation terminated due to -Wfatal-errors. >>486
1だったよ。char * と同じように計算していた。
お近くの gcc でお試しください。 gcc だと sizeof(void) が 1 を返したりするんだよな。
C++ だとこれがエラーになることを SFINAE のトリックに使ったりすることもあるんで、
どうやって辻褄を合わせているのかよくわからん。 こういう質問が来るたびに自分で試せばいいのにって思う。
仕様がどうなってるのかという質問なら理解できるけど。 単に好奇心で聞いてるだけだと思うよ
実用的に使おうと言うんじゃなく
というか関数ポインタも1バイトになるのかw 汎用ポインタとして void * で受けておいて
char * でキャストすることなく そのポインタを 1バイト単位で操作できたとしても
*で実体を取得する瞬間にキャスト必須になるし どうなんだろ ただのうっかりミスだと思うんだが
修正するとコンパイルできなくなるんで仕様にしてしまったのか >>493
> というか関数ポインタも1バイトになるのかw
んなわけないだろw
関数ポインタは普通に4/8バイトだよ
関数のサイズが1バイトになる
http://codepad.org/zwItkWg3 >>495
Cスタイルキャストだとあまり気にならないかもしれないけどC++スタイル2回重ねるのはちょっと嫌になる。 >>499
関数ポインタが1バイトとか言ってたアホがいたんだけどw
てかお前意味わかってないだろ >>501
文脈を踏まえれば >>493 が言ってるのは「関数ポインタでも (インクリメントで進む量は) 1 バイト」というのは理解できるだろ……。 文脈?
> gcc だと sizeof(void) が 1 を返したりするんだよな。
↓
> というか関数ポインタも1バイトになるのかw
恥の上塗りかよw >>503
↓これを踏まえてのsizeof(void)だろ。なんでポインタそのもののサイズが出てくるのよ。
>void *型のインクリって一体何バイト進むんだ? スレチだったら申し訳ない
とあるフリーソフトが起動しなくてdllファイルを読み込んでないのが原因っぽいんだけど
VSでdumpbinを使って関数を調べた所LNK4044のエラー 〇〇.dllは無効です、無視されます
との文が出るんだがこうなるともうdllに原因があるから対処しようがないってこと?
ここから修復出来る方法ありますかね >>507
状況によるのでその情報からだけではわからない。 ぶっ壊れではなく、OSにVCランタイムが入ってない可能性
Dependency Walker (https://www.dependencywalker.com/) で
その DLL をトレースしてみて、そいつが vcランタイム 要求していないか確認する
(そして古いverのVCランタイムをどうやって入手するかという話に) >>500
C++ だと void * のインクリメントがエラーになるので C限定のお話やね ガチ初心者なんやが、まず何すればいいん?
HtmlとCSSだけ少し触ったことがある ガチ初心者なら、なにもC言語に手を出さなくても…… >>511
こういうよくある質問
何答えればいい?ってなるよな >>511
世の中は流動的で、何が正解なのかは後にならないとわからない。
正解の道筋があるわけではなく、たくさんの知識があればどれかが役立つこともあるってだけ。
最初は物量だ。 詰め込め。 こういう奴はめんどうくさいことが嫌いで
とにかく近道が行きたくて聞いてるので
目的地なんて知らんとにかく近道教えろ!ってことなので
教えようがないんよ すみません、visual studio communityを使っています
関数は呼び出すより前に定義の必要があることが分かりました
ですがソースファイル(.c)を分けて、一方に関数を定義すると定義する順番を気にせず使えます
インクルードが必要だと思いますが、インクルードせずに関数を呼び出せます
何故でしょうか? >>519
> 関数は呼び出すより前に定義の必要があることが分かりました
いいえ、宣言しておけば定義は後でもいいです
> インクルードが必要だと思いますが、インクルードせずに関数を呼び出せます
しなくてもできるってことは必要じゃないってことです >>519
#include等の先頭に#が付いたやつはCコンパイラに処理を引き渡す前にソースのテキストに対して行われる編集を指示するものだ。
つまり #include で何かファイルが指定されていたらそのファイルを読んできてその行に挿入する。そしてそれからコンパイルが行われる。
なので #include で指定するファイルの内容を直接そこに書いてしまっても結果は同じになる。 >>519
C言語では関数宣言がなくても関数っぽく使われてるものがあったら int func(); の宣言があるものとして決め打ちする。
.hとかで前方宣言してなくてもコンパイルは通る。
利用側の.cでは引数の数と型と返り値型が分からんが、合ってれば問題なく使える。
間違ってた使い方をしたときにエラーを出せないから極力避けるべき(コンパイラによっては出るかもしれんが)
この仕様はエラーを見つける観点からすればクソなので、長い歴史があるC言語以外では採用されてないはず 暗黙の関数宣言は仕様から削除されてるよ。
C99 の時点でもう項目がない。
互換性の都合で出来るようにしてある処理系も多いと思うけど
警告くらいは出てるはずだと思うんで読み飛ばさずにしっかり見て欲しいな。 まあわかるんだけど
K&R Cの楽しさがどんどん消えていく寂しさが・・・ みんな>>519の意味がよくわかるな
というかこれらの解答であってるの? 昔大学の授業で使ったTurbo Cで
printf()等がincludeせずに使えた。
warningぐらいは出てたかも。 警告出てもコンパイル通ることあるよね
大学のシステムプログラミングの授業の教科書のサンプルコード、インクルード不足で警告よく吐いてた どんなコードでもラベルがどこかで定義されてる限りコンパイル・リンクはできるんだよ
実行時に望みの結果にならなかったり最悪保護エラーになったりするだけ コンパイルエラー・リンクエラーになるコードなんていくらでもあるだろ何言ってんだ。 動的リンクってやつかな?
C言語はDOS時代に独学でやってたんで(大学はコードの書き方しか教えてくれんかった)どうしても
「宣言だけしておけばコンパイルは通るけど、リンク時に実態が無いとエラーになる」
ってイメージが。 >>531
無関係。
動的リンクは実行時にリンクする (いわゆる DLL とか so とか) 仕組みで、ホスト環境側の機能。
暗黙の関数宣言は暗黙に宣言する言語機能。 ごちゃごちゃしてきたな
>>519に戻って「プロトタイプ宣言しなくても参照できるのは何故か」と言えば
古典的Cでは関数名は単純にfunc()→_funcというアセンブラシンボルに変換してるだけなので
別のソースでも同じ名前で定義してさえいればリンクは通る
ただCでは引数をスタックに積んで呼び出すので引数の数や順番が関数と呼び出し側で統一されてないと引数を正しく処理できないので見つけにくいエラーを起こしたり最悪スタック上の戻りアドレスを書き換えてしまって停止する
だからインクルードファイルでプロトタイプ宣言して統一しようということ
C++では[関数名_引数の数や種類]というアセンブラシンボルに変換するので、正しい引数で呼び出さないとリンク時に見つからないと言われる
それ以前にプロトタイプが必須になってるけど 519です
遅くなってすみません
皆さんありがとうございました
まず、宣言と定義の違いを理解していませんでした
同一プロジェクト中の別ソースにある関数を、宣言しないで呼び出せるのが何故か知りたいです
戻り値がint型だと暗黙の宣言で使えるようですが、戻り値がchar型の関数を呼び出せます
関数を呼び出すより前に宣言されているはずなので、先に関数を記述したソースが解析されているということ??
試しにその関数をmain関数の後に持ってくると当然コンパイルエラーになります
恐らく>>533に頂いた回答が近いと思うのですが、リンクを理解していないためか理解できません…
勉強不足で質問するのも申し訳ないのですが、ご回答いただけると嬉しいです >>534
コンパイラは宣言の辻褄が合っていると「仮定して」処理する。
宣言の辻褄が合うようにするのはプログラマの責任。
辻褄が合ってないときにどうなるかは言語仕様上は未定義のなのでなんとなく動いているように見えてもあてにならない。 C言語に慣れない頃はmain関数はファイルの最後に書いて、
呼び出される順番にソースの上の方に関数追加していったわ。
-----ccc.c-----
int FuncB(){
return 1;
}
int FuncA(){
return FuncB();
}
int main() {
return FuncA();
} >>537
呼び出しじゃなくて依存の順序で書くね
宣言はなるべく書かない! >>537
簡単なプログラムで急いで書いてる場合や
関数の仕様を手探りで作りながら書いてる状態ならそんなでもいい
ただFuncBからもFuncAを呼び出すようになった場合困るから >>534
何を悩んでるのかよくわからないが
今のCPUは8ビットレジスタなんて持ってないので戻り値がintでもcharでも戻り値の入ってるレジスタは同じになる
だから戻り値charの関数を暗黙のint関数として呼び出しても結果は特に問題なく使えるはず
ただ8ビットより上のビットにゴミ(不定値)が入ってる可能性はある >>541
(現代の一般的な) 呼び出し規約的には区別がないので動的リンクだと割と問題なさそうだが、
最適化が絡むと何がどうなるか想像もつかない。 やはりCを上っ面でなく根っこから理解するにはアセンブラの知識も必要だな コンパイラやアセンブラのnパス(ソースを読み下す回数)って仕様を思い出した。
DOS時代にアセンブラは2パスでCコンパイラは1パスが普通だと聞いて、
Cで先に関数/変数を宣言、定義しないとエラーになるのは1パスでコンパイラが知らない関数/変数が出てくるからだと思ってた。
正しい理解かは知らない。ラベルとかはgotoの後に出てくることもあるし。 >>544
バックパッチで処理できるのでコードの頭から読みなおす必要はないよ。
知らない名前が出てきたときに型かもしれないし変数かもしれないってのでは構文解析が難しくなるが
goto の後ろにくるのはどこかで定義されているラベルだと決め打ちできるから単純な処理でいける。
(gcc だとアドレス (を生成する式) を goto に与えることも出来るように拡張されてるからもうちょっと複雑なことをしてると思う。) gccはプロセス置換なんかで生成した一時ファィルを食わせられないから、少なくとも2回以上はソース通読してると思われる 関数コメントを書く場所だけど、
➀ヘッダファイルの関数プロトタイプ宣言の頭に関数仕様コメントを書く
②Cファイルの関数実装本体の頭に関数仕様コメントを書く
③両方に同じ内容を書く
のどれが今の多数派?
昔は②が多かった印象だけど最近は➀が主流なのかな? 外部仕様ならユーザーに読ませるからヘッダだし、内部仕様なら逆に見せるべきでないから本体、とかだろ。 将来Libファイル化とか考えると①の方が合理的かなとは思う。
VisualStudioの関数参照で、自動でコメントも表示されたと思ったけど、
そのときは①と②どっちが優先だったのかな? 質問失礼します
あるCのプロジェクトを見ていて
typedef struct X X;
struct X { ... some fields ... };
って記述がソース中の随所で見受けられますが、これ以前にもstruct Xの宣言がないのにtypedefできるのが非直感的に感じられます。これはtypedefを宣言するのと同時に、初めてここでstruct Xも宣言しているってことなのでしょうか? それは構造体メンバーの中にその構造体自身へのポインタを含めさせるためのトリックじゃなかったかな
struct HOGE{
色々なメンバー…
struct HOGE *next;
};
とやろうとするとHOGEの定義はまだ終わってないのでundefinedエラーになる
typedef struct HOGE STRUCT_HOGE;
struct HOGE{
色々なメンバー…
STRUCT_HOGE *next;
};
これなら通るはず(?) struct でメンバの定義がない不完全型はポインタ変数のみ宣言出来るので再帰的なやつも大丈夫だ。
ポインタはサイズが分かるから。
ポインタでない普通の変数はサイズが分からないので作れない。 >>550
その場合の typedef struct X X; の struct X は C99 の 6.7.2.3 にある
「不完全構造体型又は不完全共用体型を宣言し,その型のタグとして識別子を宣言する」
に該当する。
つまり struct X の宣言にもなっているという解釈で正しい。
あえて typedef を先に書く必然性はないんだが……
仕様にはこういう形でも書けるという例が載っているので考えなしに真似してるだけかもしれん。 >>554
詳しい説明ありがとうございました
確かによくよく考えると
typedef struct X { ... some fields ... } X;
と同じでしたね
こちらは違和感ないんですけど確かにこちらもいきなりtypedefのdeclspec内でstruct X { ... some fields ... }初めて使ってますね struct Y;
struct X {
struct Y* next;
};
struct Y は struct X と同じでした typedef struct X {
struct X *hage;
char a[0];
} X;
これはokだが
typedef struct X {
X *hage;
char a[0];
} X;
これはだめやろ C++ ではアリだが、それはそれとして配列の大きさは 0 は駄目だよ。 配列要素0個はgccの拡張やね、標準規格に取り込んで欲しいわ >>562
それはポインタと何が違うのん?
もしかして自動reallocとか? NFTゲームでのユーザー活動が20倍増加 DappRadarレポート
分散型アプリデータ企業DappRadarは20日、Blockchain Game Alliance(BGA)と共同で、
ブロックチェーンゲームについてのレポートを発表。2022年第1四半期(1−3月期)は、
前年同期と比べて、ユーザーの活動が2,000%増加したという。その他、様々な角度
からデータを報告した。
ブロックチェーン/NFTゲームへの第1四半期の投資総額は、約3,200億円(25億ドル)に
到達した。レポートは、もしこのペースが維持されれば、2022年全体の投資額は約1.3兆
円(100億ドル)に達する可能性もあると予測している。なお、2021年の年間投資総額は
約5,100億円(40億ドル)であった。
レポートによると、22年1Qの全ブロックチェーンアクティビティのうち、分散型ゲームアプリ
ケーションによるものが半分以上(52%)を占めていたという。ゲームをプレイすることで
お金を稼ぐことが出来る「Play-to-Earn(P2E)」のゲームもこれを牽引している。 >>564
だからそこで[1]を指定しないとならないのがダメダメって話
namestr[100]を確保するコード書いてみ >>565
NFTはゲームに絡んでいる部分だけは面白そう struct Header {
int total_size;
char naemestr[1];
};
本質的には int total_size + naemestr可変としたいが
sizeof(struct Header) は char naemestr[1]; を含むのでキモいことになる >>567 >>569
二個以上のメンバからなる構造体である場合に最後の要素は不完全型であることが許される。
つまり char a[]; と書く分には OK だし、 sizoef で構造体の大きさを調べたときにはこのメンバを抜いた大きさが返ってくる。
だけど、規格を総合的に解釈すると (動的に) 割り当てる大きさが 0 であってはならないと思う。
>>564
C11 以降だと VLA はオプショナルだぞ。 >>566
VLA は可変長配列の話、>>564 は可変長構造体の話、全然違うし可変長構造体は C99 で是認されましたよ
ちょっと遅れているんじゃないですか? >>567
[1]だろうと[0] だろうとどうでもよくて、問題は可変長構造体がC++では認められているか否かの話なのでは? >>570
最後の要素が 不完全型な some-type [ ] に限り sizeof は そのメンバを含まない大きさを返すけど
some-type [1] の場合にはそのメンバを含んじゃう
https://ideone.com/7GmZkR >>575
「よりよい方法があるのであえて 1 を書く必要はないじゃろ」というのが主旨。 >>574
確かに、静的可変長とかいい言葉はありませんかね
でも存在自体は昔から知られていましたよ http://www.kouno.jp/home/c_faq/c2.html#6 まあキモいけどサイズが実際より大きすぎるぶんには問題は起きない >>579
キモい?アセンブラでは普通にやりますよ‥‥ 最後が可変の構造体はchar naemestr[1]; なんて定義せずに
#definne Header_getNaemestr(p) (char *)((struct Header*)(p) + 1)
みたいに書く方法もあるよ >>571
配列と構造体を間違えたのは悪かったが
なんで遅れてるって話になるんだ? C++ の提案としては出てる。
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1039r0.html
今のところ C++ に取り入れられる見込みはない模様。
C で実績があるわけだし、変な矛盾はないと思うんだが
仕様として整合性をとるのは別の大変さがあるんかね? ビットマップのカラーテーブル部
データフォーマットの中間部分に鎮座してる可変 XEvent にはとてもお世話になりました
今は使う機会が無くなりましたが リンクリストでlist_head使ってないってこと? >>583
遅れてるからですよ、C89 から話題になっていたことを理解していないからそんな間違いをするのです‥‥ >>589
C89から話題って何のことだ?
理解してるかどうかどうやって確認したんだ?
ああ、しどろもどろってやつかw >>546
そういえば愛用のtccはストリームからも読み込めるけど
まあ全部内部バッファに溜めればワンパスに見えるし、結局のところはわからんぬ
すくなくとも論理的に2パスする必要のある言語仕様的は思い浮かばない プリプロセッサで一度マクロ展開してからコンパイラに渡してるから2パスと言えなくもない >>592
プリプロはパスに勘定しません
pascal こそ最高の正義、でも pascal 以降、おしなべてすべての言語は堕落してしまいましたね‥‥ >>593
アセンブラ以外のすべての言語は退廃と怠惰の産物と心得よ 傲慢か
既存のコード無視して上書き的なメンテするやつか? >>598
コーディングシート使って機械語を直打ちしてた俺に言わせると
アセンブラも贅沢品だぞ DOS時代にコプロセッサとか言うのあったけど、実際に使われてたの?
解説書を見ること無くWin時代に入っちゃって。 >>592
Tiny C Compiler はプリプロセスも含めてワンパスで処理するよ。
処理が各段階に分離されてないのでコンパイラのソースコードが読みづらいらしい。 GPU もある種のコプロセッサと言えなくもない。 そういう分類の仕方はあまりしないが……。 当時、コプロセッサを「子プロセッサ」だと思ってたのを思い出す。 >>603
486から標準でCPUに組み込まれて
今では自動的に使われていることになる かつてのARMはFPUどころかMMU、Cacheまでコプロ命令で制御してたな。 >>611
487は468SX(486DXの浮動小数点ユニット無し版)用のコプロやね
実態は486DXで装着すると468SXを乗っ取って全部487で実行しちゃうからCo-って感じじゃないけど 『コプロ』なるLSIを追加すると、掛け算を割り算が使えるようになる。
8~16ビット全盛時代、その文句の意味が分からなかったなあ。
BASICで普通に四則演算していたから。 CPUが電卓を使うというのが何ともミステリアスだった 間接参照の間接参照だろ
経験豊富なら余裕で見分けられる int a=1;
int *b=&a;
int **c=&b;
int d=0;
d=**c; /* d == a */ 少しわかった気がします
試してみて理解します
皆さんありがとうございます 関数のポインタとか
関数のポインタを引数に持つ関数のポインタとか typedefすればいい
typedef int AAA_FUNC( int, char *, ...);
int AAA_caller( int, AAA_FUNC*); >**
なんで char **argv が思い浮かばなかったかなぁ・・・。 char *argv[]という初心者をいたぶる陰険な罠を避けたかったんじゃね? GNU MakeよりCMakeが優れてるのはどの辺でしょうか? >>632
CMake はメタビルドツールなので make と比較するようなものではない。
CMake を使う多くの場合で make も使う。 宣言/デリファレンスの記法が悪いというより、=が悪い
両辺を等値(あるいはそうする=代入)というセマンティクスと解離してる 初期化の=は左辺ではなく、左辺で宣言されるものを指してるわけで、頭の中で=以外の記号に置き換えて読むといいかも =と==は、はっきり区別されてるだろ
連動して常に等しいという規則ならマクロでやればいいし A=1
B=2
C=3
A=B=C
PRINT A,B,C >>638
BとCが等しいかの比較結果が A に入る C言語ではA=B=C;でAとBにCの値が入るはずだが C
A=1, B=1, C=1
BASIC
A=-1, B=1, C=1 ちょー初心者
引数付きの関数で引数が空のときにも意味を持たせたい
nanntoka(char adress)なんて関数で
呼び出し側がnantoka()と書いたときも意味を持たせる場合どうすりゃいいの?
null判定でいいんですか? だよねー
やっぱ数値は工夫のしようがないから無理なのかー
やー助かりました C++にはデフォルト引数があるし
オーバーロードもできる
Cでできるかは知らん
int f(const char*s = nullptr); 普通にはできないからやるな
(1) printfみたいにやる方法
(2) __VA_ARGS__でやる方法
があるぞい >>650
printfみたいな可変引数でも第一引数は必要なので純粋に引数なしってのはできなかったはず。 >>651
できるぞ
第一引数なしで可変引数にするときは
void func();
と、省略記号なしで宣言する
ただし言うまでもないが
func();
で呼び出したときの第一引数は不定なので
使い途はない >>654
> nanntoka(char adress)なんて関数で
って書いてあるのに... >>656
> 呼び出し側がnantoka()
とも書いてあるだろ
何が言いたい? >>654
> 第一引数は不定なので
いいえ。 未定義動作です。 >>657
勝手に端折るなよ、 書いてあるのは
> 呼び出し側がnantoka()と書いたときも意味を持たせる場合どうすりゃいいの?
で、答えはできない
つまり
>>654 > できるぞ
がアホだってことな >>654
>第一引数なしで可変引数にするときは
可変引数になってないね
全然意味のない書き込みだね… >>658
不定の値にアクセスしたら未定義の動作だね
何が言いたい?
>>659
幼児レベルの罵倒語が必要か?
654は正しいのか誤っているのかどっちだ?
>>660
では聞くが可変引数って何だ?
JIS X3010にそんな用語はないが int func(void); と
int func(...); に対する言及なしで
int func(); だけ出てきてるからまともな議論じゃないと思ってスルーしてたが
可変引数は >>651 で出てきてそれに合わせてるだけじゃねーの? int func(void); だとそもそも引数なししか受け付けない。
int func(...); だと引数の型と個数を実装側が期待するものにしなければならない。間違えたら未定義動作。
int func(); だと引数の型がわからないまま関数を使う。間違えてたら未定義動作。
int func(...); の第1引数は普通は型を明示するから
int func(const char*, ...); のようになるが。 >>661
いいえ。 一致しない引数で関数を呼出そうとすることが未定義です。 >>664
一致しないって何と何が?
funcについて仮引数は宣言されていない
よって実引数との型の比較行われず
一致にも不一致にもあたらないぞ >>665
いいえ。 どこかに関数定義は存在し、関数定義 (の仮引数) とその関数呼出し (の実引数)
との矛盾 (引数の数があわない・型が適合しない) は許されていません。 可変長引数では無理なのね
>>650の(2)の実装だとどうなるの マクロでコンパウンドリテラルを作ってから (その個数と共に) 渡すという方法が取れると思う。
受け取る関数の型は >>645 の通りではできないけど。
#include <stdio.h>
#define foo(...) bar(sizeof((char[]){0, __VA_ARGS__}), (char[]){0, __VA_ARGS__})
void bar(int n, char* args) {
if(n==1) {
printf("no argment.\n");
} else {
printf("argment is %c.\n", args[1]);
}
}
int main(void) {
foo('a');
foo();
} >>666
話が噛み合っていないな
引数の数も型も比べる相手がいないのに矛盾しようがない
そもそも関数原型を用意しましょうなんていうのはCにおいて後付けの推奨事項に過ぎない
既存のコードを否定するのは影響が大きすぎるからな >>661
自分で「可変引数にするときは」と言っておいて
なにが「そんな用語はない」だよ
頭おかしい fn(void)
fn(int)
こういう2種類の引数を許容したとして
呼ばれた側はどう区別したら良いんだろう
コンパイル時に、別関数にアサインしたらいいのかな
その場合は受け取る関数も二つ用意してやらないと行けないな 区別はできない
引数を見ようとしたら結果は不定になる
単なるバグだよ (2)の想定はこれだった
https://wandbox.org/permlink/EidRL6a8uqiszn2m
これも引数0個のときは##__VA_ARGS__か__VA_OPT__が必要で
まずかったな >>669 関数定義とその呼び出しを比較するって書かれてるのに、きみが無視するから噛み合わないんだよ。 >>674
void func() { } /* 定義 */
int main()
{
func(); /* 呼び出し */
}
どこが矛盾なんだ?
# 迂闊な答えをすると罠があるから気をつけな >>670
その時点ではアバウトな言葉遣いが容認される流れだったが
厳密さを求める流れにあんたが変えたんだよ >>675 その例だけなら矛盾しないね。でも引数渡せないから>645のやりたかったことはできないよね。 >>677
引数が空のときにに意味を持たせるんだったな
void func() { puts("no arguments are given"); }
int main()
{
func();
}
# さっき言った「罠」がまだここにある まともに話す気なさそうだし、もういいや。
C言語では>>645に書かれてるようなことはできなくて、
>>654の「第一引数は不定」はどうせ未定義動作の間違い、
という点に異論が無ければ、これ以上語ることもない。 nantoka()と呼び出した場合、
呼び出された関数は、
nanntoka(char adress)として
スタック上からadressを取り出そうとするが
ここにある値はNULLではなく、不定値(所謂ゴミ)
NULL判定で回避はできない >>678
Once again, once again, you're on your own
Who's to blame? who's to blame? it's such a shame
No-one ever hears your name, or plays your game >>680
> スタック上からadressを取り出そうとするが
だからそれを実行するかどうかもわからんって話
未定義動作ってそういうもんだ グローバル変数 int exists_adress; を介してやれば引数あり/なし のモードを未定義動作を回避しつつ設定できそう
実用性など皆無だが >>682
読み出すまではできるだろ
戻りアドレスか関係ないレジスタの退避値が入っている
問題はここではエラーにならず次にこの値で何かしようとしたらクラッシュする可能性が高い
これは単にコンパイラを騙して原因がわかりにくいエラーを出す方法なだけ
全くなんの意味もない >>684
だからコンパイラは読み出すコードを吐く義務はない
未定義動作とわかった時点で呼び出しすらしないコードを吐く可能性もある
未定義動作ってそういうもんだ 読み出さなければ、実行時エラーにならないだろう
なんで、なるの? 呼ばれた側の関数は、adressに入っている(はずの)値を使うんだぜ
コード吐かなければ、それこそコンパイラのバグになるぞ 実際に呼び出すコードは、呼ばれた側の関数に実装されるが、
呼び出し側の引数セットありと、引数セット無しで、
違うコードが実行されたりするのか? 何が起こっても不思議ではない未定義派と、コンパイラ実装は実質こうなってる派で話が噛み合うはずがないと思うの。 信仰と言うより、勘違いだろう
恥ずかしくて後に引けなくなった感じ 引数セットするのは、呼び出し側
コンパイラが呼び出し側で引数がないと判定した結果、
気を利かせて呼び出さないコードを吐くって一体どういうことだろう
呼ばれた側は機械的にあるはずの引数にアクセスする
呼ばれる側はセットしてないなんて分からないからアクセスしてしまうぞ >「罠」がある(キリッ
とかお寒いこと書いちゃうくらいだしよほど視野が狭くなってたんだろうなぁ stdcall と cdecl の話か?
どっちにしても引数省略されたのかされてないのか呼ばれた方では判らん
C++なら省略の代わりにデフォルト引数入れたりマングリングしたり出来るが
Cではどうしようもない >>688-689,691-692
コンパイルエラーとして全くコードを吐かないという事すら可能なのに何を言ってるんだよ...
今時未定義動作すら考慮して最適化したりしてる時代なんだぞw
https://qiita.com/kaityo256/items/d2677e178be0180482e8 >>686
何か勘違いしてないか
コンパイラが未定義動作とわかったらエラーか最低でもワーニングを出す
コンパイラにはわからないからバグになるんだよ 一体どこのコンパイラがコード吐かずに停止するんだよ >>697
> コンパイラが未定義動作とわかったらエラーか最低でもワーニングを出す
そんな義務はない
> コンパイラにはわからないからバグになるんだよ
同一翻訳単位ならわかるだろ
勘違いしてるのは君、と言うか君の知識が浅すぎるだけ
>>699
存在するかどうかは関係なく規格上はそう言う処理系でも規格準拠という話 法解釈論「人殺しは違法であり罰される」
実運用論「証拠を完璧に隠滅できれば罰されない」
意固地になっちゃってるから何言っても無駄 意固地になるとアスペチックになるのか
アスペチックだから意固地になりやすいのか 意固地もなにも未定義動作なんて規格の話なんだから実運用論とか言われてもねw >>679
第一引数が不定とは、第一引数を何らかの方法で取り出した場合の話だが
おまえさん、その方法はどんな方法を想定しているんだ? >>707
>654が言ってるのはどうせこんなのだろうと思ってた。
https://wandbox.org/permlink/aiZH8Ytc91RyQ7HL
#include <stdio.h>
void func();
int main() { func(); }
void func(int x) { printf("%d\n", x); } 実体記述時と、宣言&呼び出し時とで、引数の型や個数の不一致
コンパイルが通るかもしれんけど、どう動くかわからないし
俺の環境ではこう動くからと、それを信じて採用するには怖すぎる >>709
654は俺でまあそんなとこだが
俺は今679に聞いている
おそらく「654と同じ」とかなんとか言って
自分の手の内は隠したまま人の批判をするんだろうけどな >>711 え? 679 (ワッチョイ 835f-GGE9) だから答えたのに何でよくわからんイチャモンつけられてんの?
いやまぁ、予想通りで結論に異論無いならいいんだけどさ。 省略時のデフォルト引数と(マングリング等による)別実装
C以前の言語でもありそうだし前者は検討してそうなもんだけど見送ったなりの理由があるんだろうか 想定が合ってたということで改めて結論も明記しとくと、
>709 のプログラムが未定義動作を起こすのは不定な x の値を使用するからではなく、
func(int x) に対して引数の数が不正な関数呼び出し func() を行うからであって、
x の値を使用しない場合(例えば関数内を空にした場合など)ても未定義動作になる、という話ね。 >>712
ほらな、やっぱり自分の手の内は晒さない 661の立場だと
void func(int x) { }
・・・・・
func();
は、記述のほうで x をリファレンスしてないからセーフで未定義には該当しないと読めるが
そいう主張なのかな 実装の話
関数側でスタックに詰まれた引数をクリーンアップする呼び出し規約(pascalcall や stdcall) だと
明後日に飛んでいくのか 引き数の値で関数内の処理を分けるか普通に関数分ければいいやん 普通の人ならそうするが、
普通で無い方法が無いかを
いろいろ議論している
暇つぶしとも言う >>718
DLLの呼び出しみたいに呼び出し先の実装をコンパイラが知らない場合
例えば引数をスタックに積む呼び出し規約だと
↓正常な動作
1)戻り先のアドレスをスタックに積む
2)引数をスタックに積む
3)DLL側のコード実行時にpopしてスタックから引数ゲット
4)いろいろ処理してpopして戻り先アドレスをゲットしてりたーん
これが↓異常な動作
1)戻り先のアドレスをスタックに積む
2)なんもない
3)DLL側のコード実行時にpopしてスタックから引数ゲット
4)いろいろ処理してpopして戻り先アドレスをゲットしてりたーん
5)わし、迷子
ってなるんちゃうん?
引数がレジスタ渡しなら、ただ変な数値受け取るだけで済むけど、今ここでの話じゃ限定してないようだし 呼び出しって引数をスタックに積んでから、呼び出すんじゃなかったかな >>725
そうだよ
だから func(int);な関数をfunc(void); で呼び出したらスタックにずれが生じる可能性がある 引数をスタックに積んでから、戻りアドレスを積んでCallするなら、
func関数はスタック先頭位置にあるアドレスに戻るだけではないかな
積まれている引数はその下だからズレないと思う >>727
>引数をスタックに積んでから、戻りアドレスを積んでCallするなら、
逆だぞ
戻りアドレスをスタックに積んでから引数をスタックに積む、その状態でfuncをコールする
そうしないと、次のpopでは戻りアドレスを受け取ることになり、引数を受け取れない
コールされたfuncはpopし引数を受け取って処理(この間にスタックへのpush/popがあったりして)、最後にpopして戻りアドレスを受け取って呼び出し元に帰る 戻りアドレスをスタックに積むのは、機械語のCALL命令が行うんでしょう? VCでアセンブラソース出力させてみました
int main()
{
call(1);
call();
return 0;
}
int call()
{
return 0;
} _main PROC
; Line 2
push ebp
mov ebp, esp
; Line 3
push 1
call _call
add esp, 4
; Line 4
call _call
; Line 5
xor eax, eax
; Line 6
pop ebp
ret 0
_main ENDP _call PROC
; Line 8
push ebp
mov ebp, esp
; Line 9
xor eax, eax
; Line 10
pop ebp
ret 0
_call ENDP フレームポインタってのもあって
まあなんでもいいんです >729
全てのCPUにCALL相当の命令があるとは限らないってことを頭の片隅に。 CALL命令のないCPUにCってどういう風に実装するのかな
キッと神様のような人だろうと思う >>736
C言語で書いたコードが実行できるようなCPUでCALL相当の命令がない奴なんてあるのか?
まさかと思うけどBSR(Branch SubRoutin)とかBAS(Branch and Save)はCALLと綴りが違うんだーっていう主張じゃないよね >>737
汎用機みたいにスタックが無いマシンだとソフトでスタック作るとかする 呼出も戻りも、ジャンプ命令で実装するんかい?
「食らえ、GOTO攻撃!」 >>737
厳密じゃないけど、
push pc
jmp xxxx
:
pop pc
みたいな。push pcする時にjmpのアドレスの次を 途中で書き込んてしまった。
>>737
厳密じゃないけど、
push pc
jmp xxxx
:
pop pc
みたいな。push pcする時にjmpの次のアドレスをpushする必要があるけど。 >739
2000年あたりのスパコンのデバッグやってたけどスタックポインタ自体無かったよ。
汎用レジスタの一つをスタックポインタの様に使ってた。
スパコンのPEはCPUじゃ無いっていうならそれまでだけど。
OSがCで書かれてたよ。 専用のレジスタを用意するかわりにアドレシングモードを充実させてるタイプの CPU もあるとは聞いたことは有る。
複数のスタックを用途別に使ったりする運用も出来るので便利っぽいよ。 リンクレジスタを使うアーキテクチャは
呼び出しも戻りもジャンブだよ >>744
だから>>740に書いたように汎用機みたいにハードウェアスタックが無いプロセッサーは普通にあるよ
でもBASみたいにサブルーチンを呼び出す命令はある(戻りアドレスをレジスタに格納してジャンプする)
スパコンの命令セットは見たことないけど似たような命令はあると思う JMPで呼び出した関数に飛んで、
JMPで呼び出し元に戻って行ってたよ。
RET、それ相当の命令が無かった(使われてなかった?)。 >>749
あれはレジスタはメモリー上に置くって言う設計思想だから >750
富士通。
実機は見たこと無い。
なんかアメリカに設置されてて、日本の端末(FMVにFreeBSDかなんか入れてた)からtelnetで入って作業してた。
入社1年目だったんでテスト作業員+フリーズした場所の特定と原因予想してた。 STM 14,12,12(13)
LR 12,15
GETMAIN RU,LV=72
ST 13,4(,1)
ST 1,8(,13)
LR 13,1 >>753
2000年辺りならベクトルタイプのVPP シリーズの方かな
スカラパラレルはUltraSPARCだし ① struct _Hoge;
② typedef struct _Hoge Hoge;
③ struct _Hoge { int a; };
④ typedef struct _Hoge { int a; } Hoge;
↑の①~④はどれが「定義」でどれが「宣言」かよくわからんです
typedef の def は define(定義)の def ですが
変数作って値を定義していないので全部宣言ですかね? 原則、重複が許されるのが宣言、許されないのが定義
ただし仮定義のような例外も一部ある コンパイラが単語を覚えるのが宣言
メモリに実態が産まれるのが定義 ③を2回書くとエラーになりますね
この辺は沼でしょうか?
厳密に分けても何かに役立つというものでもないし・・・ そういう風に決めたなら仕方がないが
意味的には、定義と宣言って逆な印象を受けます
数学でいうと、
点や直線の定義では実際の描画はまだですが
点や直線の宣言っていうと、その場に描画すると言うイメージ 宣言と定義の意味については C99 だと 6.7 に記述がある
> 宣言は、幾つかの識別子の解釈及び属性を指定する。
> 識別子の定義 (definition) とは、宣言のうち次のものをいう。
> ・ オブジェクトに対しては、そのオブジェクトの記憶域を確保する宣言
> ・ 関数に対しては、関数本体を含む宣言
> ・ 列挙定数又は型定義名に対しては、その識別子の (唯一の) 宣言
逆に言えば定義は常に宣言でもある。 実体が作られるといっても
プログラムイメージにスペースが確保されるとは限らない
静的記憶域期間を持つものはプログラムイメージに作られるが
自動記憶域期間を持つものは実行中に割付と解放が行われるし
構造体のメンバ宣言並びはコンパイラのメモリに作られる
これらのいずれも「定義」となる >>765
> 構造体のメンバ宣言並びはコンパイラのメモリに作られる
それは
> コンパイラが単語を覚えるのが宣言
の方じゃね? なんとなくのイメージ
・宣言
「xxxxって名前の変数(関数)がどっかにあるらしいよ。詳しいことは知らん。」
・定義
「xxxxの詳細はココに書かれたxxxxxである!これは決定事項である!!」 >>766
struct _Hoge;
struct _Hoge; // OK
これは _Hoge という識別子がタグ名という定型データとして作られ、
その後、定型データの中の属性フラグが検査されて一致が確認される
struct _Hoge;
union _Hoge; // NG
これは定型データの中の属性フラグが検査され不一致が検出される
struct _Hoge;
struct _Hoge { int a; }; // OK
これは定型データの中のポインタがまずNULLで作られ、
次に、そのポインタでメンバ宣言列という不定型データを指す
struct _Hoge { int a; };
struct _Hoge { int a; }; // NG
これは既にNULLでなくなったポインタの貼りかえで拒否される
宣言の重複は矛盾の検出のみを行い
定義の重複は不定型データの再作成で拒否される
{ } は無結合 struct _Hoge { int a; };
struct _Hoge { int a; }; // NG
この場合でもコンパイル単位が別ファイルだと(ほぼ)問題無い訳で
一致していなければ一致していないなりの結果が産まれる >>770
(ほぼ)は不要
問題ないというか完全に同じ内容になっていない場合は未定義の動作 ヘッダ include したことないとか
ヘッダに実装描くとか
分割コンパイルしたことないとか
そういうアホのにおいがプンプン丸 定義と宣言の区別に関して
同一翻訳単位の中で 重複が許されるのが宣言 の実例の話やろ 聞きたいのは内容じゃなくてなぜそんな話をいきなり始めたのか?なんだけどw ヘッダに実装書いたっていうレスもヘッダをincludeしたことないっていうレスも見当たらないけど… 別ソースから同じヘッダをincludeしていてもコンパイル時には必ず別ファイルとなるわけで(ほぼ)じゃ困る if ( a == 0 )
{ port &= 0b11011111 ;
}
else
{ port |= 0b00100000 ;
}
これ条件文使わずに書けるよね? port = port & ~((a == 0) * ~0b11011111) | (a != 0) * 0b00100000
頭悪いんでこれ以上無理。確実にレビューで落ちる 何だこれでいいのか
port = port & 0b11011111 | (a != 0) << 5 おまいらは何で素直にかけないんだ?(´・ω・`)? 条件によって8ビット目以上も変える訳ではないのならば…かな
&= 0b11011111 | !!a << 5や&= ~0b00100000 | !!a << 5とかも論理否定は楽な方で
後者は若干レジスタ雑に出来るが…しかし最適化するとif文も分岐排除されてほぼ変わらん Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
0b 使えないw そりゃそうだろ
C言語としてはGCCの拡張だし
C++14でコンパイルしたらいけるんじゃね? >0b 使えない
0xに変換か、どうせ定数なんだからそれっぽいマクロで代用しとけばヨロシ。 A|B == ~( ~A & ~B )
だけどまったく意味はないな >>798 たぶんgcc拡張のポインタ演算の話でしょ。他ではそんなこと言えないから気を付けて。 >>799
GCCだけど
printf("%d\n", sizeof(void)); // 1
になる。
これGCCだけなん? ではvoid型変数 sを宣言してみて下さい
サイズを測ってご覧にいれます >>808
他人のふんどしで勝負する男の人って‥‥ みっともねえよな
そんなことまでパクリしかできねえやつ
# 奴が来なくなって20年近く経ってんのに進歩してやがらねえ voidの長さはよくわからんが、取り敢えずvoid*のインクリ幅を実装の最小単位に取っておけば何でも指せるし、そのアドレス演算に意味を持たせる事も可能になる
どうしてもvoidのサイズを決めたいというのなら、まあ合理的な実装だと思う char*でいいじゃん
なんだかわからないものは「バイト列」だろ そう。
オブジェクトを指すポインタは void* との間で「暗黙に」変換することが出来る。
最終的に char* にキャストするのだとしてもインターフェイス (仮引数) が void* だとキャストをせずに済む。
memmove とかがそれ。 なんでも指せるのとインクリメント幅を1にするのは関係ない
むしろインクリメントしようとしたらミスである可能性が高いのでワーニングかエラーにすべき ハード的な最小単位へのポインタは欲しいね
charって書くの本当は気持ち悪い C の仕様上はアドレスを定義できる単位をバイトと呼び、 char は 1 バイトであると定義されてる。
つまり char はハードウェア的な最小単位と言えるが……、まあ名前が良くないのは確か。 (char が 7bit の系って生き残ってるのかしら?) というかなんでcharってsignedにしてあるんだろ?
char と unsigned charじゃなくてchar と signed char にしてくれていればよかったのにと思わなくもない
intもsignedだし(逆にintがunsignedだったら使いづらいけど)符号付の計算が基本とかあるのかね? C++ではcharが符号付きか符号なしかは環境依存だよ
unsigned charともsigned charとも別の型扱いされる不思議な子
たぶんC言語でも同じ扱いだろう そう。 >>827 の説明が正しい。
char の符号は処理系定義かつ signed char とも unsigned char とも異なる独立した型。
signed char か unsigned char のどちらかと別名という可能性もないので、
C++ のオーバーロードや C の _Generic で三種類に分岐することは出来るよ。
char は整数だから他の整数型との一貫性で考えれば符号付きになるのが自然なようにも思えるが……、
実行基本文字集合は char で (char が符号有りだとしても) 正の値になることを
要求している (C99 だと 6.2.5 に書いてある) ので各環境が採用している文字コードによっては
符号無しにせざるを得なかったのだと思う。
EBCDIC とかだとどうしてもそうなる。
まあ負の文字コードが有っても辻褄合わせは出来たとは思うんだが、
仕様が成立した時点でそうでない想定をしているコードが結構あったりしたんじゃないかな。 >>829
>まあ負の文字コードが有っても辻褄合わせは出来たとは思うんだが、
比較の際に暗黙で走る int への格上げの時にややこしくなりそうやね
char ch;
...
if (ch >= 0x80) // 上位ビット立ってる? &buf[0] ってbufと同じだよな?
なんか意味あんのこの書き方? &buf[0] 配列の先頭要素のアドレス
buf 配列の先頭のアドレス
同じ
sizeof(&buf[0]) 配列の先頭要素のサイズ
sizeof(buf) 配列のサイズ
異なる
配列の要素数を求める場合
sizeof(buf)/sizeof(&buf[0])
で頻出する >>833
>配列の要素数を求める場合
>sizeof(buf)/sizeof(&buf[0])
>で頻出する
ダウト。sizeof(buf)/sizeof(buf[0])の間違い。 >>832
配列の先頭としての意味よりその要素に意味があるということを強調した雰囲気を表すためにそういう書き方をすることはあるよ。
仕様としての解釈 (動作) に差が無い場面であっても人が読む上では雰囲気の差はある。 添え字が非0 のとき &buf[1] か buf+1
添え字が0 のとき &buf[1] か buf+0 か buf か
同じコードになるけど記述に意味を見出すかどうか 配列の大きさを知る演算子くらい標準入りしてもよさそうなもんだとは思う。 むしろ、イディオムやマクロによる素朴な実装だとポインタを渡してもエラーなく通過してしまうからこそ
言語の機能として提供して然るべきだと思うよ。 string_t *s = str_alloc(); char a[32];
char b[32];
fp = fopen("abc.csv", "r");
for(; fscanf(fp,"%[^,],%s%s", a, b) != EOF; ){
printf("%s %s\n", a, b);
}
fclose(fp); test.c:23:31: warning: format ‘%s’ expects a matching ‘char *’ argument [-Wformat=]
for(; fscanf(fp,"%[^,],%s%s", a, b) != EOF; ){
^^
問題なく動くんですが、上のような警告が出ます。
気にしなくても良いですか? &a[0]にでもしたらいいかもな
警告出さなきゃ出ないんじゃなかったかな %sが多いね
あと32バイト以上あったらクラッシュするけどいいの >>846
そのコードで問題なく動くならabc.csvがかなり特殊な形式だと思う
https://ideone.com/haAzIG 最初の%[^,]でa[]にコンマの前までが取られて
次の%sが行末までをb[]に取るから
その次の%sをコピーするポインタが指定されてないので本来はここでクラッシュするけど
前の%sで行末に行ってるのでこの%sは必ず無視されるという綱渡り状態
直しておいたほうがいいよ 生徒数と科目数と点数をキーボードから入力し、それぞれの科目数の個人、全体の合計点数、(科目数の個人、全体の)平均点をそれぞれ出すプログラミングをやっているのですが、全く分からないので教えてください。 キーボードから入力する方法がわからないのか、平均点をだす方法がわからないのか? 多分学校の宿題かなにかなんだろうが、
言葉足らずで相当補わないと問題が分からない
出題されたまんまの内容を書いてみてくれないか 「全く分からない」に対してわかるように教えるには入門書の頭から説明しないと理解できない状態ってことだからなぁ。
それなら普通に入門書を読むべき (その上でどうしても理解できない箇所があるならそれを質問すべき) という話だし、
理解する気が無くてそういうプログラムが欲しいだけなら宿題スレに投下したほうがいい。 質問者です
僕は答えだけが欲しいんです。どうして説教なんかしてくるんですか?
貴方達は黙ってコードを書いてくれるだけでいいんです。それ以外のことを私は貴方達に求めていません
ご回答よろしくお願い致します 成績を収める配列変数を宣言して下さい。
ループ変数iとforループを使ってデータ入力する処理を記述して下さい。
ループ変数iとforループを使って合計を求める処理を記述して下さい。
合計と件数より、平均値を計算して下さい。 >>859
回答するから駅前でパンツ脱いで待ってろ 近道を教えてください
目的地?そんなもの知らん
いじわるしないで近道だけ教えてくださいよ 他人にコード書いてもらいたいならお金払うのが常識だぞ
勉強になったな >>859
別人か?
釣りか?
スレを活性化させるための煽りか? >>866
別人です
釣りです
スレを活性化させるための煽りです
そもそもワッチョイ見れば分かるけどキャリア違うし
>>863も同じような輩でしょ そういや Excel 使った方が楽にできそうな問題だな。 絶望的に適性ないやつがいるな
そんな無駄なことは今すぐやめろ
限りある人生をもっと有意義なことに使え >>871
1.適性がない、というその適性を定義してください。
2.適性がない、となぜ判断したのか 1. をもとに詳しく記述してください
3.1.2.が出来ないのではないのならば、あなたこそ、あなたのいう適性をもちあわせていない、と私は判断します
以上 エラーや不具合があったときに理屈じゃなくて直感ですぐに原因が思いつくタイプは適性があると思う
経験で補えるっちゃ補えるけど >>873
どうした、頭に血が昇ってw
身に覚えがあるんだろ
別に俺が定義しようがしまいが関係ない
おまえが直面している現実が全てだ
コード書けねえんだろバーカw
そんなん俺は厨房の頃からやってたぜ
当時はBASICすらなく機械語だった
やるやつは人のせいになんかしねえんだよ ジジイがイキってるの悲しすぎるな
キャリア積んだおっさんならもうコードなんて書いてないのに >>874
経験がないとそんなことは無理だな
経験によって結果から原因を推定するデータベースを増やしているに過ぎない
生まれつきプログラマになるべく生まれた人間などいないw 直感というより論理(左脳)と感性(右脳)のどちらの活性が高いかの違い >>880
同じ事象に遭遇しても原因を自分でちゃんと究明して対策してる奴と人に言われて直すだけの奴だと取得する経験値がだいぶ違うだろ
そういう意味での適性はあると思う >>879
何も知らねえネンネだなw
熟練者を歳だけでやめさせるバカ企業が
今どうなってるか見りゃわかるだろめくら
IT業界だけ特別とでも思ってんのか
昭和の一時期だけ特別だったが
いい歳こいたジジイが言ってんなら
進化の止まった化石はてめーだ >>883
コーダージジイ効いてて草
こういうやつってマジでガキに見えるよなー
人の上に立った経験とか一度も無さそう >>880
しかし、生まれつき、あるいは育ちのせいであるのかもしれませんが、無意識領域が活発に活動しやすい人、というのはあるかもしれませんよ
人はそれを「閃きの人」と呼ぶようですが
そして無意識領域がよく働く人はプログラマの適性があるといってもいいでしょうね
https://mevius.5ch.net/test/read.cgi/tech/1556284220/703
https://mevius.5ch.net/test/read.cgi/tech/1640401906/23 BASICもない時代か。
俺の時は TK-80 に BS 乗っかったやつが BIT-INN に並んでたな。カラーの COMPO-BS もあった。
その他 Apple ][、PET、TRS-80、BASIC MASTER Level 2、MZ-80K 等がある時代で、フロッピーディスクが Apple のやつは1枚2000円だったかな? >>888
なかったっけ? あったような気がするんだが。
PC-8001 の画面の見間違いではないと思う。まだ出てなかったし。 >>884
コード書けねえ産業廃棄物がコーダー馬鹿にしてんな
フリーターだのニートだのってレベルの稼ぎの扶養虫にしかなれる見込ねえくせに
俺は生まれながらの帝王だ退かぬ媚びぬ省みぬだと? ぶわははは
這い上がる気力のねえやつに栄光はねえんだよ、憶えておきな >>885
受動意識みたいなオカルトに構っていてはプログラマにはなれませんよ
プロの仕事にはすべて説明可能なことが求められます
どこかのリモートで動いてる端末人間にプログラムはできません なかったと思うよ、そもそもCOMPO-BS/80はキャラクター表示しかできないし >>891
デバッグ箇所の発見にも説明が求められるのですか?バグが修正されたことを証明できれば十分なのではないでしょうか? 発見に至る思考過程はいらんな
ドライに事実関係の説明のみで足りる
犯人探しは俺らの仕事ではなく
下手に口を出すとこっちが立場悪くなる >>893
>デバッグ箇所の発見
バグ箇所のことかな
どうしてそのようなバグが発生したかまで明確にしないと
同じバグがまた起こるだろう >>895
話をずらしましたね
私は
>デバッグ箇所の発見
つまり、どこから手をつければいいか当たりをつける能力について言及したのであって、発見したバグの振る舞いについて説明する必要はないとはいっていませんね
話をずらしてはいけませんよね 言い逃れの天才はいらねーよ
頼むから志願してくんな
ゴミ処理だけでどんだけ負担か考えろ馬鹿が それで給料くださいだと? 金銭感覚が絶望的にバグってる超危険人物め そういう人物は確かにいる
システム障害時に、数分で原因を調べ上げ復旧する奴 >>900
その人なりのロジックがちゃんとあるけれども、凡人には理解できないのかもしれませんね…
まあ意識(ロジック)も無意識もフルに総動員しているとは思いますが
>>891
あくまでとある仮説に興味がある、といっているだけで、それですべてを説明しようとは思っていませんよ
それにしても「準備運動電位」、あなたはどう説明しますか? 電位ってそれ以上でもそれ以下でもないな
喩え話でもしたいようだが、この世界では究極の最重度池沼ってだけw >>896
でかいシステムなら分割して調査することもあるからどこから調査するとかどうやって調査するかとか事前に決めるのは珍しくないぞ
そんなことも知らないのはお前の経験値が低いだけ >>903
そんなことはあたりまえでしょう?
手当たりしだいにしらみつぶしに見てバグが見つかるとでも?
でもね、凡人が見当もつかない糸口をたどって(バグつぶしに限らず)問題解決を行う現場を見てきましたよ
そういう人間の考え方が、単にロジック一辺倒ではないのでは?という切り口で話をしているものだと思っているのですが
あるいは自分のコーディングの最中に自分のミス・バグを見つけ出すのは、最初自分が正しいと考えているだけに、結構難しいことだと思っているのですが、
そういうときは非凡な人はどういう思考方法をとっているものなんでしょうか? >>904
> 手当たりしだいにしらみつぶしに見てバグが見つかるとでも?
それでないと見つからないバグもある
> でもね、凡人が見当もつかない糸口をたどって(バグつぶしに限らず)問題解決を行う現場を見てきましたよ
そう言うのは経験値が違う
まあその考え方を文書化できるかどうかは別の話
> あるいは自分のコーディングの最中に自分のミス・バグを見つけ出すのは、最初自分が正しいと考えているだけに、結構難しいことだと思っているのですが、
> そういうときは非凡な人はどういう思考方法をとっているものなんでしょうか?
お前はテストもしないのかよ スレが活性化したようだな。
読む気が起こらんけど。 何でしらみつぶしが出てくるんだ
不具合の内容から疑われることを挙げて
排除できる項目を排除して疑う範囲を狭めていくにあたり
論理思考が得意なやつとそうでないやつの違いが出るってだけだ >>910
バグの排除にロジックが必要なのは当然ですが、それだけではないでしょう?
特に自分のバグを外すには、そもそも自分のロジックを疑うという能力は、ロジックを使うのはまず困難なのでは? >>910
疑う範囲を狭めて最後はしらみつぶしとか普通にあるだろ
なぜ排他だと思った? バグの排除とは言ってない
疑いが晴れたものを検査から除外するということだ
なぜ排他が出てくるのか脈絡がわからない >>913
> バグの排除とは言ってない
おれも言ってないけど?
> 疑いが晴れたものを検査から除外するということだ
検査の意味がわからんが調査のことならしらみつぶしは疑いを晴らす方法の一つ
> なぜ排他が出てくるのか脈絡がわからない
お前がしらみつぶしを排除しようとしてるから アホ検知用にわざとアンカー貼らなかったら見事に引っかかったなw なにを引っ掛けたつもりになってるのかさっぱりわからん
まあまともなレスを返せなくなったんだろうなw >>901
ただのDSPだろう
CPU(脳)が応答していては間に合わない用途のためにプログラマブルなDSPがある
ボールが見えてから打つかどうか決めていては間に合わない
このコースに来たらバットを振れと反射神経をプログラムできるようになっている
それがあたかも脳の判断に先行してるように見えるだけ >>921
レスできなくなって流れが読めてない~ってバカ?w はっきり言ってやらなきゃ解らんようだな
バグの排除と言ったのが誰なのか
おまえ読み間違えてんだよ >>924
だから>>911なんて俺には関係ないだろ
アンカーもまともに追えないのか? ロジックは合っているがバグだ、というのは割とよくある(まれにではない) >>926
・仕様バグ
・非同期処理絡み
・限界値オーバー等
それ以外ってあったっけ? 今は昔、DBが気軽に使えなかったシステムがあった。
プレーンファイルにデータが格納されていた。
お客の要求は、
「その中からキャンセルされたデータを見つけ、取り除いてくれ。件数は高々数十件のはず」
当時のSEは、キャセルデータ一覧から一つずつデータを取り出し、
格納されたファイルから見つけてはキャンセルフラグをセットしていく
という設計をした。スッキリした設計で、客のレビューも通った。
プログラマは仕様書通りにプログラムを作成した。
実運用に入ったところ、この処理がいつまで経っても(何時間も)終わらない事態になった。
原因調査を依頼され、調べて対処方法を提案し、
プログラムの手直しをした。
その結果、処理は10分程度で終わる様になった。
実データは、お客の想定よりは多かった(と言っても100件程度だったが)ことと
試験環境が貧弱で、性能評価が不十分だったことが挙げられた(公式見解)。 今は昔 ドラゴンボールというものありけり
7つ集めないと気軽に使えなかった 非同期やマルチスレッドなんかの 暗に平行に動いてるようなやつ
の想定順序外の順で進んでったとき 昔のプログラム系コラムで(うろ覚えなんで改変あり)
統計計算するコード書いて、
自分で用意したデータでは問題なかったが、
デバッガ―チームのデータでは誤差が酷いとの報告が。
変数をfloatからdoubleにしても改善せず、
使ったテストデータ見せてもらったら数値が10兆のや1/10兆のまであったとかなんとか。 >>928,931
件数や数値の範囲を規定してなかったんだろうな
規定してたらテストしてるだろうし
>>928の方はキャンセルする件数も重要だけど変更するプレーンファイルのサイズも重要 仕様通りに作ってあるってことで
どこもバグだと認めず、修正にかかれなかった 実行時間の上限も書いてなかったんでしょ?
ならバグじゃないからそりゃ誰も修正しないよね >>937
奈良仕様... 要人警護でバグるんだな。 >>920
それは条件反射ではない普通の「反射」
か、あるいは条件反射ですね
「準備運動電位」
https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%B3%E3%82%B8%E3%83%A3%E3%83%9F%E3%83%B3%E3%83%BB%E3%83%AA%E3%83%99%E3%83%83%E3%83%88
1970年代に行われた実験により、ボタンを押す・指を一本曲げる、手首を曲げる等運動の先立って脳に変化が起こる、という観測結果が得られています
2008 年には、被験者が意思決定をするよりも最大 7 秒先立って脳活動が認められる、という^報告がありました その生理現象を検知して価値を生み出すコードを書くならともかく
精神論や根性論の類いに持ち出す野郎はスレチ >>940
ええ、バグ取りに使えないものかと
異様にバグ取りがうまい人の頭の使い方について話題にしようと思ったんですよ そんなの経験の差でしょ
脳科学なんかを引くより経験積んだほうが実用的で合理的 >>942
いつまでも KKD ではねえ
もう少し精緻な話がしたいものです バグ取りの上手い人というか、発見が早い人は
アスペ気味の人が多い
これは悪い意味で言っているのではなく
天才肌というか、直感でものを把握出来る人という意味です >>944
それもアラアラな話だと思いますが
しかし、その直感でものを把握できる、ってのがどういう思考法なのか興味がありますね
もう少しそのタイプのプロフィールを教えていただけませんか? そういうのは、誰もマネが出来ないから参考にするのは無理でしょう
脳細胞のシナプスからして違うかもしれないし プログラムの仕組みを完全に理解したいなら、ITパスポート、基本情報、コンピュータサイエンスの3つ。 プロの化学者つかまえて次亜塩素酸ナトリウムと塩酸を混ぜるなとドヤるアホ
みたいなもんだな >>945
直感って大抵は経験に基づくショートカット。
常人でも意識しながら年単位でデバッグ続けてりゃ多少は身につくんじゃねの? >>953
身につくかどうか、ではなく、どんな考え方、思考法、そして可能であればその思考法に似た行動様式等がざっくばらんに出てくることを期待します >>954
鏡で自分の顔を観てバグを一覧にしてみ
良い訓練になる 組み込みの世界ってまだC言語が主流ですよね?
IoTも同じ? IoT というのは広い概念なのでそれだけではなんとも言えん。
低レイヤもあれば高レイヤもある。 次のCの仕様が出てくるというのにこのスレでは全く話題にならないんだな tccで標準入力からソース読むプログラムに、さらにstdinからデータ読ませるのは無理ですかね?
(echo "ccode with stdin" | tcc -run - ) <file
みたいな感じで(fileまでソースと取られてコンパイルエラー)
一時ファイル作れば出来るけど、ちょっとワンライナー書くときに不便を感じる
echo "main(char*c, char**v){puts(v[0]);puts(__FILE__);}" | tcc -run -
は
-
<stdin>
を出力します、多分tccはプロセスを自己書き換えで置き換えるんでしょうか?ファイルハンドルが継承されてる? >>958
高レイヤーだと普通にリッチな言語が使われたりするのかな
>>961
deferが入るかもって別スレで見かけたけど本当? 組み込みと言ってもラズパイ環境では完全にPythonが主流でC/C++(gcc)はあまり利用されてないイメージがある >>964
C23 には defer は入らない見込み。 全体としては C++ の後追い的な変更が多い。
auto が型推論付きの変数定義になるだとか、constexpr や nullptr が導入されるだとか、
属性の表記法が C++ 風の [[ ]] を使った形になるだとか、そういう感じのやつ。
(ちなみに今回導入される constexpr は変数には付けられるが関数には付けられないので
コンパイル時プログラミングが C++ みたいに出来るわけではない。
定数式の成立要件が C と C++ で違うので C++ 寄りにする追加機能。)
思い切った変更ではあるが、根本的なプログラミングスタイルを変えない程度のバランスのとれたところだと思う。 >>966
もちろんそういう部分も大きいけど……。
リッチな組み込みは一昔前のパソコンを超えるくらいの性能はあるし Linux くらいは載るので、
デバイスドライバさえ用意すればあとはパソコンみたいに使えるという場合は普通にある。
かつては組み込みと言えばそのデバイスドライバの部分こそ大きかったと思うんだが、
IoT を意識するレベルの製品だとアプリケーションレイヤが巨大なので Python くらいは動くこともあるだろう。
主流かというとちょっと疑問ではあるが……。 それは組み込みと言うより、OS上で動かしている単なるアプリだろう パソコンで同じことやっても組み込みなんて言わないし 組み込みの開発はクロス開発が基本なのでパソコンはただの端末だけどね
プログラムはボード上のSoCで実行される IoTにはC言語は深く入り込んでないのか
>>967
型推論付くってマジ?
個人的には嬉しい >>964
> 高レイヤーだと普通にリッチな言語が使われたりするのかな
複合機などはWebサーバー程度は普通に入ってるから設定画面等は HTML, JavaScript, CSS, Python を使ってたりする
IWS (Internal Web Server:HTML, JavaScript, CSS, Python)
https://dsp.konicaminolta.jp/best-program
もちろんOS上で動いてるし、でかいシステムだとPCその物を内蔵してたりすることもある
なのでこんなものが売られてる
https://jpn.nec.com/fc/index.html IoTというよりはスタンドアローン環境か小規模な独自ネットワーク程度の組み込み分野の方がC/C++利用は多いと思う >>974
こういう機材に囲まれたことないなー
俺はIoTは名前だけでほんとに実感がない >>969
機器に「組み込まれ」ているなら組み込みと呼んでいいだろう。
パソコンに近い構成にしてパソコンでも使えるソフトウェアを活用する場合があるというのは結果論だよ。 そうなるとPC使っていても組み込み扱いして良いと言うことになりますよね
近い構成どころか、何でもありになりそう そうだよ。
技術的な実態としてはそんなにはっきりした境界がない。 なんでもありだ。
用途の側でふんわりと分野が分かれてる。 >>961
Cは枯れた言語で今さら新機能は誰も望んでないからな
むしろ余計なことをしてくれるなと 古いソースが問題なくコンパイル出来ないと、それはそれで問題にされる。
今でもトライグラフ受け入れないと駄目なんだろう >>981
C99 の C++ との互換性がまったく取れていない変てこ機能はさっさと削除してほしいものです
いまや私は C のソースを書くのに C++ コンパイラが通るか試してみる体たらく、あれらはいったいなんなんだ? 今回「削除」になったのはいわゆるK&Rスタイルの関数定義くらいだな。
いずれ削除するということは以前から書かれてたし、
習慣的にも行儀が悪いという考え方が支配的だから
これで問題が起こるなら長い移行期間中に対応できてなかったほうが悪いと言ってよかろ。 削除って事は、古いソースのコンパイルはもはや出来ないと言うことなんでしょうか
いや、なに、クラシックカーに乗ってみたい位の好奇心ですけど 歳をとるということ 〃
シワが増えるということ 〃
なのに
ぼくたち
私たちは 〃
なぜ、最新機種で進化の止まった古臭いコンパイラを使うのでしょうか
でしょうか >>985
削除された機能を使っていればそういうことになるが、
そもそも C で書かれたプログラムなんてどこかしらで環境依存な部分があるもんだし、
よほど配慮されたものでない限り古いコードは素直には動かないのが普通だろう。
まあ C23 が出来たからと言って C89 (に対応したコンパイラ) が直ちに消滅するわけでもないし、
なんだかんだであと二十年くらいたっても C89 派がそれなりにはいそうな気がする。 K&R CこそCの面白さの塊なんだけどな
GCCが「カバにダンスを踊らせるのはあまり面白くない」なんて言ってた人もいるように
歳月とともに雁字搦めになっていく流れは酷くつまらない >>988
でもね、C のコンパイラは C で記述してほしかったですね
確かにカバの調教は難しいのかもしれませんが
というか、gcc をコンパイルするためだけの c で書かれた c++ コンパイラって需要ありますかね? ラージモデルでFarポインタ使いまくったプログラム合ったけど、
今は流石に見るのも嫌だと思う
何言ってるか分からないと思うが、俺も分からない >>992
むしろnearポインタの方が面倒だと思うが... あり人間とかキチガイ、こっちでも頓珍漢なこと書いてるのか >>992
ラージモデルの far ポインタでしょう?別に far とか書かなくても普通にポインタを書けば far ポインタになったはず
であれば、あとは 64kb の壁を意識してむやみにポインタのインクリメントをせずに上手に部分にわければなんとかなったでしょう
far ポインタでの経験はいろんな場所で活かせる貴重な体験だと思いますよ
私は試食版 LSI-C のスモールモデルで陽に far を指定して far ポインタをバリバリつかっていましたよ
スモールモデルだからコード領域はせまいけれども(near コールしか使えない)、far と書けばデータは 640KB までフルに使えましたし インテルのクソ設計でみんな迷惑してたってだけの話
K&R Cの楽しさとは全く何の関係もない
68kと86系は異次元の世界だった >>995
テキトー書く前に8086 メモリーモデル とか near far huge とかでググってから出直してこい >>997
私の認識であってますよ
ラージモデルのデフォルトポインタ(データ・コードとも)は far ですし、スモールモデルはどちらも near
しかしスモールモデルでも far ポインタは far と陽に宣言すれば使えるんですよ… Windows16ビットのCでは16ビットハンドルを架空の構造体へのnearポインタとして実装してたな(#define STRICTした場合)
例えばデバイスコンテキストハンドルをビットマップハンドルに代入しようとするとtype mismatchエラーになってすぐわかる
STRICTでないと単なる本来の16ビット整数として扱われ混同しても通ってしまう
win32ではnearがないので普通の32ビットポインタになってしまいメモリがちょっともったいない >>92push(保存)してpop(書き戻し)してるから結局pushしたときのデータになる
popとpushの間のややこしいとこはシカトな このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 222日 6時間 29分 31秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。