C言語なら俺に聞け 150
レス数が1000を超えています。これ以上書き込みはできません。
ミスってる
!extend:checked:vvvvv:1000:512
を書き込み内容にするためにもう一行書かなければならないのね 違うな
シェバンに類似する特殊な一行目は書き込みすると失われる、だろ
だから次の手順説明のために同じものをもう一行増やす
しかも「必ず1行目に入るように」って書いてあるから二行に増やしても先頭に空白行があると受理されないハズだ
もう一行書くだけじゃダメだからな では、続きをしようか
986 名前:デフォルトの名無しさん (ワッチョイ df01-vS77)[sage] 投稿日:2019/02/06(水) 04:57:27.49 ID:eUM592Vs0
ループから抜けるときに goto使ったらダメなんですか?
for (...) {
for (...) {
if (...) goto LOOP_EXIT;
}
}
LOOP_EXIT:
こういう感じで書いたら先輩に怒られました。
フラグ見てループ抜けるように修正しろと。
指示されたので従いますけど、どうしてダメなのかよく分かりません。
どなたか納得するような理由をご存知でしょうか? 若き日の俺は、gotoの他にフラグも無闇に使うなと教わったものだが
フラグはいいってことになったのは、いつからだ? どういう経緯でだ? Cにはラベル付きbreak文って無いんだね初めて知った
Javaのラベル付きbreak文
loop_exit: for(...) {
for(...) {
if (...) {
break loop_exit;
}
}
}
まぁJavaでもあまり使ったことないけど…。 #define break goto
みたいなしょーもないことしても本質的に何も変わっちゃいねえ goto があっても
いいじゃないか
C言語だもの goto文そのものが悪いわけではない。いまだにgoto文の使用そのものがよくないというやつらのせいでおかしくなっている。
goto文で前のif文内に飛んでみたり、ループのなかに飛んでみたりと、乱用して人間には理解しづらいスパゲティプログラムを作るなという話なのに。
continue文だって実体はgoto文で、コンピュータにとってはメモリ上のマシン語を順番に実行しない場合はすべてメモリのアドレスのジャンプでgoto文。 センサーで取得した計測値を数値では無く文字列で返す関数を作ろうと思ってる。
どんな計測結果が得られるか事前には分からないため文字列のサイズは関数内で
mallocを使ってリサイズする予定。
このとき測定結果が格納された文字列を関数から渡してもらうのに、
a) 引数に文字列のポインタのポインタを渡す
void sokutei( char** buff )
{
・・・
*buff = (char*)malloc( sizeof(char)*length );
・・・
}
と、
b) 関数の返値に文字列のポインタを指定する
char* sokutei(void)
{
・・・
char* buff = (char*)malloc( sizeof(char)*length );
・・・
return (buff);
}
の二つの方法があるけど
一般的にはどっちの方法がお薦め? >>12
機械語が分岐命令になる高級言語のステートメントを全否定というのは
構造化とはまったく違う話だな >>13
> センサーで取得した計測値を数値では無く文字列で返す関数を作ろうと思ってる。
これ自体が糞。
計測値は生で保持して、表示する時だけ文字列に変更しろ。
そうすればprintfだけで行けるだろ。
無駄に可変長のバッファなんて持とうとするから無駄に面倒になる。
初心者だから分からないのだと思うが、そもそも複雑にならないように全体像をまず組むんだよ。 voidにするならポインタ返した方がいいと思うよ。
正しさでいうと、既存のライブラリ使ってシリアライズするのが正しい。 関数の戻り値は処理の成否のみを返す。
正常終了なら0、異常終了なら非ゼロ。
入出力は引数で渡す。
と、決めて統一するのが良いと思う。 助言ありがとう
確かに関数の戻り値は処理の成否のみに限定するのはスッキリしていいかも
> 文字列で返すのが糞
確かにその通りで(;^ω^) 重要なのは統一するってこと。
標準ライブラリには戻り値に二つの意味を持たせているのが多いから、個人的に好きじゃない。
fopen() 成功時はファイルポインタを返し、失敗時はNULLを返す。
strtol() 成功時は変換結果を返し、失敗時は0を返す。
これじゃ変換結果が0なのか、失敗して0なのか分からない。
で、errnoを見ろってことになってる。
なんでこうなってるかというと、戻り値に処理の成否と結果の二つを持たせているから。
だったら、分ければいいじゃんって話。 >>20
多分相場が分かってないのだと思うけど、
正しく初心者の自覚があるのなら、ある程度縛りプレイで行った方がいい。
C言語なんて現役で50年来てるし、そのセンサーだって民生品なら誰かが同様に使ってる。
それでもそれ用のライブラリがないのなら、それはそもそもそういう使い方をする奴がこれまで居なかったということ。
つまり、そのやり方が間違っている、と見ていい。
初心者が自前でライブラリみたいな物をいきなり組まなければならない時点で設計が間違ってる。
それは君らがよく誤用している「無能な働き者」に該当する。
(ただし繰り返すが、Webでの多くは誤用されているので注意) 副作用がメインならともかく、欲しいものを素直にreturnすればいいよ。 strtol()は変換できなかった時の戻り値が曖昧だから0やらLONG_MAX、LONG_MINに固定してるだけだと思ってたんだけど バカかコイツラNaNが出たらどーすんだよ
文字列が正しいだろJK >>20
C言語の戻り値って、エラーのみで返して、正の値って無いから、C++だな、C++言語に行くように >>19
それやだ
んなことするくらいならsetjmpだ >>13
ほんとうはaのときは引数にエラーがいるし、bのときは戻り地を
エラーにしないといけないからあまり変わらない くっそ初心者なんだがガウスの消去法でn次連立方程式を解くようにしたいんだがn次を入力させてからやるにはどうやりゃいいんだ? 行列の格納先に配列のかわりにmallocで動的に確保する。 a)の方法。空の文字列を渡そうとすると失敗するっぽい
char** str;
sokutei( str );
これやっても有意な文字列はstrに返ってこなかった。
もしこれやるならb)の方法じゃ無いとダメかも↓
cha* str;
str = sokutei(); 初心者だから間違ってるかもしれんけど
外でメモリ確保してないからじゃない?
文字列を関数内で作ってたら関数処理終わった後は文字列がそのまま残るかは保証されなかったような気が
外で配列宣言して関数に渡して、関数内でそこにmemcpyさせるとか? >>32
それやるなら、こうじゃね?
char* str;
sokutei(&str); あぁmallocしてんのね…
aは何でchar**なんだろう >>29
C99以後ならVLAという手もある
int n;
scanf("%d", &n);
double mat[n][n + 1]; >>34
あぁなるほど
char **str;
sokutei(str); // 関数の引数にstrのアドレスがコピーされるだけ
だから関数内で代入してもコピーに再代入してるだけか
char *str;
sokutei(&str); // str自体のアドレスを渡す
これなら外のstrにmallocで確保したアドレスが入るのね 渡した引数を書き換えてくれるインターフェースは
scanf() の使い方と同じくするしかない >>37
VLA は廃れていく方向のダメな子じゃないですか?c++ からも linux からも追放されたようですし >>40
たくさんの人に使ってもらいたいライブラリを書くのなら、現状 C しかないと思います >>41
C++にはもともと導入されてないから追放とかじゃない
vectorがあるからいらんかったというだけ >>26
ANSI Cでは何かしらの値を返さなければいけない。 どこかのHPで「自分は頭悪くてC言語の命令が覚えられなかったからアセンブラでプログラミングしてた」という記述を見たんだけど
アセンブラの方がよっぽど難しいと思うんだけど、アセンブラできる人からしたら違うのかな? 単に、新しいものを覚えるより使い慣れたアセンブラのままでやった方が早いという話じゃないかな。
あるいは情報処理試験の話だったとか。 おそろしく英語がわからんプログラマーを見ると少し哀れみを感じる >>45
ものにもよるけど理解するのはアセンブラのほうが単純なぶん簡単。 一部には変数概念を理解できなかった御仁もいるらしい アーキテクチャや機械語ニーモニックは簡単なんだけど
CPUと直接関係のない、アセンブラ指示子やコマンドを覚えて
エラーなくアセンブル通るようにするのは大変 構造化アセンブラとかあったな
結局流行らなかったけど 構造化アセンブラ使っていればいずれCに移行するし
Cで記述できない部分はインラインアセンブラで補うようになる
構造化されているとはいえアセンブラはあくまでアセンブラ
生産性はCには及ばない
元組込みマイコンプログラマより >>45
アセンブラってのは理屈じゃない決めごとを憶えるだけでいいが
Cやその他の高級言語は構造化だとか処理系依存がどうたらという
どっかの知らん馬の骨が強弁する作法シキタリに付き合わされるから
気が短いやつはプイと出てっちまうのさ
鵜呑みをせず納得ずくでしか動かんやつという意味では大物の素養がある 最初がBASIC小僧だった経験から言わせてもらうと、
サブルーチン(Cでは関数)に値を渡す返すって部分が分からなかったな。
ある計算をさせるサブルーチンにパラメータを与えたいときは
大域変数に入れて共有する、値の返却も同様。
これはアセンブラでも同じでしょ。レジスタで渡す返すも可能だけど。
その後、8bitマシン語少年に進み、Cを勉強した時は
ポインタ加算の自動スケーリングに引っかかった。
int *p = &a[0];
p += 4; // ここで p == &a[4] になるのが納得いかない
新たな p が指す先は a[2] か a[1] (intのサイズに依存)、と考えたわけ。 プリプロセッサで MASM の REPT句と同じようなのが欲しいいかも と思ったことはある C言語学び始めたときに(BASIC、Z80/8086アセンブラの経験はあった)「C言語の非常識」とかいう本読んで
トラブルになりそうなところを先に学んだんでそう苦労しなかったな。
それより16bit DOS時代だったんでコンパイル設定でメモリモデルがLARGEだのHUGEだのの方が理解でできんかった。
まだ学生で「インターネットください」より前の時代で調べる手段がわからんかったし。 それ30年ぐらい前だよね。
large だの huge だのは本読んだりして覚えたなあ。 数百MBの配列データを扱うときにコンパクトモデル利用したな 30 年前に C コンパイラにアセンブラソース出させて C を学んだけど
ひょっとして普通はしないことなの? MS-DOSでPC98使ってました
多分80386だったんじゃないかな? なんかそれっぽいw
CADのデータを扱うアプリで、データが大きくなりすぎて
PCによっては読込すら出来なくなってしまい
アプリを立ち上げずに画面表示やプロッター出力する
プログラムを作れという指令が飛んだんです
データ構造は比較的簡単で、先頭部分に部品基本イメージ、
その後ろから、固定長で膨大な描画情報がある感じです
描画情報を64k未満の配列に分割して格納し、
それぞれの配列アドレスを格納した配列経由で操作するイメージでした DXFのENTITIESセクションとかかな 頭に部品イメージ云々 そんな感じです
ソフトは有名な高額ソフトではありません
スタンドアロンのMS-DOSで動作可能なほど
コンパクトなものでした(名前失念w) >>63
コードが最適化されるのが前提なところがあるので
今はしたくてもちょっと難しい気がする
できることはできるけど、イマイチ学習効果が薄そう そもそもPC-98シリーズで数百MBのメモリー載る機種あるのか?
HDDですら数十MBクラスが普通だったと思うが… >>71
メガバイトって事は無いですね
初期の無印98で128KB、MAX640KBだったかな
386乗せたRAシリーズだと標準で640KB+1024KBだったと思う あれ?
98note 使ってたけどメモリ増設で16MB 積むか12MBで妥協するかで悩んでいた記憶が…
勘違いかな? Ap2でいくら載せてたかなぁ・・・。
20だか30M程度だったと思う。
パリ有りメモリで近所で扱ってる店も無かった時代なんで。
ぐぐったら公式で最大 73.6MB 、非公式で125.6MBまでいけたらしい。
>HDDですら数十MBクラスが普通だったと思うが…
それはSASI HDDじゃないか?VM時代か?
RXで340M、AP2で4G のSCSI HDD使ってたよ。 Cしか書けませんっていうのは新卒就活のときに不利?
他にどんな言語を習得すればいいんだろうか まず「他にどんな言語を習得すれば良いんだろうか」なんて言ってること自体がかなり的外れかな
手段と目的の順序が逆
あと面接のときに「何故C言語を習得し、それを何に使ったんですか?」って聞かれてちゃんと答えられる? 新卒であればプログラム言語そのものより他にアピールした方がいいと思うけどな
組み込みであれば現代制御理論、解析系であれば有限要素解析などC言語のプログラミングを応用する専門分野の知識を売り込んだほうがいいと思う >>76
俺んとこではそれで充分
ただしCが書けるといってもHello worldの域を出ていないのは書けるうちに入らない
アルゴリズムの基本ができているかどうかを見ている
できていれば他言語が必要になっても泥縄ができるからだ
俺だってもともとアセンブラ屋で正社員3年目くらいのときにCの案件が回ってきて必死こいて憶えた >>76
冗談抜きで一番大事な言語は日本語と英語。
開発職に論理的な表現力は重要。 64ビットCPUでもデフォルトの命令のオペランドが32ビットだから
linuxでint_fast32_tを使うのは間違いだったんだな
多分64ビットのアドレス計算も32bitの命令があるからパッディングとかも
起こらないだろうな >>83
linuxはint_fast32_tが64ビットになってるから >>82の4行目で多分って書いたけど
64ビットのムーブ命令は32ビットなら0埋めされるから
ポインターの引き算をしなければ64ビット整数を使う必要ないということだな ポインタの引き算に使うんならptrdiff_tだね
int_fast32_tが何ビットかには関係ない >>84
amd64では64bitが最速でないのに64bitが選ばれるのはおかしいっていう主張? このスレの平均年齢って幾つなんだ…(驚愕)
Cってもう若者は触らないっていう感じなんですかね。 いまどきの若者ならみんなPythonに行ってるよ
やや年食ってる連中ならJavaやC#
職人気質で頑固な偏屈者はC++
Cはかつての栄光を引き摺って余生を過ごす老人の言語 >>93
でも言語を超えて活用されるライブラリ(libzip, libpng/libjpeg etc)は C で書かれることはあっても、OOP 諸言語で書かれることはないかと思うのですが?
C++ で記述される汎用ライブラリはありますか? Cの使い手が減ったんじゃなくて他の言語の仕事が増えてるんじゃないの。
もともとサーバー側のシステム開発をCでやったりはレアでしょ。 >>95
やっぱりアプリよりになっちゃうのは確かだね。
XMLのパーサとかだとオブジェクト指向の有り難みがある。 Cでがんばろうと思うと、glibみたいな形になっちゃいますね。 俺は有名な言語はほとんど全種類使えるから適材適所で使い分けてるは 使えるというか、Cが分かるなら「〜の言語でやれ」って言われたらどの言語でも3日で仕事出来るくらいは当然だけどね。
java勢とかが3日でCやれと言われてポインタまみれのコード読むのは無理だろうけど。 極端だけど、突然Prologでやれ!と言われても3日じゃまともに使えないと思う。 まあ新しい言語の勉強始めたら3日目にはそれなりに手が動くようになってるだろうからな。
でも仕事で使おうとするとプロジェクト設定の方法がわからないとかその辺で詰むと思うわ。 3日ねえ。まあ、書けるには書けてもその言語の特性をうまく活用できるところまでは行きそうにないな。 百歩譲って自分がもし言語が3日で出来たとしても業務知識や専門知識は3日では身に付かんから無理だわw >>109
Cしかわからなかったけど、入社して「これわかりやすいから」とjavapressをポンと渡され、3日後にはjavaで養鶏管理のシステムを作らされていたぞ。
業務知識なんて仕様書と上司に聞きながら覚えるものじゃん。業務知識覚えてから仕事って、新卒じゃないんだからw 業務知識覚えてから仕事なんて一言も書いてないけどw
こういう人ってちゃんとドキュメント類読めてるんだろうか
自己解釈でガンガン進めてから修正で苦労してそう
あと君が3日で出来るすごい人なのは充分分かったよ 業務知識を知ってから作るんだろう
新卒じゃないと知識なしに作り始めるのか 鶏が何を食っているか新卒で知っている人はいない。
貝殻食っていると知ってた? 仕様書に書いてあるんだろう
上司に教えてもらいながら開発するベテランさんは
知っていることなのかな? 貝殻というか石や砂など砂嚢(砂肝)に飲み込むものなら何でも良いんじゃないの? 皆さん鶏に詳しすぎません?w
もしかして:鶏 飼ってる カルシウムが不足すると、イライラしてくる
貝殻囓ると多少は改善する Cが出来るなら仕事で求められる程度のコーディングは3日で皆も出来るでしょというだけのお話だったのになぜか餌の話になっててワロタw Cのスレに書き込んでてかつ鶏飼育してるってすげー組み合わせ ここの人たちはマイコンで全自動の餌やり制御とか余裕で作ってそうだからなぁ まぁ、C言語のCはChickenの頭文字だからね。 それは機械学習の世界だからなpythonでやるべきだな 機械学習の段階に持っていく以前にどうやって特徴点を抽出するんだよ >>130
レーザー使って卵のうちにてのはもうあるらしい >>132
AIを信じろ、心を無にして写真を撮り続けるんだ。 B (programming language) が A programming language の流れを汲んでいるとは初耳だな Bは聞いたことがあるが、Aがあるのは初めて知ったw 昔々小学生の頃に道で売ってたカラーひよこを買って、だいたいは一晩で死ぬわけだがその時は電球で暖めたり色々やったら生き長らえて成長し、立派な鶏に成長し、その後親戚に引き取られて行ったが、すぐに食われた。 #include "A.h"
#include "B.h"
A.hとB.hに同じ内容の同じ名前の関数が定義されてると
こうインクルードした時点でコンパイラから二重定義されてるぞ
とおしかりを受けるわけだがどうしたらいいかな?
手作業でA.hないしはB.hから該当する関数を削除しないといけないかな? #pragma onceではダメですか?
そういう話ではない? AB共にその関数使用でインクルードするソースが多数あるのであれば
どちらか一方は関数削除し代わりにもう片方をインクルード うん、事情によらず同じ名前の関数定義があっちゃだめでしょ。 そのヘッダーをインクルードするソースが複数あったら、
やはりリンク時に二重定義とならないか? 定義の意味が曖昧だけど自分ならヘッダーはプロトタイプ宣言だけなので関数定義そのものが
二重になることはまず無いな
*.cと*.hファイルの関数定義と宣言をきちんと区別していれば同一関数の二重定義なんて事態には
そうならないと思うんだが int型の変数を文字列に変える
INT2STRって関数がバッティングしてる
便利な関数だからいろんなヘッダファイルに仕込んでるんだけど
そういうヘッダファイルを複数includeするとバッティングしちゃうんだよね 関数宣言だけなら多重でも文句はいわれない
マクロやtypedefに構造体の衝突ならインクルードガード施してそれだけをヘッダーに
}; #ifdef
#ifndef
#endif
の出番? ライブラリのヘッダ見てマネればいいじゃん
#ifndef _STDIO_H
#define _STDIO_H 1
...
#endif みなさんpragma onceじゃなくてifndef派なんですね >>155
> INT2STRって関数がバッティングしてる
> 便利な関数だからいろんなヘッダファイルに仕込んでるんだけど
その関数を定義した"int2str.h"を作って
#pragma onceなり#ifndefなりでインクルードガードしておく
各ヘッダーファイルは"int2str.h"をインクルードすればいいだけ >>155
「便利な関数だからいろんなヘッダファイルに仕込んでるんだけど」
普通は
「便利な関数だからライブラリ化していろんな実装ファイルでインクルードしてる」
とするべきでしょ。
ヘッダファイルの使い方も間違ってるような… >>161
たぶんint2str.hはヘッダーファイルじゃなくて実装ファイルでインクルードすべき性質のものだよね。
細かいことかもしれないけど、ヘッダーファイルでインクルードすると他のファイルへの影響が増えるから、必要がない限りは実装ファイルの方でインクルードするべきだと思う。 関数の実体をヘッダーにおいているのか
inline キーワードが使えるなら… という話かな? >>163
いやそんなことはみんなわかっててでも本人やりたいならこうすればいいよって言ってるだけだろ ありがとう、みんなが背中押してくれたから決心が付いた(`・ω・´)
ヘッダーファイルint2str.hを作って
関数INT2STRの実体はint2str.cに記述、
int2str.hには
#ifndef _INT2STR_H
#define _INT2STR_H
...
#endif
でくくって多重定義を防ぐ(`・ω・´)b #include <stdio.h>
int f(int i){
switch(i){
defalut:
return i;
}
}
int main(void) {
printf("%d\n", f(2));
return 0;
}
このコードを実行するとfの入力が何であっても0が出力されるんですけどなぜですか? >>169
一応手元で試したらちゃんと2がでたよ。
printfでなくてmain関数の結果を表示してるとか? defaultがラベルになる?switch の中に return だけになるのか?switch 素通りして関数の最後に return 無いけど return 0 になるのか?これコンパイルとおるの?
少なくともコンパイル警告は出るはずだから、素人は警告無視すんな ラベルは、警告出ないだろう
これ昔ハマったことあるw あー、これね。
これそのものじゃないけどcaseを書き忘れて同じようにハマった経験あるわ。 初心者なんですけどファイルをfopenで開いてからcloseせずに別のモードでまたfopenするのは問題ありですか? >>169
コピペして実行してみたがこちらでは 4195622 が出力されたw
gcc -Wall でコンパイルしてみると「ラベル ‘defalut’ が定義されていますが使用されていません」が出る。
綴り間違いだな。l と u が入れ違いになっている。 ありがとうございました!
綴が違っていたことに気づきませんでした! なるほど -Wreturn-type とか -Wall つけないと int 型の関数に return が無くても警告出ないのか >>170
コピペせずに手打ちでやったから "defalut" に気づかなかった。。 >>175
単一のファイルを複数回、fclose()しないでfopen()するってことかな。
複数の FILE* が単一のファイル(名)を操作してる状態。
FIO24-C. すでにオープンされているファイルをオープンしない
ttps://www.jpcert.or.jp/sc-rules/c-fio24-c.html
↑によると「(前略)同一のファイルを同時に複数回オープンできるかどうかも、
処理系定義とする」ってことだから、一般的には好ましくないね。
すでにfopen()されててまだfclose()されてないファイルに対する
2回目のfopen()が成功する(場合もある)か、常に失敗するかも「処理系定義」だし。 んじゃこうだな
#ifndef STDIO_H_
#define STDIO_H_ 1
...
#endif おまいらならFEのC言語問題余裕の全問正解なわけ?10分もかからんくらい? 少し古いが第一種情報とエンベデッドスペシャリスト程度はクリアしてる
即答クイズじゃないんだから時間気にするのは間抜けだぞ >>185
ああいう問題は実務では存在しないから簡単ではないよ。 マジで言い訳でもなんでもなく
業務のときと使う脳味噌が全然 違う。
普段 ファイルを単純に移動させるにも 外環境からどういう邪魔が入りうるか
プール単位で跨ぐときどういうセキュリティーホールがあるか
とかいうことを重箱の隅をつつくように考えてるのに
条件分岐を一度も使わずに素数生成しろ みたいな問題が出てくるんだもん
しかも出/入力データの危険性は一切考えない、っていうパターンがほとんど。 >>188
>条件分岐を一度も使わずに素数生成しろ
おもしろい問題じゃないですか、三項演算子 OK ならできそうですね そういった類の具体的な問題対処能力を試してみたいのであればスペシャリスト系の過去問でも見てみれば?
エンベデッドかデータベース試験の午後の記述問題あたりがいいと思う
https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_mondai.html 情報処理試験は実務やってたらAPよりスペシャリストのほうが簡単だわ。 「100以下の素数を表示するブログラムを作りなさい」
どんなプログラムを作るかで実務向きかどうかを判断できるらしい。 で、実務向きと判断される人はどういう風に回答するんだろうかw 「100以下の素数を表示するブログラムを作りなさい」だと
手打ちの固定テーブル(初期化済み配列)って解答もありそうだな。
2重のforループで「エラトステネスのふるい」を回して0/1の配列を生成。
値を表示する/しないは、要素2個の関数ポインタを格納した配列ってトリック。
そもそもfor, whileや三項演算子は「条件分岐」じゃないのか?
みたいな疑問を感じ始めると答えられないね。 単純に考えれば素数を漏れなく見つけるにはエラトステネスのふるいによるしかない
いかにして無駄な計算を避けるかが重要
プラグラム言語よりもいかに数学的素養の能力を身に着けているかが問われる
馬鹿正直に2から100までループを回すようならまったく実務には向いてない
整数論の基礎だけで100以下の判定に必要な要素は2,3,5,7だけであることはすぐにわかる
プログラムに落とし込む以前の問題 該当する素数一覧が埋め込まれた文字列を表示するプログラムが一番速そう 俺は拡張性がちらついてエラトステネスにしたくなるわ。どれだけの実行速度が求められるのかわからないとどの方法でやるか決心がつかなくてタイムアップしそうw >>192
問題の意図や目的を明示せずに解かせた答えだけみても、その人がどんな意図でその回答を出したのかは断定できないから、これだけで実務がどうこう言うのは短絡的だとは思うよ。
よくある性格診断とかで、○○を選んだあなたは××な性格です〜ってのがあるけど、解説を聞いてもまったく説得力のない決めつけがほとんどだし。それよりはいくぶんましだけど。 実務的には、「要求を満たし、簡潔にして高速で間違いがないこと」位かな >>199
いや拡張性をサッとそえとく心配りは必要だろ 夜な夜な素数配列DBをどんどん作ってくれるプログラムと、素数配列DBから値を引っ張ってくれるプログラムの組み合わせでファイナルアンサーだ! 3以上の素数は奇数であること。
n以下の素数を調べるときは、ルートn以下の約数を調べればいいこと。
整数論を勉強したなら、これくらいは知っておいて欲しい。 >>199
組み込み用でメモリが非常に少ないマシン用のプログラムの場合もう一捻り必要。 ま、いいや。うちに帰ってから俺が変なプログラム作ってみるよ。 >>196 こんな感じね。
#include <stdio.h>
int main(void)
{
puts("2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97");
return 0;
}
どうやって文字列を作ったかはヒミツ。本当に合ってるかは不明。
「素数なら表示し、素数でなければ表示しない」の部分は
テーブルがすでに出来てるとすれば、
tbl[i] && printf("%d\n", i);
てな具合に論理演算子の短絡評価を使う手もあるか。
パズルとしては面白いけど、実用で何の意味があるのか、
金払って受験する資格試験の問題としてどうなのか、疑問だなぁ。 素数の知識がなければ暗号解読やハッキングができないかも。 この流れだと
世の中のあらゆる暗号鍵はあらかじめ配列に格納することで突破可能、どうやって配列を作るかは秘密
とか言い出しそうだな
本質が分かってない
素数を高速に表示することが目的ではなく素数を少ない計算量で見つける事が本来の目的 >>188 「条件分岐を一度も使わずに素数生成しろ」
>>192 「100以下の素数を表示するブログラムを作りなさい」
2つの問題に同時に応えてるコメントがあるみたいね。
「条件分岐を使わずに100以下の素数を表示するプログラム」てことで。
かく言う自分もそのクチなんだけど。 >>207
そのアイディアに近いものはレインボーテーブルと呼ばれていて、すでに実用化されている。 >>209
レインボーテーブルはハッシュの検索高速化のための技術だと認識してたけど、素数を利用した暗号鍵の
Decryptにも実用レベルで応用できるのか? 一般的なコンピューターでは素数暗号の解読は困難だね。A5/1 Security Projectが進めばどうなるかわからないが。 Windowsのユーザーアカウントくらいなら数日あれば。。。 >>192
「100以下の素数を表示するブログラムを作りなさい」
これ素数の定義が問題に記載されておないとただの数学の問題になってしまうな。 >>195
>整数論の基礎
素数だけで構成する積による表現がすべて自然数について存在すること、ならびに、この積の表現が一通りであることを証明してください
>整数論の基礎
単に掛け算の交換則だけでいいのでは? >>197
エラトステネスの篩にも欠点があります。
篩の大きさだけ広大なメモリ空間を確保しなければなりません
限られたメモリ容量で超巨大な素数を求めることは可能ですか? >>202
>3以上の素数は奇数であること。
>n以下の素数を調べるときは、ルートn以下の約数を調べればいいこと。
あえて聞きます、証明はどのようなものに? >>205
それは表示した数が、果たして素数かどうか、を示してはいませんよね >>206
RSA 暗号はもう古いです、今は elgamal 暗号がトレンドです >>215
「ある整数の倍数の存在が周期的であること」を利用すれば、メモリーを節約できる。 >>207
>素数を少ない計算量で見つける事
個人的には、素数の原始根を求める方法が知りたいです、いまんところ力技で解くしかないかと >>219
たしかに 2 と 3 の公倍数である 6 をもとに
6n + 1, 6n + 5 だけをテーブルに載せる、とかは可能ですね
私はやったことがない、それはどうでもいいとして、これをコード化(coding-realized) したのも見たことがありません、いつか誰かやるだろうと思っていたんですが、なかなか表に表れませんね >>216
3以上の素数pが奇数でない、すなわち偶数であれば、偶数の定義より、pは2で割り切れるが、pに2以外の約数があれば素数でない。矛盾。□ >>201
サーバー側ならこれが攻守最強だな。隙がねぇ…… >>222
>pに2以外の約数があれば
ここがおかしい >>221
素数プログラミングの競技に参加してやってみれば? 倍数の周期性を使えばBuzzFizz問題の応用(多重化)でメモリーが節約できるはず。 バッチ処理で素数生成するなら、途中から計算を再開できるようにしておくとよい。 「3以上の素数は偶数ではない」って、
「2以外の2の倍数は素数ではない」と言い換えられるよね。
対偶命題の真偽は等しい、ってことで。
「3以上」「2以外」の部分の処理がちょいと面倒かも知れんが。
素数の定義から自動的に成立する、トートロジーって気もする。
実用的には、チェックすべき対象が一気に半減するから
決して役に立たないつまらない事実とは言わないけど。 なぜ「nの倍数」のうち「2の倍数」だけを特別視するんだ? たぶん2の倍数に特別に「偶数」って名前がついてるから。
て言うか「2の倍数」を「偶数」と呼び替えるせいで
「3以上の素数は偶数ではない」がそれらしい命題に見える心理的効果。 じゃあ例えば3の倍数を俺数と呼ぶことにすれば
「5以上の素数は俺数ではない」がそれらしい命題に見えるわけか >>237
実際にそういう理屈で俺数をちゃんと名前つけて定義してた気がする https://ja.wikipedia.org/wiki/%E5%9C%8F%E8%AB%96
集合論的な数学理論の構成では集合やその元に対して写像や関係を導入し、それらが満たすべき公理を列挙する。その公理を満たすような「構造」を持った個々の集合が理論の具体的な実現を示していて、それら一つ一つの実現に共通の性質が公理から演繹的に証明される。 10進数で扱ったときに下一桁だけで素数でないか判定できるし https://ja.wikipedia.org/wiki/%E4%BB%A3%E6%95%B0%E4%BD%93
一般には、素数は代数体の整数環の素元として定義される(そこでは反数などの同伴なものも素数に含まれる)。このため、有理整数環での素数は有理素数と呼ばれることもある。
自然数あるいは実数の中での素数の分布の様子は高度に非自明で、リーマン予想などの現代数学の重要な問題との興味深い結び付きが発見されている。 >>240
意味ないじゃん
下位一桁で素数か判定できるなら有り難いが 2の倍数は1個となりにあるけれど3の倍数は2個となりにあるわけじゃないからだろ 世界の半数の人間を一気に殺せるとしたら、スゴイ兵器だろう https://ja.wikipedia.org/wiki/%E5%90%88%E5%90%8C%E7%AE%97%E8%A1%93
ガウスの貢献はこの集合、今日整数の合同類 の環 ℤ/nℤ と呼ばれる代数系、の構造を詳らかにするものであった。第一に加法に関して考えれば、これは 1 を生成元とする巡回群を定める。第二に乗法に関しては、これは法 n に依存して性質が異なり、法 n が素数ならば体が得られる。このような方法により、計算の記述は簡素化される。 平方剰余の相互法則は奇数の素数でしかなりたたないから2は特別らしい プログラマ以前のただのC言語の評論家の集まりだからな
数学の素養どころか一般的な定番アルゴリズムすら理解しているのか怪しいのがいくらでもいる 「100までの素数」は単にロジックが書けるかどうかの話で、素数の話ではないだろうに。 配列に数字を並べて表示するだけの処理の何処にロジックがあるのやら
あれではただのゴリ押しだ 誰かがこの問題から実務向きかどうかがわかる、なんて言うからいけない 最近知ったことだが、clangとclang++には、-pedantic -Wallの他に-Weverythingというオプションがある。これを使えば最大限に警告してくれる。 とりあえず、Cできない娘は受付時に言うとか、ホームページにわかるようにしてくれないとキツイ。 >192
「オッケーグーグル、『100以下の素数を表示するブログラム』を端末にダウンロードして!」 C言語とか勉強じゃなくて仕事だったり動くもの作らないと覚えられないと思うんだけど
何をすることでC出来るようになったの? 納期までに完成させないと大変な事になるというスリルとサスペンスが人間の能力を引き出すのです。
しかしこれは恐怖から逃れようとする行為なので恐怖がなくなる、または度胸がついてしまったらそこで終わりです。 #defineじゃなくてconstすすめてくるやつは机上の空論だな
constつかったら最適ななしにするとswitchのラベルにつかえないじゃないか >>263
C++ では const 変数を case ラベルに使えるから、混同してる人かも。 C なら「名前のついた整数」は enum だね。
スコープ効くし case のラベルにも配列定義の要素数の指定にも使える。 Cのenumはenum-baseがないから
どでかい定数には使えない enumはあくまで値の大小は関係なくユニークな識別子であって、大きな値が問題になるような用途に使うのはいかがなものか。 プリミティブな定数以外のスイッチって
ものすごく気持ち悪いんだが
長大数渡して色々工夫してスイッチするのと
似たようなことコンパイラがやらなきゃいかんよね C の enum は「互いに区別できる一群の整数値の組」で、
具体的な値にさほど拘らない用途で使うべき、っていう
言語機能のそもそも論を言われると、その通りなんだよな。
その意味では case のラベルに enum の値を使うのはいいけど、
配列定義の要素数で使うのは便利にコキ使いすぎ、って感じか。
実際のところ enum で表現できる値の範囲が、
配列の要素数指定に使える範囲(size_t)と一致するか、という
疑問を持って調べたけど、いまいちハッキリせず今も解消してない。
まぁ、それ言うと case ラベルで受け入れられる値の範囲が
enum の範囲と同じか、についても確信ないんだが。
(権威主義に逃げ込む気はないと事前に言い訳した上で)
#define のマクロ値の代わりに enum の値を使うってのは、
カーニハンとパイクの『プログラミング作法』第1章、
「1.5 マジックナンバー」で紹介されてることを付記しておく。 enum
{
a = 4294967297
};
int main()
{
printf("%d\n", sizeof a);
printf("%llx\n", a);
}
gcc:
8
100000001
cl:
4
1
どっちが正しい?
とりあえずはコケるほうに合わせるが 以前に組込み用途の8bitマイコン用C言語を使っていた時の話
CPUの機能的にint型は8bitだった
ところが多条件の分岐処理でif-elseを使った時よりenum変数のswitch文使った方が明らかにパフォーマンスが
低下して問題になったことがあった
訳が分からず逆アセンブルして調べてみるとenum変数は何故か16bitに展開されていて条件判定毎に型変換が
発生していたことが原因だっということがあった、という昔の思い出 >>271
int が 8bit という時点で仕様に反しているので
整数演算のいろんなところで暗黙に int に変換してから
計算する C のルールが破綻するんじゃなかろうか。
処理系が必ずしも言語の規格に完全準拠する必要はないけど、
基本的な部分で変えちゃうとどういう挙動になるのか
予想しづらいよな。 charがその処理系の最小bit数であることだけは仕様に明記されてるけど
それ以外の整数型は大小関係だけが規定されていてintそのものに
具体的なbit数の決まりはなかったんじゃなかったっけ?
実際その時もchar、short、intが8bitで、longが16bitだったと思う >>270
C ではこういうルールになっている
・ 列挙定数の値を定義する式は int 型で表現可能な値を持つ整数定数式でなければならない
・ 列挙体 (列挙型のオブジェクト) の大きさは要素の全てを保持可能な大きさをもつ
がその選択は処理系定義である。
・ 列挙定数の型は (列挙型ではなく) int である
つまり、 C では列挙体と列挙定数の型が異なり、
列挙定数の型は int そのもの。
それは単に int の大きさがそれぞれ違うってだけじゃないの?
だとするとどちらの挙動も仕様通り。
(余談だが C++ では列挙定数の型は列挙型なので、 C とは少し解釈が違う。) >>273
気持ちとしては賛成したいんだが
残念なことにISO/IEC9899 5.2.4.2.1 Sizes of integer types <limits.h>に、
INT_MAX +32767と書いてあるんだ
腹立たしいクソ規定だがそうなっている >>273
ビット数という形ではないが、
limits.h で定義される各整数型が表現可能な数値の範囲を表すマクロ
についての最低限度の値という形で間接的に定義されている。
C99 だと 5.2.4.2.1 にある。
int は実質的に 16bit は必要。 整数型をワードより大きくしなきゃいけない
なんてなったら使い物にならんよな 確かにint型は規格的には最低16bit必要みたいだなぁ
C11 N1570 draft
5.2.4.2.1
―int型オブジェクトの最低値
INT_MIN -32767 // -(2^15 - 1)
―int型オブジェクトの最大値
INT_MAX 32767 // 2^15 - 1
6.2.5.5
「単なる」int型オブジェクトは実行環境のアーキテクチャにとって自然な(<limits.h>ヘッダに定義されたINT_MINからINT_MAXまでの任意の値を含むに十分大きい)サイズをもつ。 >>271
そのせいで組み込みでswitch使うな伝説が発生したんだな
逆に16ビット以上なら使っても問題ないということか 言語規格そのものというより標準ライブラリの都合というかヘッダーの仕様だけのような気がするけど
limit.hで最大値と最小値を規定するのであれば-128と127を宣言すればintの範囲を変更した実装も可能ではあるな
厳密には問題があるかも知れないけどC99準拠の実装と言うことでお茶を濁している処理系はあり得そうだ >>279
組み込み市場的に8ー16bitが主流だけどな。 一時期、組み込みもLinuxに席巻されそうになったこともあるけど昨今のIoTブームで16bit以下の超省電力が復権してきたイメージあるわ。 でもそういう機器ってメモリの読み書きしかすることねえもんな。
あんまりおもろない。 組み込みではLinuxどころかOSすら搭載してないシステムも多いよ
ネット家電なんかの一部を除けばエアコン、冷蔵庫、洗濯機など家電製品の殆どはOSもファイルシステムもネットワークスタックも無縁のスタンドアローン動作
電源投入リセット後ひたすら処理ループを回すだけ
CPUコアは8bitか16bitでRAMは数KB、ROMは数十KB程度のワンチップマイコン メモリの読み書きよりもIOポートを制御するのがメインの仕事 電卓ほど単純ではないけどね
まともにフィードバック制御を実装するにはそれなりの演算負荷は掛かる
センサー入力に応じて出力を迅速安定に目標に追従させるには裏では予測判断も必要
マイコン使っている以上は単調なON/OFF制御では無いよ 欲深い人間のことだからどうせすぐいろんなことをさせたくなる メモリーバスが I/O につながってることもあるしな。 >>291
IOポートを弄るにはそれぞれのSFR(特殊機能レジスタ)を操作する
一般的なメモリマップトIO方式ではSFRはCPUの特定のアドレス空間にマッピングされてる
Cプログラムからはそのアドレス空間をそれぞれ適当な変数に割り当てて基本的にはビット操作で制御する
SFRのイメージが分からなければ適当なマイコンのデータシートでも見てみるとある程度は分かると思うよ
参考として電子工作で有名なPICマイコンのサイト貼っておくので見てみるといいよ >>274
だな
あのあとgcc -pedanticとやってみたら
ちゃんと警告出たわ 組み込みマイコンでI/O空間がx86みたいに別なマイコンってあるかな メモリ(RAM)に割り当てられた変数は演算とその結果に意味がある
IO(SFR)に割り当てられた変数はビットのR/W操作そのものに意味がある
SFR変数上で演算操作を行うとほぼ確実に誤動作、暴走する >>297
I/Oポートの挙動はメモリと同じとは限らない
書き込みと読み出しが別のものに繋がっていることもある
volatileは本来このためにある >>296
あるよ。AVRはメモリマップされたIO空間にin/out命令で効率的にアクセスできる。 >>299
READアクセスでSR、WRITEアクセスでCRというケースは珍しくないが
なんで突然volatileが出てくるんだ? 全然関係ないぞ Read動作を確実に実行するためだろう
プログラム上はSFR変数からダミー変数への代入にしか見えないので何の演算にも関与しないと判断されて
コンパイル時の最適化で処理が削除される恐れがある
SFR変数はvolatile宣言しておくのが普通 それはREADの回数やタイミングの話だろ
READとWRITEで対象が異なる場合があることと何の関係があるんだよ そこに拘っていたのか
てっきりメモリとIOによる変数の扱いの注意点のことかと思っていたわ volatileなしだと、同じsfrにwriteした直後にreadすると最適化により実際にはreadされないことがある。 メモリとIOは違うっていっても、要は裏でなんかやってるだけだし。
だからvolatileなんて話も出てくる。 >>305
他に何に拘っていると言うんだ?
> 書き込みと読み出しが別のものに繋がっていることもある
↑
何の関係があるんだ
↓
> volatileは本来このためにある
答えるか撤回かどうなんだ >>309
306は話のすり替えだ
READの回数やタイミングの話なんかしていない
READとWRITEの対象が違うということについてだ
volatileと何の関係があるのか
ただの言い間違えか
どっちだ? >>310
CRにwriteした直後に同じアドレスのSRをreadした時に最適化され、write値がそのままread値に使われるのをvolatileなしでどうやって回避するのん? >>308
横からだけど>>305の2行目ぐらい読んでやれよ
それとも俺様に謝らないと許せないってか? w >>308
知らんがな、>>299本人に聞けよ
一般に言えることはメモリ上の変数の場合は読み込みと書き込みの間には必ず何らかの関連性を持っている
意味もなく読み込みや書き込みを行うことはなくその値は必ず何処かで利用される
利用されなければ変数もろとも普通は最適化で削除される
SFRの変数の場合はRead/Writeその操作の行為そのものが目的であってその結果その値がどうなろうが値そのものには何の意味もない
コンパイラにそのことを明示的に指示する方法がvolatileということ こうして見るとやはりC言語は組み込み屋専門ということか
話が難しすぎてついていけねえw >>311
という説明ができるの、あんただけみたいだな
頓珍漢なレスばっかでイラついてたわ >>314
全然難しくはないし、組み込みに限った話じゃないよ。
ただ単に「今見えている処理とは別のとこからそのアドレスの値が更新される可能性があるので最適化しちゃダメよ」ってのを明示的に示すためのvolatileなので。
C#やJavaとかでもスレッドをまたいで不用意にアクセスする変数はvolatileつけないとバグるし。 組込専門、みたいなひとって抽象的な話のできないクソ多いよ。
コードもクソが多い。sleepせずにビジーウェイト使うタイプ。 横レスだけどWrite属性のSFRの値(この場合CR)をReadしても値は不定だけどね
同一アドレスにマッピングされているRead属性のSFRの値(SR)の値が返ってきて変数に代入されているだけ
普通はWrite属性のSFRの状態を記憶する必要があればバッファ変数に内容を保存しておく write属性なんて用語あったっけ
ゲートだけ出てるのはREでデコード
トーテムポールになってるのをWEでデコード
というのは属性か? Read/Write属性というのはあるよ
むしろその方が多い
ただ前レスに出てきたCR(コントロールレジスタ)とSR(ステータスレジスタ)は意図的にその名称通りにWriteまたはRead専用属性の例として
提示してきたんだろ、多分 いやーないだろ
ゲートが出てるだけのユニットにWRITEサイクルを実行なんてしねえし すまん
書き込みの意図がいまいちよく分からんのだけど出力形式の切り替えの話か?
オープンコレクタ出力とトーテムポール出力の切り替えか?
というかこの文脈でデコードの意味が分からん、何のこと? 誰かわかる奴いるのか?
俺も>>319は意味わからん volatileの話が本筋と関係ないなら適当に流して先に進めばよかったんだよ。
それなのに噛みついて話を爆発させてしまったところにコミュニケーション能力の欠如を感じる。 このスレはC言語という話題を通じてマウント取り合うスレなので、今日も平和に通常運転。 ゲートが出てるのがオープンコレクタとかもう
そのうち電圧が流れるとか言い出しそうな勢いだな volatileまではまだ分かる
ゲートやトーテムポールやデコードの単語の羅列は意味不明 >>320
> Read/Write属性というのはあるよ
いやいや、 Read onlyとかWrite onlyって言うのはわかるけどRead/Write属性なんて言う用語を使うか?
って話な
>>324
なんとなくデコードって言うのはアドレスデコードした信号(要するにChip select)にRE(多分Read enable)とかWE(Write enable)をandする話だと思う
ゲートとトーテムポールはよくわからん >>330
そういうことか
マイコン内蔵デバイスの話ではなくてガチのハードウェア回路設計のアドレスデコードとコントロール信号の話か
唐突過ぎて訳が分からなかった ReadやWriteではなくて入力信号と出力信号だな 内部or外部CPUバスのことを言ってるにしても、Write onlyがないってとこに繋がらない。
やっぱ解読不可だわ。 そういえばread-modify-writeっのを思い出したな
もう10年以上前の事だが 懐かしい話題だな
わざわざラッチ回路を設けて問題回避したりしていたな >>330
ちょっと亀レス気味だけど、確かに属性というのは一般的ではなかったかな
当時使っていたCコンパイラでは同一アドレスにマッピングされたRead OnlyとWrite OnlyのSFR変数は
共用体unionで宣言するのだけど、それぞれが読み込み/書き込み専用の変数名であることを明示するために
プリプロセッサの#pragmaでいわゆる属性(R, W, R/W)を宣言することが出来た
Read属性変数に代入操作を行なったりするとコンパイル時に警告されるような仕組みになってた write属性レジスタってのは確かに一般的ではないけど、かといって用語としてwrite専用レジスタじゃないといけないって明確なルールもないだろうし、仕様書書いてるわけじゃないので別に雰囲気で伝わるから気にしなくていいんじゃない? 一般的な用語じゃないとそこにどんな機能が含まれてるかわからんからな
>>336見りゃわかると思うがそもそもレジスタの機能ですらなかったわけだし 議論の流れで大体わかるけどな
さすがにプログラム言語やマイコンの話の中でいきなり回路設計の話が出てきた時は
しばらく話について行けなかったが >>339
お前はわかるのかも知れんが>>319みたいにちゃんと確認しようとする奴もいる
そもそも一般的で無い用語を使う理由もないだろ これぐらいのことが話の流れで推測できないなんて、生き辛そう。
お大事に。 >>317で指摘されているけど抽象的な話のできない人というのは確かにいるからな 確かに昔からハードウェア弄ってきた純粋の組込み専門屋にとって、周辺デバイスの制御レジスタをSFR変数として抽象化して捉えることが出来ないとは思ってもなかった
一般的ではなくても属性で話は通じると思ってたんだけどなあ
というか本当にC言語で開発してるのだろうか? 「出来ないとは思ってもなかった」
否定の否定表現でわかりにくい。 SFRって特定アーキテクチャの特殊用語じゃん。何勝手に一般化してるん。 ワンチップマイコン使ったことが無いのなら口を挟まないほうがいいよ
どこの製品でもSFRで話は通じる もしかして組み込み以外の話は
【初心者歓迎】C/C++室 Ver.104【環境依存OK】
で聞いた方がいいのか? C言語の一般的な話題を扱うスレなんだから
特定の人間を排除するような発言をするのはおかしいだろう
そういう特定の話題をしたいならスレを立ててすればいい
ワンチップマイコンは専用スレ立ててそこでやれと言う話 今や純粋なC言語の所理系は初心者の学習用途か組込み開発用途くらいでしか使われていない
スレに組込み開発経験者が集まるのは自然な流れ どちらかといえばC言語学習者は高圧的で排他的な気はする 妥当な発言なら問題ないんだけどね
挑発的な発言が目に余るので煽り発言は控えたほうがいいと言ってるだけ そもそもワンチップマイコンの知識は
C言語の話題をやり取りする上で必須ではないだろう
そういう話題を話したいなら専用スレを立てろと言っている 相変わらずみんな仲いいな。
今日も平和に通常運転。 >>346
それ単にプログラム内のルールにすぎない。どんな言語であれ、入れ物を使い分けを限定することで、プログラマのミス防止や可読性、保守性が高まるのは、まともなプログラマなら必ずやっている。
これがハードウェアの機能にあるのか、ソフトウェアの機能にあるのか、それともそんな機能はないのでコーディングルールなのかの違いにすぎない。 >>346
それ単にプログラム内のルールにすぎない。どんな言語であれ、入れ物を使い分けを限定することで、プログラマのミス防止や可読性、保守性が高まるのは、まともなプログラマなら理解している。
これがハードウェアの機能なのか、ソフトウェアの機能なのか、それともそんな機能はないのでコーディングルールなのかの違いにすぎず、現代では常識的な話。
コンピュータにとっては動けばいいわけで、設計の話とアーキテクチャの話をごちゃ混ぜするからよくない。
高水準言語であればあたりまえすぎることだが、C言語は中水準言語で、OS、ハードウェアの組み合わせにより、動きが異なるから、本来は仕様、設計があって考えること。
これがアーキテクチャがこうだから、こういう発想になるというのは順番が逆。 普通に一般化してる用語で話せばいいのになぜかオレオレ用語使って指摘されたらわからないのかとか逆ギレw
なんとなくはわかってもそのローカル用語が意図してるものと自分が思ってるものが同じかどうかはわからんから指摘してるのに…
まともなエンジニアじゃないんだろうな 知識や能力の不足に対する自己防衛反応みたいなものだから流し読みしてればいい 具体例なしで一般論しか言わないやつは信用できない
特徴は具体的な質問されると話をそらすか黙り込むやつ >>346
あ? ベアメタル系のプロだが
おまえみたいな手合いがSFRとかどういう意味で言ってるのかは警戒するぞ ベアメタル系のプロの意味がよく分からないけどC言語と何か関係あるの? 大体何と勘違いしたのか予測はつくがおそらく間違ってるぞ
少なくともx86系では通用しない すみません、初心者なんですが図書館にプログラミング言語Cという本があったので借りてきて勉強中です。
p105のコード
nはint
if(n / 10)
printd(n / 10)
なんで割り算自体を条件に出来るのですか。 出来るかどうかは自分で試した方がいい
その上で、なんでそうなるかを考え、
分からないときに聞きにおいで >>376
わり算の結果(この場合は整数)がゼロじゃなかったら論理値の真(true)と見なされる。 >>376
C言語のifは0か0以外かしか見ていないため。 >>378 >>378
ありがとうございます、==とか>とかでの比較しか頭になかったんですけど、ifは0かどうかだけなんですね。 他の言語でいえば
1:true
0:false
って感じですな >>381
この表現は語弊があるので忘れてください、すみません >>376
こういうように条件文に、実質的なbool 値以外を書いたら、ダメ!
MISRA-C みたいな、安全なコーディング規則があって、禁止事項になってるから、
普通のプログラマーは、変に思うはず 他の言語ならともかくC言語プログラマ的には普通だな 説教くせえことを書くならてめーの言葉遣いくらい気をつけろ
boolじゃねえだろ_Boolだ
MISRA-Cが安全だなんて決まりはどこにもねえぞ
コーディング基準はそれを守りさえすれば安全だなんて信じているようだが自分の頭で考えることを放棄した手合いか?
少なくともそういうカスはPGとして普通未満だぜ >>380
そう。比較する演算子を使うとその結果が0または1になるので他の言語でのifと同じようにも使える。 ISO/IEC 9899:2011 7.18 Boolean type and values <stdbool.h> には
マクロと書いてあるが、どこかに予約語と書いてあるのか?
ISO/IEC 9899:2011 6.4.1 Keywords にはねえぞ >MISRA-Cが安全だなんて決まりはどこにもねえぞ
>コーディング基準はそれを守りさえすれば安全だなんて信じているようだが自分の頭で考えることを放棄した手合いか?
>少なくともそういうカスはPGとして普通未満だぜ
この3行が主張なわけでboolについて話してる時点で話それてないか?w 漏れが言ってるのは「実質的なbool 値」
特定の物を指していない、一般的な言語での概念
条件文に、実質的なbool 値以外を書いたら、ダメ!
品質基準から減点される
トヨタでも、100点満点中、5点しか取れなかったとか、言ってる人いる
MISRA-C 無しのC 言語は使ってはならないと、決まっている! 昔々、int bool = 0; と書いてあって普通に変数として bool が使われている夫馬ログラムを見た事がある。 昔はintの別名でマクロ定義してたな
今は予約語だったのか 夫馬ってなんやねんw
スマホでの打ち間違いは候補間違いもあるからより変な風になるなあ。 boolが予約語というのは聞いたことない。
<stdint.h>で使えるのは知ってるけど。 >>391
ほう論点が2つあるのをおまえの脳内では話がそれたと言うのか >>398
いやすまん、boolについては論点にしてないと勘違いしていた。 やっぱり相変わらずみんな仲いいな。
今日も平和に通常運転。 >>376
>if(n / 10)
は if(n / 10 != 0)
に読み替えてください >>383
MISRA-C は馬鹿が使うものと聞いていますので、あなたも馬鹿の一人なんですね >>385
C99 の _Bool はいろいろと残念な仕様なので、そんなものを使っていたら馬鹿呼ばわりされてもしかたがないと思います… >>392
その「実質的」という単語の定義を教えていただけませんか? >>404
いやーそこはちゃんとカッコをつけて
if((n / 10) != 0)
じゃないとMISRA通らないだろー。
と煽ってみる。 >>394
C の予約語に asm が存在したことがあっても、bool なんて金輪際ございません… >>408
なんだか misra っていろいろうるさいですね…馬鹿が使うものの典型と理解しました >>410
そのとーり。
MISRAはfool proofのための規格だよね。
あんなもん、クソの役にも立たんわ。 実際の開発現場ではMISRA-Cも_Boolも頭の片隅に意識する(人がいる)程度であまり意味はない
そんなことより他に考えることはいくらでもある >>411
久々に私の意見に賛成する人がおられましたね… essentially Boolean (実質的なブール型)
C90にはブール型はないが、真又は偽のブール値を表す式はある。
MISRA-C:2004ではこのような式をブール式と呼んで、数値を表す式と区別しており
if (hoge==TRUE)
このhoge が、実質的にはブール値なら、if (hoge) と書いてもOK >>404
そういう例はやめた方がいい。二度、評価することをおかしく感じなくなる。 >>417
マクロ関係ではないから、二度評価問題は関係ないのでは?もう少し詳しく教えていただけますか? 2値しか取らない、真偽値という概念を作り出して、単純な数値と区別している
明瞭になるように、可読性を高めるために、明確に使い方を分けている essentially Boolean (実質的なブール型)
hoge が単純な数値なら、if (hoge) とは書けないので、
比較演算子などを使って、( )内を真偽値にしなければならないが、
hoge を2値しか取らず、実質的には真偽値として扱っているなら、そう書いてもよい >>382
というよりtrueとfalseを使えよ C++か他の言語か勘違いしてないかな?
C言語の枠内では(以下略 #include <stdbool.h>すれば、C言語でもbool, false, trueが使える。C99から。 マクロなのか 乱暴な解決法と見るか予約語にしなかった・できなかった理由があったのだろうか >>428
bool 型は C99 では _Bool 型となり「bool」そのままではありません >>413
口調が似てると思ったら、やっぱりあいつだったのね >>418
if ((n / 10 != 0) != 0) とは書かないのですか?
if (((n / 10 != 0) != 0) != 0) とは書かないのですか?
if (n / 10) で充分だろ if文の仕様がまずかったんだよな。演算子がコマンドで数値を返すところがいまとなってはわかりにくい。 C の _Bool は完全に後付けだし、
true, false の型は int (整数リテラルの 1 や 0 に展開されるマクロ) ってのも
C らしい歴史的経緯ってやつだよねぇ……。 なんでもいいがboolは使った方がいいよ
キャストするとちゃんと0と1になるよ #define TRUE (1==1)
#define FALSE (!TRUE)
昔はこう書いて使ってたっけなあ _Bool型(stdbool.hインクルード時はboolも可)の値は0か1しか取り得ないのでわざわざキャストする必要は無い
しかしながら自分はC言語では普段は_Boolもboolもどちらも使わない
単純にintなどの数値型を0か非0かだけで判断して使ってる
尤もC++ではbool型は普通に使っているけど
https://i.imgur.com/47mIrVh.png >>376 を見て、久し振りに『プログラミング言語C』を開いてみたところ、
確かに p.105 に printd() って関数が載ってる(第2版)。
ここのテーマは再帰なので printd() は「1文字出力 putchar() を使って、
整数値を10進数で表示する再帰関数」の例。
話題の if (n / 10) では「n が 10 以上か」を判定してる。
直前で符号の処理をしてるので n が負ではないことは保証される。
(さらに「だだし n == INT_MIN の場合は…」に相当する注記あり)
で if (n / 10) が if ((n / 10) != 0) の意味だってことは、
p.68 第3章 制御の流れ 3.2 If-Else でさらりと説明されてるし、
その前 p.63 の条件式(三項演算子)の部分なんかにも載ってる。
たぶん他にも、あちこちで出てるんだろう。
「真と偽」みたいな独立した項目を立てた方が良かったんじゃないかな。
そうすりゃ索引からも探せるようになるし。
ついでに言えば、この場面では if (n / 10) より if (n >= 10) の方が
やってることが明解だし、処理も軽い気がするなぁ。 単純に開発当時のC言語としては処理をシンプルにしてパフォーマンスを稼ぎたかったのだと思うよ
普通のCPUは0か0でないかの判断は得意だけど0か1の判断は手間が掛かる
少しでもパフォーマンスを稼ぎたい場合(現在では組込み用途など)では余計な処理は極力除くように工夫する >>440
処理が軽いかどうかはちゃんと実測で比べろ
妄想だけで完結するアフォがよくいる いや、さすがに単純な整数値の大小比較と、割り算とで
どちらが速いか実測しなくちゃ分からないってのは
「実測しろ」って原則を無批判に(条件反射的に)
振りかざしてるんじゃないの?
予測は一切禁止ってルールじゃないでしょ。 >>433
n / 10
と
(n / 10) != 0
の型を意識しない底辺乙 w >>444
そもそも>>440が言いたかったのは「やってることが明解だし」の方だろうしな
なんにでも噛み付く老害なんでしょ、スルー推奨 でもcのコンパイラって割り算の時は最初に比較があって、n < 10なら比較直後に0返すんじゃなかったかな。
昔アセンブラの実習でやった気がする。
帰ったらみてみよ。 n / 10 と (n / 10) != 0 とで違うコード吐くとか?
オプティマイザなめんなよ >>439
最新のwindowsでもフォントにアンチエイリアス掛かってないのか
Mac唯一の利点だな MSゴシック以外のとこはアンチエイリアスかかってるだろ >>447
割り算はコンピュータにとって簡単なことではない。人間だってそうだろ。 >>445
0〜1以外を取るかどうかが違うだけで型は同じでは?
等価演算子(==と!=)は真の時に1、偽の時に0を返すとしか明記されてないでしょ >>453
自己レス、型はintって書いてあったわ C では比較演算子が返すのも、 if の判定にも真偽値型は現れない。
真偽値型は後付けで、言語の中核の意味論には関与しない。
真偽値型は整数型の一種だから何か演算しようとすると整数拡張で int になってから計算するしな。
_Bool で表現してもほとんどの場合にコメントと同程度にしか意味ない。
コメントと同程度に「意図」を表せるならそれはそれで有用ではあるけど、
型システムが間違いを防止する役に立つ場面はあんまりない。
(余談だが C++ では (組込みの) 比較演算子は真偽値型を返すし、
if の条件節は真偽値型にキャストして判定するので C とは解釈が違う) >>453-454
型が同じだから区別不要?
昭和の老害かよw >>456
「型は同じ」って言っただけで区別不要とはどこにも書いてない訳だが いや、マジで型安全とか知らなさそうで可哀想ですらあるんだが… >>459
> 型を意識しない底辺乙 w
にレスしてるのに?
なら結局何を言いたかったんだ? >>461
言い方として「型を〜」っていうのが(あくまでC言語として)おかしいなと思っただけだよ
別に!=0をつけた方が分かりやすいことは否定しないし 「ばあさん、いただきものは型を意識した応答だろう」
「いいえ、お爺さん型を意識した応答でしたよ」
「そうかい、わしゃまた型を意識した応答だと思ったよ」 >>464
双方が int に拡張されて足し算されて 2 になったのが
再び bool にキャストすると 1 になる。
演算子の両方の型が int より小さい場合には
両方が int に拡張されてから計算されるというのが
C の基本的なルール。
(全ての演算子がそうというわけではない。) >>455
MISRA-C は、C89/90に、bool という概念をバックポートした。
それを「実質的なブール型」と呼んで、単純な整数型と区別している
ブールを表現する場合は、整数型を使っていても、
それはブール型ですよってアピールする事で、
技術者間での意思疎通を図り、安全性を高める >>466
なる場合とならない場合がある。
古いコンパイラではならない。 あれ、ぶーる同士足し算できないの?
ちょっと信じがたい気はするけど 1bit計算のインストラクションなんぞ
わざわざ作らないだろ
そもそもbool型ってなんだよ
気持ち悪いな 要は
bool a = 1;
bool b = 1;
として、
bool c = a + b;
ができたとしても、内部的には
bool c = (_Bool)(((int)a) + ((int)b));
になるってことじゃないの 整数型には加算はあるけど、
ブール型として扱うなら、加算は存在しない
AND, OR, NOT だけしかない
だから技術者間での、こういう共通意識が大切なわけ。
これは「実質的なブール型」として扱っているから、整数型の演算はできません!
ブール型が無かった時代の、
技術者間での意思疎通を図り、安全性を高める、苦肉の策 bool a = true, b = true;
int c = a + b;
これは2 >>467
>それはブール型ですよってアピールする事で、技術者間での意思疎通を図り
そういうのは、わりきってハンガリアンを使う方がいいのでは?
bool を使うことで文法的縛りが導入されないことには意味がない気がします 仕様の話とコーティング規約とか作法の話が混ざってるからややこしくなってるのでは MSVCではbool変数同士の論理和でも加算でも再評価されて0か1のいずれかが再設定されてる
内部処理は全く同じ
gccの内部処理は分からんけど
https://i.imgur.com/3EzADoO.png >>467 >>472
コーディング規約・ガイドラインを設けるのは結構だが、
それを守っている組織・プロジェクトの中では意思統一しやすいという話であって、
技術者一般にまで適用できるほど強い権威は MISRA-C には無いよ。
仮に (あくまで仮に!) MISRA-C がとても良い習慣だとしても、
言語仕様としての理屈を理解しておくことは大前提だ。
元の質問者である >>376 みたいなのに MISRA-C を勧めても何のたしにもなりゃしないだろ。
規約としての理屈よりも言語としての理屈をまず説明してわかってもらわんと。 >>476
内部処理は全く同じ?
逆汗までしたのにどこ見て言ってんの? 最後に評価されるタイミングで一致してりゃなんでもいいんだけどね
+って相当するのはxorだかorだかわからんという問題もあるね >>479
> 最後に評価されるタイミングで一致してりゃなんでもいいんだけどね
とか言うなら内部処理ガーとか言うなよ
って話だろ
> +って相当するのはxorだかorだかわからんという問題もあるね
orはわかるがxorになることなんてあるのか? ついでにいくつか検証
xorは排他なので当然true同士はfalseに反転する
2項演算や0/1以外の値の代入(boolの範囲外の値であっても)は内部処理は共通
単項演算のインクリメントやデクリメントはコンパイル時に1か0を割り当てるため別の処理らしい
https://i.imgur.com/STxUA6o.png ブール値は 0/1 しかとらないから1ビットの整数値、と解釈して
true + true == 1 + 1 == (2進数で)10 → 下位1ビットを採用して結果は 0
よってブール値での加算はビットでの排他的論理和と同等、
という考え方もあるんだわ。
「無符号整数のオーバーフローの方式を1ビット幅まで狭める方向に推し進める」
とでも言おうか。 基本的なハーフアダー演算器の考え方だね
キャリーを出力してビットを反転させる
多ビット加算の基本構成
いくら高級アセンブラとしてのC言語であってもキャリーを抽象化した演算を実装するのは結構面倒だけど
多バイト加算はそれなりに手間が掛かる 仕様を小さくするため論理演算をビット演算で代用する言語はあったと思うが、
わざわざ下1bitだけで真偽を表すってのは見たことないなぁ。 >>482
> よってブール値での加算はビットでの排他的論理和と同等、
> という考え方もあるんだわ。
そんなの聞いたことないw
お前のオレオレ理論じゃないと言うならその考え方を示してる例を出してくれ >>485 分かりやすく説明できる自信はないけど、一応答えてみる。
と言っても、新しい情報は出ないので期待されちゃ困る。
>>482 は、そう考える考え方(代数系)が可能、という意味で、
そのように内部処理してるプログラミング言語の処理系が存在する、
という主張とは違うって点をまず断っておく。
その「ブール値の加算を排他的論理和と同等に扱う」体系が
内部的に矛盾を生じないこと、実用的な面で利用価値があり、
現実にも使われているってことは、>>483 がコメントしてくれた
前半部分で、十分に例示されてると思う。
て言うか、俺が下手にクドクド書いてもあのレベルは無理。 少なくともC言語である限りは規格に反するんじゃ?
_Bool型は0に等しければ0、その他は1って明記されてる(C11の6.3.1.2)から2進数で10は0に等しくないように思うが >>486
ハーフアダーはキャリーとセットで話すべきものだからハーフアダー云々は頓珍漢過ぎる Cの、ビット幅の狭い整数値は int に変換してから計算するってルールにより
true + true → (int)1 + (int)1 == (int)2 → true
という流れで true + true == true であることは納得してるんだ。
型が _Bool でも適用されるよね。勘違いなら訂正求む。
(今回の話とは直接関係ないけど、まるっきり無関係でもない余談)
ただ、これが例えば unsigned int の値を真偽値として扱う場合だと、
unsigned int a = UINT_MAX; // 真偽値としては真
unsigned int b = 1; // 真偽値としては真
a + b == UINT_MAX + 1 == (オーバーフローして)0 → 真偽値では偽!
という事態も起こりうるのでご注意。 加算てのは常に状態を変える操作なので、論理演算としてはXORの方が似てるんですよ。
もちろん単に似てるという話で、加算は禁止するくらいが正しいといえば正しい。trueとfalseを1と0に割り当てたせいで足し算できそうな気になってしまったのがよくない。
1ビット整数だと考えてもいいが、元々そんなもんないからsizeofも1以上にするしかないという。
構造体に入れたらビットフィールドと同じメモリのレイアウトになるんだろうか。実装としては。 C言語の_Bool型(boolはただの別名)のtrueを1以外に割り当てるとC++との互換に問題が生じる
C++のbool型のtrueの内部表現は1
bool(論理型)をcharやintなど(整数型)にcastすると1が返される
C++では論理型同士での四則演算は不可能なので問題は生じないが論理型の存在しないC言語ではどうしようもない
trueを1に割り当てて妥協するしか無いと思う >>444
>「実測しろ」って原則を無批判に(条件反射的に)振りかざしてるんじゃないの?
いいところを突きますね、そうそうその調子、いい感じですよ
百人一首の上の句と下の句をつなげる、みたいな思考力を使わない、言葉のオートマタを批判するのはすばらしい着目です、感心しました >>492
作ったことはあります、最初 C でちょろちょろっと書いたのが、いつのまにか成長してまとまったものになりました、まだまだ改善は必要ですが
https://mevius.5ch.net/test/read.cgi/tech/1434079972/51 昔8bitマイコンの組込みシステム開発で、被除数が24bit長、除数が固定値(値は3)の除算処理が必要となったとき、
C言語の除算処理では実行時間が要求仕様を満足しなかったのでインラインアセンブラで書き下ろしたことがある
処理系そのものは16bit長までしか対応してなかったので、32bit長の汎用演算ライブラリ関数が付属してたのはいいけど
そのライブラリが遅くて使い物にならなかった 昔bool型ってのを初めてみたときは、誰が使うんだよ気持ちわりーって思ったな。charで8個もフラグ取れるし、
flg & 04とかで好きな位置のビット取れるし、なんでわざわざtrue,falseと思ったもんだ。 貧民てか脳がアセンブラに侵されてる
Pascalから入った俺はintでBooleanの代用とかサボりすぎだろって思ったわ 当初から予想された抵抗だ
Pascal教に対する宗教改革じゃけえの >>497
思い切り最適化されて最終的なコードがそうなれば誰も文句言わないんだろうけどな。 bool は真偽値を格納するのに充分であればいいんだから普通は 1 バイトだろっていうのも昔の話で、
今の主要な処理系はだいたい int と同じ幅だったりしてあんまりリソースの節約にもならんかったりするし。 ブール値の変数を1ビットで表現して1バイトに8個押し込めば
容量の節約にはなるだろうけど、速度的には損な気がするな。
(これも「実測しなけりゃ何も分からない人」向けの釣り餌かも)
ブール値をバイトなりワードで記憶すれば、CPUによっては
レジスタにロードした時点でゼロフラグに反映されて
ゼロとの比較やマスク演算が不要という利点を得られる場合もある。 >>503
CPUしだいだろうね。レジスタに入れないで0かどうかだけ調べる命令があったらそれの方が速いかも知れんし。 / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|CPUしだいだろうね。レジスタに入れないで0かどうかだけ調べる命令があったらそれの方が速いかも知れんし
\___________ _______
V
/ ̄ ̄ ̄ ̄ ̄ ミ / ̄ ̄ ̄ \
/ ,――――-ミ / |
/ / / \ | ∨∨∨∨∨\ |
| / ,(・) (・) | |▲ ▲ ||
(6 つ | |(・) (・) 6)
| ___ | | | ||
| /__/ / | ¨ /
/| /\ \/\ /\
/ ̄ ̄ ̄ \
∧
/ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
| なわけねーだろ!!
\__________________ 真偽値の超巨大な配列が必要な場合ならともかく、
今の時代なら 1MB が 8MB になったくらいならたいした差ではないしな。
ただ、キャッシュにのるかどうかで劇的な差になったりもするから、
そこらへんは状況によるというか、それこそ実測しなきゃわからん。 >503
ロードストアに比べて
ALUの制約は少ない
だから詰めたほうがいいとなる
スペックシート読めずに
実測して速い遅い語ってる人は
遅くなると断言しよう プリミティブな静的変数のビットフィールドにアクセスするときってロック意味あると思う? >>508
しらん
>>503
フラグを全部使うなら8回ロードと一回ロード+マスクする
をくらべないとだめだろ 10進で2桁程度の「整数値」にもintを使えという主張に似ているな >>505
あれ?そう?そう断言できる根拠あるの? >>511
レジスタに入れないでって無理
メモリREADサイクルでどのみちラッチするんだから
名前のある公開レジスタか、名前のない非公開レジスタかという違いにしかならない
どうしても疑うんならHDLでCPU書いてみろ 自分にツッコミ。
「ブール値の変数を1ビット幅にしてメモリ1バイトに8個押し込む」方式は
Cの規格とは相性悪いね。
&でポインタ取ったときにバイト番地で表現できないとか、
sizeofで1より小さな小数を返すのか、とか。
「ある変数が1バイトより小さな領域しか占めない」って性質が原因だ。
>>509
その点は気がつかなかった。1回の判定しか考えてなかったわ。
1バイトを1回だけ読んでマスク値をシフトしながら判定と、
1バイトずつ8回読むのとで比較しないといけないね。
一度にもっと多く、4バイト単位とかで処理できるかも知れないし。 ソフトから見て1命令でも、メモリに対して1バスサイクルでビット操作は不可能だからねぇ。
メモリビット操作命令は裏でマイクロコードが暗躍して結局ロードストアアーキと同じ動きしてる。
lockが必要ない利点はあるけども。 >>514
ここはCスレだけど、それまさにstd::vector<bool>でやらかしたやつだね。 >>512
知らんよ。そういうCPUがあればそうだねってだけの話だし、お前もその自分の体験や知識から言ってるだけで全世界の全CPU調べた上で言ってるわけじゃないだろ?予想外の変なCPUはあるかも知れんから断定はできんだろう。 >>514
一応C言語では構造体にビットフィールドがあってビット単位で扱う事が出来るようになっているな。まああれは数値変数として扱うだけでboolではないわけだけど。効率が良いかどうかはどう最適化されるかに掛ってるかな。 要素が3ビットの多次元配列が簡単に作れて扱える様になると便利ですね >>515
メモリバスがネックになるようなシステムなら、
バス幅のビット分情報が詰まってるほうが、
メモリのアクセス回数減らせるから利点もあるだろう。
なんにしろ、一長一短は有るんだから
正しく理解して正しく使うことが重要かと。 >>518 1ビット幅のブール変数をビットフィールドと同じ扱い、
つまり「アドレスを求めることもsizeofを適用することもできない」
というルールにする手はあるか。
と言っても、アドレスを取れないとなると、ポインタ経由での操作、
配列に入れてインデクスで順番に走査することもできないわけで
非常に使い勝手の悪いものになってしまうね。 ビットフィールド構造体はあくまで構造体であるのでアドレスを返すことは出来る
というか自分ならビットフィールドだけでは使い勝手が悪いので構造体をcharなどと一緒に共用体に纏める
構造体を配列で操作するときなどは同一アドレスのchar変数でビットフィールドを纏めたパッケージとして取り扱う方が使い勝手がいい maxima
(%i1) load("bitwise")$
(%i2) bit_not(i);
(%o2) bit_not(i)
(%i3) bit_not(bit_not(i));
(%o3) i
(%i4) bit_not(3);
(%o4) - 4
(%i5) bit_not(100);
(%o5) - 101
(%i6) bit_not(-101);
(%o6) 100 typedef struct {
unsigned8 b7 :1; /* bit7 */
unsigned8 b6 :1; /* bit6 */
unsigned8 b5 :1; /* bit5 */
unsigned8 b4 :1; /* bit4 */
unsigned8 b3 :1; /* bit3 */
unsigned8 b2 :1; /* bit2 */
unsigned8 b1 :1; /* bit1 */
unsigned8 b0 :1; /* bit0 */
} BYTE_FIELD; >>517
だから、できると思うんならやってみろよ
うまくいけば特許権で儲かるかも知れんぞ >>521
謎だな。
ブールの配列ならint bool やら char boolやらした時点で確保されるメモリをそのまま使って、and or xorあたりでビット操作してshiftで走査したらいいじゃん、ってのが爺の言い分。
どのビットを何に使ってるかってのはコメントに書いておいたり仕様書に書いといたりカンペ回したり。
メモリ確保もロードも最小単位があるんだから、単独1ビットのブール変数ってのは無理だろ。
あ、組込み用のマイコンは知らないけど。 >>525
君がマウントを取りたいだけのサルということが良くわかった。
ま、頑張れ。 >>527
体験も知識もないやつが妄想を垂れ流すと突っ込まれるという当たり前のことが起きただけだ
今後は身の丈に合った発言を心がけるんだな >>505
結局レジスタに入れずにってのは有りうるの?喧嘩せずに冷静に結論を出してくれると嬉しい。気になる。 intが64ビットの環境で32ビットの変数を扱いたいので、
とりあえず(私の環境で) typedef long INT32;とか定義してるんですが、
longを使うのが普通でしょうか?
環境によって違うらしいとは知っているのですが、
typedefに出来るだけ無難な型を使っときたいという意図です。 >>534
stdint.hかinttypes.hをインクルードしてint32_tを使うのはダメなの? レジスタに入れずに直接メモリ上のビット操作はないよ。
そりゃやろうと思えばメモリセルの制御単位を1ビットにしてデータバスを1ビット、アドレスバスのアドレス単位も1ビットにでもすれば1バスサイクルでのビットアクセスができるだろうけど、あまりにも非効率なのでやらないだろう。
そんな汎用CPUはどこにもないと断言しても良いレベル。 >>535
組み込み系をやっていて、
ライセンスにかかわらず、ヘッダを含む外部ライブラリを一切使ってはいけないルールになってます。 こんなデタラメまじりの掲示板で
聞いた所で所詮オカルト
はっきりさせたきゃ
sdramの転送どうなってるか
自分で読めばいい それなら提供されている範囲で使える物を使うしかない
32ビットもあえて使わなくても良いように思うけど
何かこだわりがあるのかな? >>538 コンパイラ付属のヘッダファイルも存在しないのかな。
その場合は、コンパイラの取説でも見て、32bitになる整数を選んで
typedef すれば良いかと。
どのみち移植する際には、その辺も含めて丸ごと再検討ってことになるだろうし。 >>534
intが64bitでlongが32bit?
いくら何でもC言語としてあり得ないだろ
妄想で話を盛っているのか? >>542
クロスだろ。ターゲットのlongが32なんでしょ。 int型が64ビットの環境で、longという型が32ビットなのは引っかけだな。
あとで見た他人に恨まれるぞ。 >>537
話の流れとしてそこはビット単位の話ではなくなっている。 職場でクロス開発やってるけど、家では開発環境無くてVSかなんかで勉強してると妄想してた。 >>548
昼夜を問わず沢山のマウントありがとうございます。 >>536
すげー昔の話だがメモリー側で論理演算できるようにして1アクセスでビット単位操作を可能にした特許があったな
元々はグラフィック用で図形の重なりの演算をメモリー側でやるようにしたものだったけど
特開昭61-264453 >>551
前世紀の話だが液晶モニタ側にメモリ機能を有して
PCの電源落としても液晶モニタ側に必要な情報が画像として記録されてるから
再起動後すぐにデータを使えるようになる、なんてニュースが真面目に流れてたっけ たとえばFPGAだとビット操作向けのコンピュータ作れたりするんですか? >>553
外付けのSRAMやSDRAMではI/Fが決まってるので困難だけど、FPGA内で閉じて作るなら可能なんじゃないかしら。 大昔のDRAMには必要なビットだけ書き換えできるライト・パー・ビットって機能を実装したものもあったな そういえばGRAM用にそういうRAMが何種類かあったね。
OpenGLとかで全画面書き換えが当たり前の今では役に立ちそうにないけど。
C言語とは関係ない話題ですまんかった。 MB-S1はそういう回路を搭載してグラフィックの処理がやたら速かった。 X68000のVRAMは変わった仕様だったみたいだね。 Cはコンパイラにより
型の変数の容量どころかポインターすら変わる
きれいに書くことなどできん!
Cの恐ろしいことは、標準っぽい関数が
リソース開放の事を考えてなかったりする所w 表面的だな
どっかで吹き込まれたことの受け売りはすぐにバレる >>559
>Cの恐ろしいことは、標準っぽい関数がリソース開放の事を考えてなかったりする所w
それはどの標準関数ですか?具体的に指摘できますか? >>563
標準関数ではなく、
標準っぽい関数なんだから
相手にするだけ無駄かと。 その昔、printfはメモリリークするとかぬかしてたアホがいた 小学生のプログラミングの授業が始まったせいで5chにも大量に小学生が湧いてるな
学校でプログラミングを教えるのは勘弁してほしいは >>564
いえいえ、標準っぽい、というのだから、標準関数に近いという主観的判断があるのでしょう
それはそれで私は純粋に好奇心が湧いたのです ぼくのかんがえたさいきょうの標準っぽい関数
atod
stringをdouble型に変換する。
標準っぽいが標準でない。
リソース開放を試みるものの、constに阻まれる。 標準的な関数で痛い目にあったといえばlocaltime()
コイツがスレッドセーフじゃないせいでひどい目にあったよ……
まあ返り値がポインタな時点で疑うべきだったが。 >>570
atod() にてリソース解放の必要はあるのでしょうか? stringは無視するとして、const char*をdoubleに変換する標準ライブラリ関数はatofまたはstrtod 超*2 初心者です。
#include<studio.h>
int main(void){
int a,b;
b=3*a+4;
a=2*b+3;
printf("a=%d\n",a);
printf("b=%d",b);
return 0;
}
とプログラムして、
a=-2
b=-2
という出力を期待したんですが、
a=3
b=0
と出力されてしまいました。
何が間違っているのでしょうか??
長文スマソ int a,b;
b=3*a+4;
b = 3 * <未初期化の a は不定の値> + 4;
= <不定の値>
なにになるかはわっからんちん >>575-576
まずプログラムとして完全に間違っているのは、
b=3*a+4; の評価時点で a は初期化されていない。
初期化されていない自動変数の中身は未規定で、
何が入っているかわからない。
そして第二の間違いとして、
C は二次方程式を解いたりしない。
b=3*a+4; は a の中身に 3 を書けて 4 を足すという処理をしたものを b に入れ
その次に a=2*b+3; の処理、すなわち b に 2 を書けて 3 を足したものを a に入れる。
そんだけ。
これはもう、質問以前の話で、完全に C のごくごく初歩をわかってないので、
普通に入門書を最初から読んで。 "1文字=1数字"の式をもたない連立方程式は解けないということですか? あああ 数学的に式を記述したら解を求めてくれる mathematica 的なものを考えてたのか
残念C言語はそこまで親切じゃない むしろmathematicaだと解いてくれるの?すげぇ。 >>585
数値解求めるのもあるし
可能なら解析解も出せる(テイラー展開されてきもい出力になるケースもままあるが・・・) 代入を=にしてしまったのが不味いよな
やっぱ代入は矢印にするべきだわ それは <-- こうしよう
まぁすごく今更だけどなw <- 比較演算子と単項マイナス
<-- 比較演算子と前置デクリメント 式 + 二項演算子 + 単項前置演算子 + 式; OK
式 + 二項演算子 + 式 + 二項演算子 + 式; OK
式 + 二項演算子 + 二項演算子 + 式; NG そろそろGUIでフロチャート化や命令/関数アイコンの並び替えで作れる言語を!!
・・・そんなに利便性はあがらんか。 はるかの昔からそういったGUIプログラミングツールやCASEツールがあったけど、どれも決定版にはなってないよね。
唯一、車業界でMatlab+Simulinkと自動コードが標準的に使われてるけど、あれはモデル化して徹底的にシミュレーションする目的がメインなのでちょっと汎用的には使いにくい。
実際吐き出されたコードはロジックに問題はなくてもソフト技術者から見ると目も当てられないぐらい悲惨なコードだし。 多分要件定義を渡すとプログラムを作成してくれるAIを作る方が早いだろう
誰が作るかは知らないが >>604
そんなんすでにいくらでもあるだろ
つScratch >>610
そういうややこしい話はAIに考えさせるべき なんでこんなゲシュタルト崩壊みたいなスレになってるの?
みんな疲れてるの? Cでなくていいならnode-redなんかはいい感じにグラフィカルだと思うわ。 AI 「めんどくせー、報酬出して人間に考えさせたろ」 マイクロソフトのビジ男ってフローチャートからコード吐いてくれる機能あったよね、まだ生きてるのかしら フローチャートではなくてUMLのクラス図からC++のコードを自動生成する機能だったと思う
その類の機能は廃止されたよ >>618
そうか、亡くなってたのか。一回触って無言で閉じた事しか覚えてないけど、根は優しい奴だった。 Executable UMLは見事に死んだな。あれはさすがに無茶だろうと思った。 >>604
ほぼゲーム制作専用だけど、Unreal Engine4のブループリントが
完成度高いような >608
ゲーム作れるようになりたいって言ってコンシューマ版PRGツクール買わされた気分。 返り値がポインタの関数って
int *func() {...}
↑みたいに関数名にアスタリスクが付いてるのが違和感あるんだけど何か理由あるの?
意味を考えればint* func()もしくはint * func()にするべきなんじゃないのかな 複数のポインタ変数を宣言するとき
int *a, *b →OK
int* a, b →NG
ということがあるので前者の記述にする。
関数についてもそれに揃えてるだけ。
だと思ってるんだが違うかもしれん。 そんな書き方する人はいないだろうけど(というかできたっけ?)、極端な話、
int* func1(), func2();
という宣言だとダメだしね。 昔、*をどこに付けるべきか議論あったね。
「int *」も型なのでスペース空けるのはおかしい、「int*」と書くべきだと主張してる人も結構いて、今もまれによく見かける。
統一してれば良いんじゃね? >>624
int *a, *b は *aと書くと整数。 int*ならtypedefやらtypeofやらつかえと思うわ >>623
それC言語の初期はそっちの方が普通だったんたよ。 ああ、わかった。*aで正数になるから宣言するときに int *aって宣言すると自然だよってことか。なるほど。 でもそれなら
int *a; で*aがintになるから自然だけど
int* a; でaがint*になるから自然さはこっちでも同じだな。なんか俺勘違いしてる?
連投スンマソン そう書いてbがint*にならないのが悪い
cの最初の設計が悪い 50年前のクルマに「性能が悪い」と怒っても意味が無い だから、それしたいならtypedef使えって。
typedef int *(*f)(int *, void ** );
f a, b;
Cの型の表現方法はそこそこ合理的だと思うよ。 int* なんて型はCにはないけど。
ついでに、int*もトークン分割時点で int * ってスペース入るんだけどな。
int *pも int * pってなる。 規格的には別にスペース入れろなんて書いてない様な気はするが…
int*xは良いんだっけ? >>638
tokenの区切りで勝手に解釈してくれるから問題ないよ。
スペースをいれる必要があるのは、入れないと前のtokenと連結して解釈されてしまうような箇所だね。 >>632
勘違いといえば、
int* が型だと思ってるところかな。
変数の前に付いた*は演算子。逆参照演算子って名前だったか。 変数宣言のときと式の評価のときとでは、働きが間逆になる、ときいていますが、私も馬鹿になったので、そういわれていることをそう理解できなくなりました… 宣言は演算子とは別じゃなかったっけ?
typedefもできるし規格はpointer typeって書いてるからポインタ型って認識も間違いじゃないと思ってたけど違うんかな
確かに一行での複数宣言だと確かにおかしなことにはなるけども ポインタ宣言子というやつでデリファレンス演算子とは別。 演算子でしょ?評価順があるじゃん。
関数の()とか配列の[]も同じで、もちろんCだと宣言にも使うことになるけど。 >>640
意味的には int* は型。
でも文法的には * は変数名と優先的に結合するので、
変なことになってんだよ……。
C++ だと設計者 (stroustrup) が * を型名に寄せる書き方をしてるので、
近頃はそれが C にも流入してる感じ。 C11の6.7.6.1にpointer declaratorって書いてあるから、宣言時の*はポインタ宣言子で間違いなさそう >>647
ぜんぜん変じゃないでしょ。
変数と型が直接結びついてるんだから、評価順が逆になるのは当たり前。 *から始まってる宣言子をポインタ宣言子って言うんじゃなかった?
宣言での*自体の名前もポインタ宣言子って言うのかな。修飾子? あれ、そうかも。シンボルまで含んで宣言子かな、すまん。 >>649
カンマより優先度を高くする必要はないだろう。 >>646
型の宣言の構文が入れ子になっていて結合順はあるが、評価順があるわけではない。
見た目が似ているだけで、型の宣言と式の評価はまったく別の概念だよ。 int* 型はない。型と見なしたら混乱する、俺は。
int *p;は、記号表現としての*pという表現がintという意味。*pで1つのint変数。
だから当然sizeof(int)のメモリも確保される。
int*が型ならアドレス変数のサイズだけ確保され、intオブジェクト分のメモリは確保されないはず。
int a b c *d;などと、まとめて書けるように作ってある
ここで、
*のない変数はアドレスを参照するために&が必要
*がある変数は*を外すだけでいい
&がメモリ上のオブジェクト(変数とか関数)のアドレスを参照するのに対して、アドレスからオブジェクトにアクセスするから*は逆参照演算子と呼ばれる。単項演算子。 >>654
いやいや、何を勘違いしてるのか知らないけどint *p;はポインタサイズのみ確保されるんだけど。
結果intとアドレスサイズが一致するとしてもsizeof(int)と同一視すべきではないんでは? >>654
int *p;の宣言じゃsizeof(int)は確保されないでしょ
環境によってはint *p;したあと*p = 0;したらセグフォか何かなると思うが
今一応clangで確認したらTrapしたし 教えるスレでデタラメ言ってはいかんな
釣りのつもりか? >>654
お前が混乱しようがint*は型だ。
キャストもtypedefもsizeofもできる。
お前のオレオレ定義はどうでもいいから、標準的な用語で会話できないならいちいち書き込まないでくれ。初心者の理解を妨げる害悪でしかない。 結合順って左右どっちからかという話だろ?
うまいこと、左に型で右に変数という形では宣言できないという点には関わってくるね。
Cではtypedefでそれがカバーできるので使えばいい。
単にstructの省略のためとかだと微妙だけど。 自分以下のように「*」をくっつけて書いてた。
int* p;
「int変数のアドレスを格納する型」
と理解してたので。 intのポインタだから int* と書くのが直感的だよね
int* a, b, c; と書いた時に全部ポインタで宣言できれば良かった
俺は宣言でカンマは使わないことにしてる 規約とかで決まってなきゃ思想の問題だし良いんじゃない?
Cでは意味論的には(ポインタ型って書いてあるし)int* pが近くて統語論的には(複数宣言で違和感がないから)int *pが近いっていうイメージ
規格内の例はint *p記法で統一されてるからこっちがCではスタンダードっぽいけど >>662
ポインタでポインタが指している先頭アドレスから始まる領域をint型として扱うだから、*intにすべきだった。 C++ なら std::add_pointer を使うなどという方法もとれるんだが、
C でどうにかする上手いトリックってないもんかね? >>662
関数ポインタはどうすんの?
左に型書いて右に変数というルールで統一するとなると。 int* p[10]; // intのポインタの配列
int (*p)[10]; // intの配列のポインタ >>640
自らの名誉のために書いておくがint*を型だと思ってるわけではないぞ。ただint*で意味をなしてはいるだろ。 int*は型だぞ
printf("%d", sizeof(int*)); //pass int* は型名。 C99 なら 6.7.6 で定義がある。
変数の宣言の文脈ではそれが型指定子と宣言子に分断されるのが、
なんか変な感じがするよなぁという話。 >>662
そういうのは typedef で型名作ってしまうしかないな。 >>671、>>672
自らの名誉のために言っておくが、型名な気もするなとも思っていたぞ。 >>674
お前の名誉のために言っておくが、お前の名誉なぞ誰も気にしてないから安心していいぞ int* が型って言うのはどこに書いてありますか?
K&C2版とc99の仕様書見てきたけど、どうしても見つけられないのです。
どこで調べるとint*型や例えばchar*型等の記述を見る事が出来るのでしょうか。 >>677
お前さんの定義する「型」ってのは具体的にどういう定義なんだ? 特定の型のポインタは書いてないけど
pointer typeって形で載ってるはず
C11の6.2.5.20とか 全ての型に付けることが出来て
あたかもメソッド++があるかのように振る舞うオブジェクトの様なものだから混乱する
&や*もやはり何かのメソッドの演算子での表現と見做すと理解が捗る
つまりポインタまわりだけ大勢の予想に反してオブジェクト指向になってるから混乱する >>677
C99 で 6.7.6 の項目名がそのまま "Type names" やし、
索引もあるし、さらに言えばちょっと前 (>>672) に私が書いてもいるのに、
どこまで節穴なんや……。
型指定子 int と抽象宣言子の * を合わせてひとつの型名ということになる。 >>678
c99 6.7.2
void char short int long float double signed unsigned _Bool _Complex _Imaginary
構造体共用体指定子 列挙型指定子 型定義名
>>679 >>680の言うように、ポインタ型はあります。仕様書を見ても、int* でもfloat*でもいいんですけど、それぞれint型へのポインタ型とかfloatへのポインタ型といった説明しか読み取れませんでした。読解力不足でしょうか。
私はint型を指すポインタ、floatを指すポインタなどと言うように、例えば
int* pであれば、ポインタ型pがあり、それはint型を指す
、と言うように独立した物だと理解していました。
どうしてもint*型と言うのがわかりません。 >>683
お前さんのいう型の定義では
「signed long long」
は型なのか?型の集合なのか? >>677
ここだ
ISO/IEC 9899:2011
6.7.7 Type names
3 EXAMPLE The constructions
(a) int
(b) int *
(c) int *[3]
(d) int (*)[3]
(e) int (*)[*]
(f) int *()
(g) int (*)(void)
(h) int (*const [])(unsigned int, ...) C言語を作ったときにあとから型指定のポインタ変数を付け加えたんだろうな。 >>686
ポインタがなかったのばBだ
最初期のCにもポインタはあった voidはなかったんだよな。
どうでもいいけどcdeclはちょっとした型の勉強にはいいよ。 685を見ると、「型名を左に書くのが自然」みたいな主張がまったく間違ってることがわかるね。 ポインタ型は派生型(deprived types)の一種で、派生型は他に配列型とか構造体型とかがある(6.2.5.20)
例えば、struct MyStructure {int num;};とかやったとして、struct MyStructureは規格に書いてないから型じゃないって言ってる状況に近いように見えるんだけども >>691
「全ての*が演算子である」
という主張は間違えている。
ということは理解できてる? 演算子ですよ。いや、文字列の中はどうなんだとか言われると困るけど。
xor的な思考しかできないタイプ? 685 の文中に出てくる * を演算子とみなすのは嫌な感じ 宣言の中の*は演算子ではない
宣言子の構成要素の中のポインタに含まれる記号だ
演算子の*はポインタを実体にする作用を持つが
宣言の中の*は客体をポインタにする作用を持つ
おおむね逆の作用となっている >>687
ポインタが指しているところの型を明示しようとしたのは明らかにあとだよね。 そういえば*のオペランドがオブジェクト指してなかったら未定義動作なんだよな
宣言の*が演算子だったらint *p;だけで未定義動作踏んでそう >>693
そこから知らない訳か。
int a=3 ;
の =が代入演算子では無いことは理解できてる? >>699
代入という言い方をしている時点でわかってないと思うよ。意味が逆になっている。
変数ではなく定数だったら、わからなくもない。
右辺、左辺という言い方も嫌い。 >>701
お前の好き嫌いの話だったのか。
規格用語くらい理解して発言しろよ。。。 「俺はこう思う」と「規格にこう書いてある」はきっちり分けて欲しいね。 英語はsubstituteで意味が広いのに、日本語だとすべて「代入」に翻訳してしまったのか。 >>684
型指定子の並び
>>685
それは元からint*型がある、と言うよりもint* p;だったらint*と言う型名になるって話ですよね。
>>690
型じゃない、ではなくて、int*型と言う型はintに*をつけないとありませんよね?typedefを使わなくても作れますけど、int*型というのは元からはありませんよね?自分で作った型名なのにc言語にint*型がある、と言うのは変だと思いませんか? >>705
X 3010:2003 (ISO/IEC 9899:1999)
6.2.5 型
型char,符号付き整数型,符号無し整数型及び浮動小数点型を総称して基本型(basic type)と呼ぶ。
派生型(derived type)は,オブジェクト型,関数型及び不完全型から幾つでも構成することができる。
派生型の種類は,次のとおりとする。
− 配列型
− 構造体型
− 共用体型
− 関数型
− ポインタ型
派生型を構成するこれらの方法は,再帰的に適用できる。 >>706
派生型を構成できる、と言うことは、int*はコード書く人が自分でint*と言う派生型を構成したんですよね?
構成できることを以ってC言語にint*型がある、定義されていると言うのは変だと思いませんか? とりあえず、今のところ(>>623 以降)議論になってるのは
「int* は型か、型ではない(int型に*を作用させた何か)か」
「ポインタ変数を宣言する際の * は演算子か演算子ではない何かか」
→ 「変数宣言の * が演算子でないなら何と呼ぶのか」
…あたりかな。
個人的には >>699 の「int a = 3; の = は代入演算子か違うものか」も
ちょいと気になる。
変数定義と代入 int a; a = 3; の省略表記に過ぎないのか、
char s[4] = "yes"; みたいな初期化時の特例になるのか。 変かどうかの主観的な問題ではなく「派生型を定義できる」と決まってるなら、客観的に派生型もやっぱり型だろ。
それを変だと思うならここではなく然るべきワーキンググループに意見すべき。 >>706
それを言い出すと派生型は全部その類に含まれる(そもそも構造体型へのポインタ型とか言い出すと規格に書ける訳もないし)
元々int *って型は存在しないって言い出した流れ(たぶん>>640)はint *も型だって話(>>626)の中にしかなかったと思うからそもそも話がだいぶズレたんだろうな
今の流れはざっと見返した限り>>708がまとめてくれた通りだと思う >>708
>個人的には>>699 の「int a = 3; の = は代入演算子か違うものか」
宣言での=は、初期化宣言子内の区切り子
>「int* は型か、型ではない(int型に*を作用させた何か)か」
>「ポインタ変数を宣言する際の * は演算子か演算子ではない何かか」
>「変数宣言の * が演算子でないなら何と呼ぶのか」
宣言での*は演算子ではなく、ポインタ宣言子の区切り子
6.7.5.1
ポインタ宣言子
意味規則
宣言
T D1
において,D1 が形式
* 型修飾子並びopt D
をもつ場合,次のとおりとする。
宣言
T D の ident
に対して指定される型が Tの派生宣言子型並び
であれば, T D1の ident に対して指定される型は
Tへの型修飾子並びをもつポインタの派生宣言子型並びとする。 >>707
お前さんが型と呼びたいものはC言語では基本型であって、C言語における型の一部でしかない。
>>707が挙げてくれている通り、基本型と、再帰的に定義される派生型を合わせてすべて型と見なされる。
この定義によって、どんな型をどんな順序で組み合わせようと、ポインタが何段あろうと、どんな名前をつけられようと、定義に再帰的に合致させられるそれらすべてを型と見なせるとあらかじめ定義されている。 >>713
宣言時の型の話です、元々
int*p;
のint*は型かどうかと言う話です。宣言した結果pの型がint*型に・・
あ、int*は型指定子か、と言えばよかったのかな? 逆に「int* 」が型じゃないって考えの人は
int* a
のaの型は何って聞かれたときにどう答えるのか知りたい。 >>712
「初期化宣言子内の区切り子」っていう言葉がヒントになった。ありがとう。
n1570.pdf (>>1 のリンク参照) 6.7.9 に載ってるね。
英語だから、すらすら読めるわけじゃないけど。
スカラの算術型に関しては「{} で囲んだ初期値を入れられる」
(構造体の初期化と同じ書き方ができる)ってのが代入演算子と違うところかな。
int a = {3}; // 「定義と同時の初期化」では許される
int b;
b = {4}; // エラー: 通常の代入演算子では値を {} で囲めない
だからどうした、って話かも知れないけど、
動作の違いが確かに存在するってのは気分的にすっきりするわ。 >>715
ごめんなさい、int*は型指定子かどうかと言うべきでした。
int*a;
aはなにか、と聞かれるとintへのポインタと答えます。
aの型はなにか、と聞かれるとint*型と答えます。
宣言でのint*の文字の並びは型か、と聞かれると宣言でのint*と言う文字の並びは型指定子intと、ポインタ宣言子の並びであって、結果int*型となるがint*型の指定子ではない、と答えます。 みなさんごめんなさい、私が型指定子とはっきり言わなかったせいで混乱を招いてしまいました。
あ、その前に、
int*p;
のint*は型指定子じゃありませんよね?私の理解合っていますか? オブジェクトにもちろん型はあるけど、Cで「型指定子」なんてもんを明確化することに大した意味があるとは思えんね typeof使うと左と右にはっきり分けて書けるので、好きな人は好きだろう。
typeof(int (*)(void *, char []) hogeobj; >>707
713も言っているように、おまえさん用語の意味を誤解してるんだよ
型は基本型の他に派生型も含まれる用語だ
それから定義の意味もおまえさんおかしいぞ
定義は宣言のうち重複できないものをいう
キーワードは定義できない >>721
はい、気をつけます。
>>719
>>1のc99 6.7の構文規則でいうと
宣言:
宣言指定子列 初期化宣言子並び opt;
宣言指定子列:
記憶域クラス指定子 宣言指定子列 opt
型指定子 宣言指定子列 opt
型修飾子 宣言指定子列 opt
関数指定子 宣言指定子列 opt
初期化宣言子並び:
初期化宣言子
初期化宣言子並び , 初期化宣言子
初期化宣言子:
宣言子
宣言子 = 初期化子
ですから、
int *a,b,c,*d;
という書き方は
宣言指定子列と初期化宣言子並びなのですけど
int*が型指定子だとすると、
宣言指定子列の型指定子がint*、
以降の a,b,c,*d;は初期化宣言子ですから、a,b,c,*dのどれもがint*型になると思うのです。
int*は型指定子ではないから
aはint*,bはint,cはint,dはint*になりますよね。
型指定子かどうかは重要じゃありませんか? >>717
ありがとう。話のレベルが高くて自分にはもはや質問しかできないが… for文とif文を使って整数nを入力して、2つの1以上10以下の整数x,y(x>=y)の自乗の和がn(n=x^2+y^2)になるx,yとなる組み合わせを求める(n=45のときx=6,y=3みたいな )C言語のプログラムを作りたいんですが、関数って使いますか? >>725
分かりました、ありがとうございます。
>>726
どのスレのことか分からないのでそのスレの名前を教えて頂けるとありがたいです。 >>727
「宿題」で検索するくらいのことはしろよ…… >>728
検索した上で分からなかったので聞いています 宿題スレって、回答の丸投げだろう
質問に応えるスレではない 宿題スレ見てきたけど過疎って誰も居なさそうだったけど・・・ 依頼があればやってくれるだろう
それ以外に話題がないスレだし 「宿題」はこの辺かのう。
設立も古いし、何ヶ月も投稿ないから沈んでるのかな。
通常のインターフェースで一覧を見ないんで正確には分からんが。
C/C++の宿題片付けます 170代目
http://mevius.2ch.net/test/read.cgi/tech/1456911928/
C/C++の宿題片付けます 170代目
http://mevius.2ch.net/test/read.cgi/tech/1456647534/
こんなの↓も見つけたけど、これは「宿題」では見つからないタイトルだね。
【C】至急課題のプログラム教えて【アマギフ】
http://mevius.2ch.net/test/read.cgi/tech/1551308087/ >>724
その目的を直接的に達成する標準関数はない
自乗を求める標準関数ならpowというのがあるが
整数を前提とするその問題には適さない
処理の一部を、おまえさんが関数にする可能性ならある
おまえさん、プログラムを作ってくれなんて言ってないよな
変な妄想してるバカは無視していいぞ >>729
何でわからないんだよ。どういう環境で使ってるんだ? 明日テストでその過去問にこのような問題が出て、関数が必要なら諦めようかなと思って質問しました。
スレチだったならすみません。答えてくださってありがとうございました。 >>736
スマホで専ブラ使ってます。予測はつきましたが、過疎っていたのでそのスレで合っているのか疑心暗鬼でした。今はどのスレのことか分かっています。 >>724
これはifとforの練習問題以外の何者でもなさそうだ。便利な関数使って解いたりしたら先生が泣いちゃいそうw >>739
ありがとうございます!このような問題です。
for文とif文を使って整数nを入力して、2つの1以上10以下の整数x,y(x>=y)の自乗の和がn(n=x^2+y^2)になるx,yとなる組み合わせを求める(実行例:n=45のときx=6,y=3)C言語のプログラムを作成せよ。そのような組み合わせがない時は、nothingと表示せよ。 候補絞り込みの最短手順を求めるような問題でも無さそうだし力技の総当たり探索で良いんじゃないの? >>744
宿題スレに書いてここに書いた場所を報告すれば、問題を解くプログラムを私が書きましょう >>744
この程度のプラグラムを自力で解こうとする気が無いなら素直に落第しておけ いいんじゃないの?恐らく数学的になんとかしようとするとコンピュータ使わずに解が出て終わってしまうだろうし。 もう取り繕う理由ないからタメ語で話すけど
簡単な問題に関してめっちゃレスしてしまってすまんな
明日のテスト頑張ってくるわ
説明してくれた人皆ありがとノシ >>752
手を煩わせたんだから 良かれ悪かれちゃんと結果報告には来いよな
幸運を祈ってやる >>753
ありがとう
さっきテスト終わったけど微妙だった
合格の可能性ワンチャンあるけど、期待はしない方がいい
多分来週に結果が分かると思う、遅くても今月以内
結果が分かった時に報告する >>754
テストに落ちたらどうなってしまうんや…… 課題を出されましたが、全くわかりません
このプログラムを作っていただけませんか?
スレ違いなら誘導をお願い致します
@キーボードから任意の文字を入力します。
A先頭が数値の場合
・入力を数値に変換して、メモリーに格納します。
・格納されている全ての数値を降順(大きい方が先頭)に並び替えます。
B先頭が数値でなければ、現在入力されている数値を並び順の逆順で全て表示する。
尚、数値は100個以上格納できるものとします。 >>756 宿題スレッドへのリンクは >>733 な。今のところまだ有効。
携帯端末(小さい画面)のせいか、スレッドを遡って読むのが難しい人の
質問が増えたようだけど、そういう閲覧環境だと、質問に対する回答の
ソースリストを読むのも一苦労な気がするなぁ。 >>757>>758
誘導ありがとうございます
上のスレの方に行きます >>758
ソースを何らかの方法で PNG なり JPEG なり GIF なり Cはじめましたよろしくです。これみてやってください
FILE *fp;
char *p;
char fname[100];
char str[500];
gets(fname);
fp = fopen(fname, "r");
p = fgets(str, 500, fp);
while(p != NULL){
printf("%s", str);
p = fgets(str, 500, fp);
}
とやって難なくファイル表示してくれましたが、これpはしょれんじゃね?と思ってこうしてみましたの
gets(fname);
fp = fopen(fname, "r");
p = fgets(str, 500, fp); とりあえず放置
while(str != NULL){ p→strに書き換え
printf("%s", str);
//p = fgets(str, 500, fp); コメ停止
fgets(str, 500, fp); こうしてみた
}
すると
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・っと無限に続いて >>761-762
str が NULL になることは無いので。
配列として確保した str の「場所」は中身が何であろうと同じ場所にある。 >>763
もすこしだけおしえてください
fgetがfpに指定したというか登録したファイルから指定数読み込んで、それをpに渡して…
このときに文字終端ならpにNULLも渡ってそれでwhileの条件に合致して止まると思いまして ←ここまであってますか?
なら、pに渡さんでもfgetsが読みに行ったときにもう読む行ないならNULLも引っさげて帰ってくるからstrにNULLがはいってて
じゃーああいうふうに掛けばpいらねんじゃね?と思ったんですがなぜこれだとNULLはいってないんでしょ printf("%s", str);
memset(str, 0, sizeof(str));←これ入れてみ
fgets(str, 500, fp);
どうしてかは、自分で考える >>764
str が「どこにあるか」と「何が入っているか」は別物。
NULL と比較するのは「どこにあるか」であって、中身とは関係ない。
何度ループしても str の場所は同じなんだよ。 配列名strは先頭要素のアドレス&str[0]と同じ
strの評価結果は常に同じアドレスを返す
配列が正常に確保されている限りNULLになることは無い >>765
>>766
うぉあー 小一時間なやんできますありがとうございました! >>767
NULLがなにかよくわかってないことがよくわかりましたw いってきます >>764
fgets()は成功したら配列の場所を返す(つまりp == str)けど
失敗した場合はNULLを返す(つまりp == NULL)
ここで問題なのは他の人が言ってる通り「引数にとった配列の場所は変わってない」こと
char str[500];
っていうのは(今回はファイルから文字を読み込むために)char型のデータ領域を500個確保するってことで、
わざわざ取った場所を変更したり勝手に消したりはしない
対してNULLはまぁ何もない場所のアドレスって考えでとりあえずはいいと思う
だから、strの領域の(内容は変わってるかもしれないけど)場所はfgets()の結果がNULLでも確保してあるだけだから変わらない
最初の(動いた方の)プログラムで、fgets()した後に
printf("p=%p, str=%p\n", p, str);
とかやってアドレス表示させて途中と最後比べてみたら感覚的に分かるかも fgets の戻りは ポインタである必要は無く、int (bool) でいいと思うんだ
printf("%p\n", fgets()) のように直接重ねても、ファイルエンドでぬるぽ踏むわけだし 暗黙の型変換で配列がポインタになるってのが諸悪の根源なんだよな。
まあそれでだいぶん書くのが楽という面もあるんだけど、
この手の思い違いが連発するのはやっぱりどこか良くない設計だったのかもなと
思わないでもない。 配列名や関数名はアドレスを指しているというだけであって暗黙の型変換とは無関係 >>775
配列名は配列型を指すし、関数名は関数型。
それがアドレス (ポインタ) になるのは暗黙の型変換による。 >>777
int[10] が int* 型に型変換されたり、 void(void) が void(*)(void) になったりするという暗黙の型変換の結果だね。 >>778
配列Array[]の型はint[]型であるけど、配列名Arrayの型はint*型(値は&Array[0])
関数Func()の型はvoid(*)(void)ではあるけど、関数名Funcの型はvoid*型
暗黙の型変換など関係なくポインタに代入出来る 配列と配列名を別物としているようだけど、それなら配列と配列名を暗黙変換しているわけだろう。 配列Array[]と配列名Arrayは別のオブジェクト
配列名Arrayは配列の先頭要素のアドレス&Array[0]と同一オブジェクトの糖衣構文 >>781
それは明らかに間違った理解。
これ以上の説明はしないので仕様を読んで。 sizeof の時に区別していない/区別できないのなら 糖衣構文でも納得できるんだがね T型の配列は一部の例外を除き「配列の先頭の要素を指すT型へのポインタへと型変換される」(C11 6.3.2.1.3)
だから暗黙の型変換で間違いない >>774
左辺値変形が諸悪の根元だと?
じゃあ printf(&"Hello world"[0]); などと書かされるのが
おまえさんの望みなのか >>786
繰返しになるけど、暗黙の型変換で書くのが楽になってるのは承知してるんだってば。
ただ、初心者が (時にはベテランでも) 変な理解をしがちな理由はこれだろうな
っていう意味での根源は暗黙の型変換にあるっしょ。 おじゃまします
printf("[%s][%d][%p]\n", str, str, &str);
こう表示させたとき%sと%pに出る値は意味わかるのですが(文字列とアドレス)
はわかるのですが%dに出る数字の羅列はなにになるんですか >>788
str は char の配列ということでいい?
だとするとアドレス。
str が配列であれば str と &str はアドレス値として見れば同じになるはず。
型は違うけど。
(整数への変換で何が起こるかは言語仕様でははっきりした規定は無い
ので、表現が変わってしまうことな無いとは言えない。) >>789
なるほど!
値が違ったのでアドレスじゃないのかと思いましたの
%dと%pではアドレスの表現が少し違うという解釈でよさげですね
いつもありがとうございます >>790
表示が違うのは %p は16進表示になってるとかじゃない? 単に%dだからアドレスの10進表記になると思ってだけど、はっきり決まってはなかったんだ。 >>787
そういう諸悪の根元なら左辺値変形ではなく
関数仮引数で空の角括弧を許していることだろうが まぁ、双方明示的に(個人の感想です)strとキャストすべきなんだろうな。 ポインタに対してprintf()で%d指定した時ってアドレスがちゃんと出るって保証されてたっけ? voidのポインタの便利さに気づきました
こんな私に何かアドバイスはありますか? 横質問で申し訳ない
NULL の実際の値
'\0' の実際の値
は実装依存ということで間違いない??? >>795
保証されていない。
というより、値がアドレスには違いないのだけど
その表現がどうなっているか未定義なので、
意味のある値なのかどうかはわからない。
(常識的にはデタラメな値ということもないだろうけど……)
整数とポインタの関係について確実に保証されているのは、
ポインタをポインタのサイズより大きい整数型に入れたなら、
元の型にキャストしなおすと変換前と等しいってことくらい。 >>800
実装として、ASCIIとEBICDIC以外で「これは認識してないとダメ」なものがあれば御教示くださいませんか? >>804
数字 ('0'〜'9') に対応する文字コードが連続する保証は有る。 '0' 〜 '9' で挟んで '0' で引き算するのは保障されてるので成立するけど
'a' 〜 'f' , 'A' 〜 'F' で挟んで - 'a' + 10 や - 'A' + 10 は保障外のコードになる と。 >>801
未定義じゃねえ処理系定義だ
未定義に該当するためには何らかの禁止を破らねばならない
禁止を破っていないのに決まっていない事項は未規定
未規定のうち文書化されるのが処理系定義だ
先輩方が変な言葉遣いをするから
若いのが勘違いするんだよ
気をつけな >>807
「処理系が必ず定義しなければならない」
「純粋に処理系依存なので、規格としては何も触れない」
この違いがイマイチ良く分からんのですが >>808
> 「処理系が必ず定義しなければならない」
それが処理系定義
たとえば sizeof(int) が返す値だ
> 「純粋に処理系依存なので、規格としては何も触れない」
これは未規定
たとえば printf("%d %d", getchar(), getchar()); の場合の左右の getchar の実行順序だ
わかってないんなら、ちゃんと規格票で確認しとけ >>795,801 ポインタの表現形式とは関係なく、未定義の動作になります。
https://www.jpcert.or.jp/sc-rules/c-fio47-c.html
実際の処理系での挙動を説明しようとするとポインタの表現形式で説明が付く
ことが多いだろうとは思います。 C11 7.21.6.1.9で「変換指定子が不正である場合の動作は未定義」ってあるね
処理系定義は%pの時のポインタの値の表現形式と間違えてないか >>810
規格で「何も」触れられていないのは未定義 (undefined) なのでは?
禁止を破るほか、規格に定めのないところの動作も含まれます。
規格で示される選択肢のうちのどれを処理系が選ぶかが定められておらず
処理系任せ(文書化も不要)なのが未規定 (unspecified) かと。 自分はc言語とc#(pcツール開発用途)使うけど、
c言語は仕様がコンパクトで、このスレのような議論があって面白いな。
c#はライブラリが充実してて凄く便利 >>813
嘘つくんじゃねえ
規格で触れられていない事項は未規定だ
未定義は「知るかボケてめーが悪いんだろうが」という意味の用語だ >>815
http://kikakurui.com/x3/X3010-2003-01.html#9
> この規格の制約以外の箇所で現れる…(し)なければならない又は…(し)てはならないという要求をプログラムが守っていない場合,その動作は未定義とする。
> この規格では,このほかに,用語 未定義の動作を使うことによるか又は動作の明示的な定義を与えないことによって未定義の動作を示すこともある。
> これらの三つの書き方は強調度において何ら変わりはなく,それらはすべて未定義の動作を規定する。 未定義な動作っていうのはプログラムが未定義な動作をするわけじゃなくて
コンパイラー製作者が決める動作が未定義だから好きなように動作を決めれるってことだぞ ID:LKFNCpsT0は言語仕様の前に日本語を勉強すべき
> 動作の明示的な定義を与えないことによって未定義の動作を示すこともある。 >>819
未定義とは何かの本文は「3.4.3 未定義の動作(undefined behavior)」だ
おまえが出してきているのを、この本文に対する補足説明と理解して読み直してみろ >>815
JIS X 3010:2003 3.4.3
未規定の動作(unspecified behavior) この規格が,二つ以上の可能性を提供し,個々の場合にどの可能性を選択するかに関して何ら要求を課さない動作。
C11 3.4.4
未規定動作
不特定の値の使用、あるいは当国際標準が提示する2つかそれ以上の可能性があり、いずれを選ぶかに関してそれ以上の要求を課さないその他の動作。
一応選択肢は与えてるように見えるな 「異常なプログラム」、「正しくないプログラム」、「正しくないデータ」
↑
このへんのキーワードが、なぜ「未定義の動作」という用語をわざわざ作っているのかの存在意義だ
他の「処理系定義の動作」や「未規定の動作」と見比べてみな
「未定義」だけ異質な点はただ1つ >>820
あほか、そこに「正しくないプログラム構成要素」って書いてあるだろ
規格には正しいプログラムの定義は書いてある
書いてないことは全て正しくないプログラムだよ
そもそも全ての未定義を定義できるわけないことぐらいはアホでもわかるだろw CとC++のことで少しはまったことがあったので質問です。
はまった部分を単純化して例を挙げます。
1.単純化した例
FuncC.c
#include <stdio.h>
void Func(void) { puts("FuncC"); }
FuncCpp.cpp
#include <stdio.h>
void Func(void) { puts("FuncCpp"); }
main.c
void Func(void);
int main(void) { Func(); return 0; }
上記3つのファイルを gcc *.c *.cpp でコンパイルリンクするとFuncC.cのFuncが呼ばれます。
main.cをmain.cppに名前を変更して同じことをするとFuncCpp.cppのFuncが呼ばれます。
clでも試しましたが同じ結果です。
2.はまったこと
拡張子によって呼ばれる関数が違うことに気づかず延々と的外れなことをやっていた。
3.知りたいこと
1の結果がなぜそうなるのかちゃんとは分かっていません。
なぜそうなるのか分かるサイト等あれば教えてもらえませんか? >>825
C++ は extern "C" {} のブロック内にC言語書かないと駄目なんじゃなかったっけ?
で、C++って同じ関数名で引数の違う関数作れるよね。だからCと見た目そっくりでも作られるコードが少し違うんじゃないの? Cは関数名がそのままシンボル名になるけど
C++のほうは関数名に引数の型情報が付加されたmanglingされたシンボル名となるので
リンカーでリンケージする際に区別してる
C++ から C 関数を呼ぶには 明示的に extern "C" と宣言されてないとその機構を突破できない
んじゃなかったかな >>825
c++ から c の関数を呼ぶのなら extern "C" おお。多分そうだ。
あとはもっと詳しい人に任せた。 途中で投げてしまった
私がはまったのは、win32api で、 ::RegisterClass() にて登録する WindowProc を extern "C" しなかったために、凄く困った記憶があります >>825
main()からcallされるasm用関数名が違うのでは
FuncC.c func() ---> funcC()
FuncCpp.cpp func() --> _Z4Funcv()
main.c call func() ---> call func()
main.cpp : call func() --> call _Z4Funcv() >>824
規格では正しくないプログラムをill-formedという
つまり正しくないプログラムも記載されているということだ
別に規格に限ったことではない
あるものが何であって何でないという境界を明確化するのは
ごく当たり前のものの書き方だ >>834
> あるものが何であって何でないという境界を明確化するのは
すでに明確だろ?
「正しいプログラムでないプログラム」は「正しくないプログラム」
正しいプログラムの定義は書いてあるから境界はすでに明確だよ
ill-formedとかの名前がどうのこうのは関係ない >>836
見苦しいのは>>834だろ
なんのためにill-formedとか言い出したんだ? w 「未定義」と「不定」については Phinloda さんの↓も分かりやすいね。
少々古いのが難だけど、内容は今でも正しいと思う。
初級C言語Q&A(7)
ttp://www.st.rim.or.jp/~phinloda/cqa/cqa7.html
ところで、「不定の動作」であるが「未定義ではない」、
しかも「不定であることの影響をユーザが見ることができる」
コードの例って何かあるだろうか。
ちょいと考えてみたけど、不定の影響を見るために何かすると
そのせいで未定義の領域に突入しちゃうんだよ。 >>838
どう見てもお前だろ
そもそも内容についてレスできないなら黙ってなよw >>839
少し前に誰かが書いてた関数の引数の評価順序とか >>840
推測してんなよ
第三者に聞く勇気がねえの見え見えだぜw >>839
foo(), bar()でなんか画面に出力するとかして
その例にある
a = foo() + bar();
でいいんじゃね? >>839には未定義は間違いと書いてあるけどそれは間違いで
未定義が間違いか間違いじゃないかを決めるのも未定義だから
未定義が間違いというのも間違いなんだよな >>845
そういう話をしたいならまずは君の言う「間違い」とやらをきちんと定義してくれ そもそも間違いを定義したくないから未定義にしたんだから定義できるわけないよな [翻訳]あなたがプログラミングに向いていない10のサイン - Qiita
https://qiita.com/hareku/items/4bfc48e23e83e0d300f3
1 好奇心の欠如
2 自律性と機知の欠如
3 問題に直面しても粘り強さが無い
4 問題解決に成功した気持ちはない
5 学習と理解に焦る
6 思考に飽きたり疲れたりする
7 自分のことを考えられない
8 堅く、狭く、そして無秩序な考え
9 複数の答えの間の「良い」と「悪い」の連続性に気付かず、「正しい」答えを望んでいる
10 細部に注意を払っていない >>847
何が間違いか、はっきり丁寧に説明してやっても
結局、自らの間違いを認める潔さを絶望的に欠いていて
まったく話にならない痛いやつであることを
ここの連中は目の当たりにしたばかりなんだが >>850は>>849の9番のサインがあるからログラミングにむいてないな 日本語を勉強すべきだの、あほかだのと、無礼な態度は若気の至りと
こちらは目を瞑って色々と箇条番号やらキーワードやら出してやってたが
そろそろ見限る頃だな >>841 >>843 (少々長くなった、読みにくくてすまぬ)
2つの関数があって、それらを「同時に」使う式で評価順が不定、
しかも未定義ではない、というのは分かるんだ。
int foo(void) {return 1;}
int bar(void) {return 2;}
func(foo(), bar()); // 関数引数の foo(), bar() どちらが先に呼ばれる?
int a = foo() + bar(); // 式中の foo(), bar() どちらが先に呼ばれる?
・どちらが先に呼ばれても同じ結果が得られる(後者では a の値は 3 になる)
・どちらが先に呼ばれたかをユーザが知ることは不可能
ところが、呼ばれた瞬間を捕まえてやろうと、関数に仕掛けを施すと…
int foo(void) {printf("foo()\n"); return 1;}
int bar(void) {printf("bar()\n"); return 2;}
「二つの副作用完了点の間に、オブジェクトの値を2回以上変更」という、
未定義の動作になっちゃうんだよ(俺はここで勘違いをしてるのだろうか?)。
printf() の内部状態もオブジェクトだろうからね。出力バッファとか。
・どちらが先に呼ばれるか表示される、おそらく結果は同じ(a == 3)だろう
・しかし、このプログラムには未定義の動作が含まれている
実際問題としては printf() を差し込んでも動作が変わらないように
うまくライブラリが作られてると思うけどね。
この投稿の趣旨は、「不定の動作であっても、結果を使うだけなら
プログラムとして正しい。しかし、不定の動作の内実を探ろうとすると、
その活動によって未定義動作を含んだプログラムになってしまう」っていう
不確定性原理みたいな何かが規格に仕込まれてるんじゃないか、という疑い。
(別に陰謀論をブチ上げようって意図はないので安心してくれ) >>857
そのコードが未定義かどうかは達成しようとしている目的による
たとえば、こういう場合
int x = 0;
int foo(void) { return ++x; }
int bar(void) { return ++x; }
int main(void)
{
int y = foo() - bar();
assert(y == -1);
}
fooとbarの実行順序に依存すると
実行順序は未規定だが、未規定に依存することは禁止で、
その禁止を破ったせいでmainの動作が未定義となる
これに対して、
int foo(void) {return 1;}
int bar(void) {return 2;}
int main(void)
{
int y = foo() - bar();
assert(y == -1);
}
この例では未規定の動作を含むが
その未規定がどう転んでも影響がない、
つまり依存していないので未定義の動作とはならない というわけで、printfで実行順序を見てやろうという目的なら
どちらが先でも、その目的が達成できるので未定義の動作ではない >>857
printf(..., printf(), printf()); こういうのとは違って
仕込んだ printf() の完了点はあくまで文末の; であって
printf() の内部状態変遷による未定義は踏まずに済むような気がする >>859
いや、 >>857 が言ってるのは、
printf の中のバッファなどの状態管理で同一の変数を破壊しないって保証ある?
ってことだと思うんだが。 毎度だけど話がズレるんだよな
>>810に対して>>813で「規格内で触れられてないのは未規定じゃなくて未定義じゃね?」って物言いがついた(未規定の動作は>>822)
で、>>816が「規格内で触れられてない場合も未定義」って言おうとしたんでしょ
>>823でなぜか未定義動作は異常(不正)なプログラム云々言い出したので話が分からなくなったんでは? 冷静な議論ならともかく、レスバ状態になると各々有利な立場になろうとしてだんだんと話が逸れてくんだよな。 「レスバ状態」というのは「レスバトル状態」の意味ということでよろしいか
20世紀の「レスって何」を思い出すが… >>857
2回以上変更しなきゃいいんなら
int i=0;
int a[2]={0,0};
int foo(void){i=1; return 0;}
int bar(void){a[i]=1; return 0;}
でいいんじゃね?
a[0]=0; a[1]=1; ならfoo() ⇒ bar()
a[0]=1; a[1]=0; ならbar() ⇒ foo()
の順 >>861
printfが持つ状態って具体的に何だ?
妄想しだすとisdigitみたいのまで状態を持つことを考慮せねばならんのだが >>857 は >>861 の意味で書いた(前半部分が余計だったのかも)。
最初の4行のコード foo(), bar() に printf() が仕込まれてない方は
「不定」だが「未定義ではない」。
ところが後半 printf() を仕込んだ方は >>858 の出してくれた最初の例、
foo() と bar() が同一のグローバル変数を変更する場合と
本質的に同一の、つまり未定義動作じゃないか、という話。
>>866 これは巧妙だし、思いつかなかった。
考えてみる(調べてみる)ので少々時間をくれ。 >>867
端末になにか表示されている、ファイルに文字が追記されている、というのが「状態」だよ。 >>868
ID:Jx7dUCON0はスルーでいいよ
レスの内容が頓珍漢すぎる >>869
つまりstdioさらにはデバドラがRENTかREUSかって問題ということで
じゃあ別プロセスでprintfを使われたら未定義動作ならHello worldすらill-formedって話だな >>866 の案も未定義な感じ。
EXP30-C. 副作用が発生する式の評価順序に依存しない
ttps://www.jpcert.or.jp/sc-rules/c-exp30-c.html
本文冒頭の引用部 (ISO/IEC 9899:2011 セクション 6.5 らしい) より再引用
> スカラオブジェクトへの副作用が、このオブジェクトへの別の副作用、
> または、このオブジェクトの値を使った演算、のいずれかに対して
> 順序が規定されていない場合、未定義の動作となる。
foo() の i=1; が「スカラオブジェクト i への副作用(代入)」
bar() の a[i]=1; が「このオブジェクト i の値を使った演算(配列の添字)」
に該当するかと。
ちなみに前述の Phinloda さんのページだと【未定義の例】にある
二つの副作用完了点の間に、オブジェクトの値を2回以上変更している場合、
又は変更した後で新しい値を得ること以外の目的でそのオブジェクトを
アクセスしている場合。
の部分と思われるが、ちょいと分かりにくいね。
…いや、自分で紹介しといて、その言い草はないだろ、と我ながら思うけど。 >>867 返答が前後して失礼。
printf() が持つ(かもしれない)状態ってのは、例えば
出力バッファ(fflush() で強制的に吐き出させるアレ)の
使用量を管理するカウンタかポインタか、そのあたりを考えてた。
もちろん stdout のバッファリングを禁止すれば、この場合に
printf() を安全に使えると考えてるわけでもないのだけど。
むしろ「不定の評価順序を調べるのに printf() を使えるなら、もっと簡単で
末端プログラマに読めるソースコードで実現できるんじゃないか」って感じ。
ライブラリ関数だと、中で実際に何をやってるか見えないからね。
>>849 の 3, 6 あたりに該当してきたので、本日はここまで。
…というか「バーナム効果」って奴じゃないの? >>872
> bar() の a[i]=1; が「このオブジェクト i の値を使った演算(配列の添字)」
> に該当するかと。
なるほど
よくよく考えたらそのリンク先の未規定の例を参考にして
int i=0;
int foo(void){i=1; return 0;}
int bar(void){i=2; return 0;}
でいいと思う なにやら話がややこしい方向に行ってるけど、
そもそも関数の呼び出しは副作用完了点だぞ? C言語初心者です。
やっとポインタの学習にさしかかったところです。
C言語におけるポインタという概念と、
メモリの間接アドレス指定とは似ていると思ったのですが、
この感覚は間違っていますか? ポインタの理解の前にメモリ間接アドレス指定をご存じな人ってすごいw >>879
ベーシック、アセンブラの順にやってきたら
だいたい理解はできているもんじゃないの? >>877
>>878
恐縮です
学習の中でつまずいたらまた質問させてください
>>879
>>880
間接アドレス指定のほか直接・相対・即値…などは
基本情報技術者試験の勉強範囲になっているので知りました
C言語もきっかけは基本情報の対策として取り掛かったものです
残念ながらBasicもアセンブラも手付かずです セミコロン2つ並ぶのってどういう意味でしょ?最初は誤植かとおもいましたが
for(i = n;;){ ←ここ
if(strcmp(hogehogehogehogehoge >>885 で for ループを使う必然性って何だろう
while でも良いように見える >>887
while (1) {
は warning が出るコンパイラもありますので
for (;;) {
を多用しています… 確かに for (i = n;;) /* 初期化あり, 継続条件なし, 更新なし */ よりは
i = n; // 初期化
for (;;) // 無限ループ, 終了判定はループ内
の方が for の使い方では見慣れた書き方だよな。
というか for (i = n;;) を見せられたら、いったん立ち止まって
頭の中で2行分けに翻訳して理解すると思うわ。 while(1) に難癖つけてくるコンパイラって具体的に何だ? https://www.sejuku.net/blog/25197#continue
で
if(i + 1 < 3) {
と書かれていて i < 2 でないのは何故でしょうか
先進的なコンパイラだと自動的に最適化されるものなのでしょうか >>892
実行結果を見ると、最初に表示されるのは「3回目の処理です」だね。
この 3 はループ変数 i から算出される値。
最初に表示したい値である 3 を if の条件式の中にも書いておく方が
プログラムが何をやってるか(3を表示する状態になるまで continue する)を
読み取りやすいという考え方かと。
if (i < 2) を見て「i < 2 の間は continue される。i == 2 になったら
continue されずに下の処理に進む。すると最初に表示される数字は i + 1 で 3」
と理解するより簡単だろう(とプログラムを書いた人が考えたのだろう)。
実験したところ、ちゃんと最適化されるみたいね。
if (i + 1 < 3) でも、アセンブリの方では 2 との比較になってた。 >>891
情報ありがとう
希ガスってことは昔の話だよな >>893
それを言うなら while(!0) だろ everlasting的な英単語を1でdefineしてwhileに突っ込んで無限ループ作ってるコードなら見たことある
却って分かりにくかった >>897
悪いなのび太、それ単体試験用のマクロなんだ #define forever while(1)
これでええやん 知りたいことが答えてもらえないが文脈からさっすると
for(i = n;;)は ;; こいつが無限ループさせる whileのときの (1)みたいなもんなんかな
そうなると i = n って表記は i が nといっしょやったらずっと無限ループしとけってことになるんかな
んーそうう考えると for(;;)だったら無条件でループやっとけって感じでつかえそうだけど i = nならとかなんか条件はいるなら ;; こんなん
つかわんでももっと他になかったんじゃろかと思うな。 しかしこのテキスト何の説明もなくいきなりあんな技使いやがってやぶりすてたろか >>900
for 分のカッコ内は必ずセミコロンが2つ必要で、最初の項目は変数の初期化、2番目の項目は終了条件、
3番目の項目はブロックの最後に実行させる(主に変数をインクリメントしたりデクリメントしたりする)処理だ。
この項目が抜けていた場合はその処理に関して何もしない。例えば2番目の項目が抜けていたら終了条件なし
(つまり無限ループ)になる。
まあ入門書見ればわかると思うが、これの置き換えだ。
i = 1;
while (i < 3) {
/* 何かの処理 */
i++;
}
↓
for (i = 1; i < 3; i++) {
/* 何かの処理 */
}
特別なのは終了条件が空の場合は終了させなくなる事だけ。 >>900
すまんね。>>885 の質問を見て、普通の for の使い方、つまり
for (初期化; 継続条件; 再初期化) は理解してると感じたのだ。
その辺の説明は >>901 を見てもらうとして、ちょっと気になった点。
for (i = n;;) の i = n は「i が n に等しければ…」ではなく、
「i に n の値を代入する」だよ。等しいかの判定には == (イコール2個)を使う。
for の普通の使い方では「ループ制御変数 i の値を n に初期化」ということ。
代入の = (イコール1個)と、等値判定の == (イコール2個)は、
携帯端末で見分けにくかったりするのかな。
自分では新式の装置を使わないので、そういう部分に思い至らなくてな。 お願いします。OSはcentos7です
メルセンヌツイスタを使って、ひとつだけ乱数を出したいのですが
乱数を出す間隔が非常に狭く、以下の関数でtime(NULL)を用いると
同じ乱数ばっかり出てきてしまいます。
※関数はコレを使ってます
http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html
たとえば、1回関数を実行して、ひとつ乱数を生成。
それを、秒間20や、30繰り返したとしても異なる乱数が出てくる方法ってありませんでしょうか
勝手なお願いですが、できる限り簡単な方法でお願いします。
VBAでパチンコシミュレーターを作ったのですが、
実行速度が非常に遅く、もっと高速化するためにCの勉強を始めたばっかりです >>904
time(NULL) は1秒以上の実行間隔がないとアウト
それ以外の何らかエントロピー源を使わにゃならんということだ
たとえばスペシャルファイルの/dev/randomだとか、
Core-i7ならrdrand命令を使うとか まあシステム由来のシードを使えばいいんだけど、分布・周期が問題なんだから同じ数字が出てきてもいいんじゃない?
シミュレータってそういうもんですよ。 >>904
乱数値を1個だけ返すコマンドを作成、シード値に time() を使用。
同じ1秒の間に何度もコマンドを呼ぶと同じ値しか返ってこない。
次の1秒も(さっきまでと違う値だが)同じ値が何度も返ってくる。
…という話なら、しごく当然だね。
元の目的のプログラム、パチンコのシミュレータだっけ?
そっちをCで作り始めて、メルセンヌ・ツイスタの関数を組み込んじゃえば
自動的に解消する問題って気がするけど。
シミュレータの方はVBAで続けて、乱数だけCのコマンドを使うって方針なの? >>909 それはその通りだね。
VBAはWindowsで動かして、CentOSの方では「乱数サーバ」を回す、
というクライアント・サーバ・モデルも何か変な感じだし。
だから、全面的にCentOS上のCでの開発に移行する準備として
乱数ルーチンのテスト用に値1個だけ返すコマンドを作ってみたら、
「立て続けに呼ぶと同じ値しか出ないぞ」と心配になったのかな、と。 >>752だ、報告遅くなってすまん
合格してた!!!
俺に教えてくれた人達、本当にありがとう
勉強してC言語はよく分からんってことだけ分かったわ ちなみに不合格だと必須科目だから同じ科目をもう一回受講しなきゃいけなかった >>912
むしろそれなら不合格でちゃんと勉強したほうが良かったような? 情報系じゃないのに共通科目とかで必須指定されてたりしたら単位だけもらっても問題ないんでね? dfコマンドの -h オプションみたいな
数値をヒューマンに優しい表現にしてくれるライブラリって
ありますか?
ddみたいに、ヒューマンから数値にしてくれるやつも欲しい log A / log 10 とって 10の累乗数出して 3で割って近場の補助単位を選択
(ヘクトとかデシとか 3の倍数じゃないのは 知らんw) ライブラリは知らんなあ。
でも簡単だから作っちゃうなあ。
あ、そうだ。お題スレのお題にするか。簡単すぎて馬鹿馬鹿しいかも知れんが。 ライブラリは知らんなあ。
でも簡単だから作っちゃうなあ。
あ、そうだ。お題スレのお題にするか。簡単すぎて馬鹿馬鹿しいかも知れんが。 あれライブラリ化されてるのかと思ってたけど無いのか
意外とあちこちのコマンドで出てくる仕様だし
汎用的なのがあると思ってた >>923
GNUの複数のコマンドで使われてるからあるかもよ。詳しい人がこのスレ見てないだけで。
まあしかし ls も df もソース公開されてる筈なので探せば何れわかる。 GNUのソースを参考にするのは良いけど、GPLへの感染に気をつけないとな。 FreeBSDのuserlandな訳で…
ライセンスは自身で確認されたし
「GPL汚染」という言葉は良く聞くけれど「感染」って何でしょう >>930
「GPU汚染」という非常にポピュラーな言い回しを使わず
敢えて「感染」と表現する理由が全く書かれていないようです >>931
感染の方が伝播するニュアンスが強調されている気がする 「GPL汚染」って言葉はGPLへの敵意が感じられるんで避けたのよ。
日頃からGNUさんのおかげで色々便利に使わせてもらってるわけだし。
でも、うっかり1ヶ所でも使うと、プロジェクト全部のソースが
GPLライセンスになって公開を義務付けられたりするのは、
やっぱ「感染」じゃないか、と思う部分もあったり。
よく「車輪の再発明をするのはバカバカしい」とか言うけど、
GPLが「丸い車輪」の利権を押さえてるせいで、
わざわざ自前で「歪んだ車輪」を作って使わざるを得ない
境遇に置かれてる人もいるんじゃないかな、と。
…この場で書くような話でもないんだがネ。 >>931
> 感染性
> これはあたかも、伝染病(それも不治の病)が広がっているかのように見える。
> このため、ソースを公開しないソフトウェアを作る一般的なソフトウェアメーカーや、
> 他のライセンス支持者からは、「感染性のライセンス」「ウイルス性のライセンス」と呼ばれる。
他人事なやつにゃ、あーそー(asshole)でしかないんだろうな >>931
マイナーな言い回しをするときは理由を添えないとダメなの? >>933 でうっかり「GPLライセンス」と書いたけど、
GPL が GNU General Public License のことなら
GPLライセンスだと「〜ライセンス・ライセンス」だね。
「〜ソースがGPLライセンスになって」は
「〜ソースにGPLが適用されて」あたりの方が適切だったか。
言葉の選択に敏感に気づいてくれたんで、理由の説明に5行ほど使ったが、
半面、「GPL汚染」を知っる人が、感染だと分からないことは予期しなかった。
(これはカマトトにカマトトで応じてるだけ、のつもり、為念)
「GPL汚染」がポピュラーってのは正式な用語ではないことも認識してるんだろうし、
してみると技術用語に対する完璧主義とも違うんだろうな。
…言葉の使い方について、少し言葉を使ってみた、と言う感じのお話。 ん、待て待てGPL汚染じゃなくGPU汚染と931は言っているな
NVIDIAの話か? それともAMD? ありゃりゃ、確かに「GPU汚染」だね。
文脈に基づく先入観で「GPL汚染」としか見えてなかった。
すると、そっちがお誘いだったのかな。節穴で申し訳ない。
ついでにコピーせずに投稿文を手打ちしてることの傍証にもなったね。 どんな有能なプログラマーにもタイプミスはある。許してさしあげろ。
それより5ch用のリントツールが必要だということが浮き彫りになったな。 GPL汚染というのは商用アプリケーションを作る会社が
GPLライセンスのライブラリーを使いたいのに
ソースを公開すると売れなくなるから使いたくないから言ってるのと
ソースをみせたくないひとが言っているんだよ まあ味方にもよるよね。GNUの思想を支持する側から見たらプログラムを自由に使えない事は悪だろうし。 ちょっと前MMUをMMOと言っちゃって、ちょっと恥ずかしかった。 25行目からが
if(c!=0){
break;
}
else{
continue;
}
while(c==0);
になってるけどwhileの場所が間違ってる。 28行目からだわ。つまり}が足りてない。そこだけ直したら上手くいくのかは確認してないけど。 >>952
正しくはどうなりますか?すみませんさっぱりわかりません… >>952
>>953
今気づきました!!ありがとうございます!やってみます! >>956
ありがとうございます
そこも間違えてたみたいです https://i.imgur.com/nY9LuSR.jpg
https://i.imgur.com/U46WJvs.jpg
https://i.imgur.com/wwRNBB2.jpg
試してるのですが最後の1文字が表示されないままずっと実行中になってしまいます。3枚目はhello world入力で何回か実行した時の画面です。上の3回は強制終了して、一番下のはフリーズしてるやつです
どなたかわかる方いましたら教えてもらえないでしょうか
何度もすみません🙏 随所でprintfしまくって、変数の値が想定通りか確認していくんだ
これをprintfデバッグという
ってか、まともなデバッガがある環境でやった方がいいよ >>960
配列の添字も一緒にprintfしてみれば。
あと変数名は意味のあるもんにした方がええよ。 a とか b はあかんわ。
あと配列は初期化した方がいいかもよ。自分で中身を把握してれば別にしなくていいんだけど。 >>960
check(int a, int b, int c[]);
がだめ。
aが既出の時は0を返して、既出じゃないときはaを返す関数になってるけど、
aに0を渡すと既出じゃなくても0が返るから既出扱いになる。 あと"hello world" に対してsent[10]は長さが足りてない。 >>961
>>965
無事解決しました
大変ありがとうございました(^ω^) スマホ世代は画像と文字の区別が付かないらしい
これホントだよ 区別を付けられる世代には是非、画像認証で出される文字を認識するプログラムを書いてもらいたい >>967
これからは書き込む時にヘッダーにContent-Typeつけないとダメだな 「要素型がint型で要素数がnの配列を受け取って、
全要素に添字と同じ値を代入する関数set_idx」を作成しました。
http://codepad.org/krsZoljq
配列aの要素数はマクロ定義で#define NUMBER 10とし、
問題なく動作しました。
ところが、この要素数10を60に書き換えてみたところ、
コンパイルされたexeファイルを実行しても動作しません。
コンパイラはMinGW(gcc)です。
思い当たる原因を教えていただけないでしょうか。 >>978
>>979さんの仰る通りint a[NUMBER]={0};と書いたら意図通りに動作しました。
a[]と宣言するのでは、配列に割り当てる適正なメモリサイズが確保できないということでしょうか、、、 >>980
どういう教科書を使っていて、どういう風に学習してるのか知らんが…
先生に確認した方が早いんでねえか >>980
初期化に使った右辺に合わせて自動的にサイズを決定してくれるので、
int a[] = {0};
だと大きさは 1 と指定したのと同じ。 >>981
社会人で完全に独学なので、質問するとしたらこういう場しかなくて…
初歩的な質問でスレ汚し申し訳ないです。
ちなみに教科書は柴田望洋『新・明解C言語(入門編)』を使っています
>>982
なるほど!
とてもわかりやすいです 私も「ド素人&独学でしかやってない&プライベートでしか使ってない」ってかんじですが
set_idx関数がバッファオーバーラン対策を全くやってないのが気になるかも
int *set_idx(int n) とかいう風な、ポインタを返す関数に書き換え、関数内でmallocというのが考えられるけど
正確にセキュアな方法はワカラン
https://www.ipa.go.jp/security/awareness/vendor/programmingv1/b06_02.html が参考になるかも知れないし
「まだ早い」ということになるかも知れないし、何とも言えない >>977
そのURLのページ昨日から開けなくてなんだかわからない。 >>990
乙
スレ立てのタイミングとか特になかったような
たまに落ちてて誰かが復活させたりとか… >>989 の補足というかスレチというか…
Windows 環境なら hta を javascript で書くというのも良いかもですね
コピペプログラミングベースで良いなら、ウィンドウを表示するプログラムを作ってチョコチョコとカスタマイズする位なら30分掛からない
「javascript 全く知らん&Excel VBAやマクロは少し分かる」なら hta を vbscript で書くのも良いかも
…このスレの人達からしたら忌み嫌われかねない環境かも…? >>993
Windows だけでよければ electron みたいな重量級のフレームワークをあらためて導入する必要もなく
ウェブ系の GUI デザインの延長で使える HTA は楽だとは思う。
「忌み嫌う」というよりは C とはまるで使いどころが違うので、
C を必要だと判断して始めた (その判断が正しいかどうかは別として) 人に対して状況を確認することなく
何か他の言語や環境を勧めるのは意味わからんという感じだと思う。 省略形にかぎらず関数使用でも理解不十分なまま作成する記述スタイルを変えれればこの先生きのこれるかもしれうめ _,,...,_
/_~,,..::: ~"'ヽ
(,,"ヾ ii /^',)
:i i"
| (,,゚Д゚) ・・・
|(ノ |)
| |
ヽ _ノ
U"U このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 56日 10時間 47分 19秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。