タグ付けされた質問 「c」

Cは、システムプログラミング(OSおよび組み込み)、ライブラリ、ゲーム、クロスプラットフォームに使用される汎用プログラミング言語です。このタグは、ISO 9899標準で定義されているC言語に関する一般的な質問で使用する必要があります(特に指定のない限り、最新バージョン9899:2018。バージョン固有のリクエストには、c89、c99、c11などのタグも付けます)。CはC ++とは異なり、合理的な理由がない限り、C ++タグと組み合わせるべきではありません。

1
ASLRがオンになっているのに、__ libc_start_mainのアドレスがGDB内で常に同じであるのはなぜですか?
Breakpoint 1, 0x00007ffff7de8060 in __libc_start_main () from /usr/lib/libc.so.6 (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/firstlove/projects/org-ioslide/example/a.out Breakpoint 1, 0x00007ffff7de8060 in __libc_start_main () from /usr/lib/libc.so.6 (gdb) r The program being debugged has been started already. Start it …
16 c  linux  gdb  libc  aslr 


1
np.dotが不正確なのはなぜですか?(n次元配列)
np.dot2つの'float32'2D配列を取得するとします。 res = np.dot(a, b) # see CASE 1 print(list(res[0])) # list shows more digits [-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287] 数字。例外として、次のものを変更できます。 ケース1:スライスa np.random.seed(1) a = np.random.randn(9, 6).astype('float32') b = np.random.randn(6, 6).astype('float32') for i in range(1, len(a)): print(list(np.dot(a[:i], b)[0])) # full shape: (i, 6) [-0.9044868, -1.1708502, 0.90713596, 3.5594249, 1.1374012, -1.3826287] …
15 python  c  arrays  numpy  precision 

3
非constへのポインターと同じアドレスのconst引数へのポインターを使用した関数呼び出し
データの配列を入力し、ポインターを使用して別のデータの配列を出力する関数を書きたいのですが。 コンパイラがconstを最適化できることを知っているので、両方が同じアドレスsrcをdst指している場合、結果はどうなのかと思います。未定義の動作ですか?(CとC ++の両方にタグを付けました。これは、答えが異なるかどうかわからないためです。両方について知りたいのです。) void f(const char *src, char *dst) { dst[2] = src[0]; dst[1] = src[1]; dst[0] = src[2]; } int main() { char s[] = "123"; f(s,s); printf("%s\n", s); return 0; } 上記の質問に加えてconst、元のコードでを削除すると、これは明確になりますか?

5
効果のないステートメントがCで合法と見なされるのはなぜですか?
この質問が初心者の場合はご容赦ください。次のプログラムを検討してください。 #include <stdio.h> int main() { int i = 1; i = i + 2; 5; i; printf("i: %d\n", i); } 上記の例では、ステートメント5;とi;はまったく不要に見えますが、コードはデフォルトで警告やエラーなしでコンパイルされます(ただし、gccはでwarning: statement with no effect [-Wunused-value]実行すると警告をスローします-Wall)。それらはプログラムの残りの部分に影響を与えないので、なぜ彼らはそもそもなぜ有効なステートメントと見なされるのですか?コンパイラは単にそれらを無視しますか?そのような発言を許可することには何か利点がありますか?
13 c 

5
少しブール値と比較する
私がuint16_tでエンコードされたフラグのセットを持っているとしましょうflags。たとえば、AMAZING_FLAG = 0x02。今、私には機能があります。この関数は、フラグを変更するかどうかを確認する必要があります。変更する場合は、フラッシュに書き込む必要があるためです。そしてそれは高価です。したがって、flags & AMAZING_FLAGがに等しいかどうかを確認するチェックが必要ですdoSet。これが最初のアイデアです。 setAmazingFlag(bool doSet) { if ((flags & AMAZING_FLAG) != (doSet ? AMAZING_FLAG : 0)) { // Really expensive thing // Update flags } } これは、直感的なifステートメントではありません。次のようなより良い方法があるはずだと思います。 if ((flags & AMAZING_FLAG) != doSet){ } しかし、これは、実際に仕事をしないtrueに等しくなるように思えます0x01。 それで、少しをブール値と比較するためのきちんとした方法はありますか?

1
Cコードのtimespec_get()の秒コンポーネントの1秒遅れてtime()が報告する時間がなぜですか?
次のコードスニペット: struct timespec ts; for (int x = 0; x < 100000000; x++) { timespec_get(&ts, TIME_UTC); long cTime = (long) time(NULL); if (cTime != ts.tv_sec && ts.tv_nsec < 3000000) { printf("cTime: %ld\n", cTime); printf("ts.tv_sec: %ld\n", ts.tv_sec); printf("ts.tv_nsec: %ld\n", ts.tv_nsec); } } この出力を生成します: ... cTime: 1579268059 ts.tv_sec: 1579268060 ts.tv_nsec: 2527419 cTime: …
12 c  time  posix  timespec 

4
この関数が文字列の正しい長さを返すのはなぜですか?(charポインタのインクリメント)
これは文字列の文字数を数える関数です: int str_len(const char* s) { int i = 0; while(*(s++)) { i++; } return i; } なぜこれは正しい長さを返すのですか? この関数を単純なStringで呼び出すとしましょう"a"。次にs、whileループでインクリメントされるため、sおよびの値iは両方とも0です。
12 c  while-loop  strlen  c89 

1
同じ名前の関数にマクロを定義するのはなぜですか?
私はhttps://github.com/torvalds/linux/blob/master/arch/x86/include/asm/atomic.hで以下のコードを見つけました static __always_inline bool arch_atomic_sub_and_test(int i, atomic_t *v) { return GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, e, "er", i); } #define arch_atomic_sub_and_test arch_atomic_sub_and_test #define本当に何をしますか?いつそうする必要がありますか?
12 c  linux-kernel 

3
「揮発性」は、マルチコアシステムのポータブルCコードで何かを保証しますか?
見た後、束 の 他の 質問 と その 回答を、私はという印象を得るCで「揮発性」というキーワードが正確に何を意味するのかには広範な合意はありませんが。 標準自体でさえ、誰もがそれが何を意味するのかについて合意するのに十分明確ではないようです。 他の問題の中で: それはあなたのハードウェアとあなたのコンパイラに依存して異なる保証を提供するようです。 コンパイラの最適化には影響しますが、ハードウェアの最適化には影響しません。そのため、独自のランタイム最適化を行う高度なプロセッサでは、コンパイラが防止したい最適化を防止できるかどうかさえ明確ではありません。(一部のコンパイラーは、一部のシステムで一部のハードウェア最適化を防止するために命令を生成しますが、これは決して標準化されていないようです。) 問題を要約すると、「大量に読み取った後」「揮発性」が次のようなことを保証しているように見えます。値は、レジスタからだけでなく、少なくともコアのL1キャッシュにも、同じ順序で読み書きされます。読み取り/書き込みがコードに表示されます。しかし、これは役に立たないようです。レジスタからの読み取り/レジスタへの書き込みは同じスレッド内ですでに十分ですが、L1キャッシュとの調整は、他のスレッドとの調整に関してそれ以上何も保証しません。L1キャッシュとだけ同期することがいつ重要になるかは想像できません。 USE 1 揮発性の広く合意された使用は、ライトを(直接、ハードウェアで)制御するメモリ内のビットのように、特定のメモリ位置がI / O機能にハードウェアでマッピングされている古いシステムまたは組み込みシステムであるようです、またはキーボードのキーが押されているかどうかを通知するメモリ内のビット(ハードウェアによって直接キーに接続されているため)。 と思われる「利用1」とは、そのターゲットのマルチコアシステムを含んポータブルなコードでは発生しません。 USE 2 「use 1」とそれほど変わらないのは、割り込みハンドラー(ライトの制御やキーからの情報の保存など)によっていつでも読み書きできるメモリです。しかし、すでにこのため、システムによっては、割り込みハンドラが 独自のメモリキャッシュを備えた別のコアで実行される可能性があり、「揮発性」はすべてのシステムでキャッシュの一貫性を保証しないという問題があります。 したがって、「use 2」は「volatile」が提供できる範囲を超えているようです。 USE 3 他に議論の余地のない唯一の用途は、コンパイラーが認識しない同じメモリーを指している同じメモリーを指すさまざまな変数を介したアクセスの誤最適化を防ぐことです。しかし、人々がそれについて話していないので、これはおそらく議論の余地がないだけです-私はそれについての言及を1つだけ見ました。また、C標準では、「異なる」ポインター(関数への異なる引数など)が同じ項目または近くの項目を指す可能性があることをすでに認識しており、コンパイラーがそのような場合でも機能するコードを生成する必要があることをすでに指定しています。しかし、私はこのトピックを最新(500ページ)の標準ですぐに見つけることができませんでした。 では「use 3」はまったく存在しないのでしょうか。 したがって、私の質問: 「揮発性」は、マルチコアシステムのポータブルCコードで何かを保証しますか? 編集-更新 最新の標準を参照した後、答えは少なくとも非常に制限されているように見えます: 1.標準は、特定のタイプ "volatile sig_atomic_t"の特別な扱いを繰り返し指定しています。ただし、この規格では、マルチスレッドプログラムでシグナル関数を使用すると、未定義の動作が発生することも規定されています。したがって、この使用例は、シングルスレッドプログラムとそのシグナルハンドラ間の通信に限定されているようです。 2.この規格では、setjmp / longjmpに関連する「揮発性」の明確な意味も規定されています。(重要なコードの例は、他の質問と回答に記載されています。) したがって、より正確な質問は次のようになります 。「揮発性」は、(1)シングルスレッドプログラムがシグナルハンドラから情報を受信できるようにする、または(2)setjmpを許可することを除いて、マルチコアシステムのポータブルCコードで何でも保証しますかsetjmpとlongjmpの間で変更された変数を表示するコード? これははい/いいえの質問です。 「はい」の場合、「揮発性」が省略された場合にバグになるバグのないポータブルコードの例を示すことができればすばらしいでしょう。「いいえ」の場合、マルチコアターゲットの場合、これら2つの非常に特殊なケース以外では、コンパイラーは「揮発性」を無視してもかまいません。

4
コンパイラのビルトインを使用せずにオーバーフローセーフな追加を効率的に計算するCスニペットはありますか?
intオーバーフローが発生すると失敗する、別のに追加するC関数を次に示します。 int safe_add(int *value, int delta) { if (*value >= 0) { if (delta > INT_MAX - *value) { return -1; } } else { if (delta < INT_MIN - *value) { return -1; } } *value += delta; return 0; } 残念ながら、GCCやClangでは十分に最適化されていません。 safe_add(int*, int): movl (%rdi), %eax testl %eax, …

1
山かっこのGCCの実装には次のものが含まれます。なぜそれは以下に説明されているとおりでなければならないのですか?
このドキュメントのセクション2.6計算済みインクルードには、次の段落があります。 行が<トークンで始まり、>トークンを含むトークンストリームに展開される場合、<と最初の>の間のトークンが結合されて、含まれるファイル名が形成されます。トークン間の空白は1つのスペースに削減されます。その後、最初の<の後のスペースは保持されますが、閉じる>の前のスペースは無視されます。CPPは山かっこインクルードのルールに従ってファイルを検索します。 これは実装で定義されていることはわかっていますが、なぜGCCにとってこのようにする必要があるのですか?上記の強調表示された文を具体的に参照しています。 編集 上で引用したものの前の3番目の段落が次のことを言っていることに気づきました。 マクロを定義するときは注意が必要です。#defineテキストではなくトークンを保存します。プリプロセッサは、マクロがの引数として使用されることを知る方法がない#includeため、ヘッダー名ではなく通常のトークンを生成します。文字列定数に十分近い二重引用符を含むインクルードを使用する場合、これが問題を引き起こすことはほとんどありません。 ただし、山括弧を使用すると、問題が発生する可能性があります。 ここでどんな問題が指摘されているか知っていますか?
11 c++  c  gcc  language-lawyer 

2
IBMサンプルコード、非再入可能関数がシステムで機能しない
プログラミングの再入学を勉強していました。IBMのこのサイト(本当に良いサイト)。以下にコピーしたコードを見つけました。これは、ウェブサイトに登場する最初のコードです。 コードは、「危険なコンテキスト」で絶えず変化する2つの値を出力することにより、テキストプログラムの非線形開発(非同期)で変数への共有アクセスに関する問題を示します。 #include <signal.h> #include <stdio.h> struct two_int { int a, b; } data; void signal_handler(int signum){ printf ("%d, %d\n", data.a, data.b); alarm (1); } int main (void){ static struct two_int zeros = { 0, 0 }, ones = { 1, 1 }; signal (SIGALRM, signal_handler); data = zeros; alarm …
11 c  gcc  signals  x86-64  data-race 

3
関数から一意のvoidポインターを返す
void *CIの関数からを取得するには、次のようにします(非常に基本的な例)。 void *get_ptr(size_t size) { void *ptr = malloc(size); return ptr; } 使用時に同じ結果を得るにはどうすればよいstd::unique_ptr<>ですか?
11 c++  c  unique-ptr 

1
コンパイラが呼び出し先に保存されたレジスタの使用をここで主張するのはなぜですか?
次のCコードを考えてみます。 void foo(void); long bar(long x) { foo(); return x; } -O3またはのいずれかを使用してGCC 9.3でコンパイルすると-Os、次のようになります。 bar: push r12 mov r12, rdi call foo mov rax, r12 pop r12 ret clangからの出力は、呼び出し先保存レジスタとしてではrbxなく選択することを除いて同じですr12。 しかし、私はこのように見えるアセンブリを見たいと思っています/期待しています: bar: push rdi call foo pop rax ret 英語では、これが私の目に見えるものです。 呼び出し先が保存したレジスタの古い値をスタックにプッシュします x呼び出し先が保存したレジスタに移動します コール foo 移動しx、戻り値レジスタに呼び出し先保存レジスタから スタックをポップして、呼び出し先が保存したレジスタの古い値を復元します 呼び出し先に保存されたレジスターをいじる必要がないのはなぜですか?代わりにこれを行わないのはなぜですか?それはより短く、よりシンプルで、おそらくより高速に見えます: xスタックにプッシュ コール foo xスタックから戻り値レジスタにポップ 私の組み立ては間違っていますか?余分なレジスタをいじるよりも効率が悪いのでしょうか?これらの両方に対する答えが「いいえ」である場合、GCCまたはclangのいずれかがこのようにしないのはなぜですか? …
10 c  gcc  assembly  clang  x86-64 

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.