C言語なら俺に聞け 158
■ このスレッドは過去ログ倉庫に格納されています
>>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 か
同じコードになるけど記述に意味を見出すかどうか ■ このスレッドは過去ログ倉庫に格納されています