C言語なら俺に聞け 158
■ このスレッドは過去ログ倉庫に格納されています
>>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
アセンブラ以外のすべての言語は退廃と怠惰の産物と心得よ ■ このスレッドは過去ログ倉庫に格納されています