seki_yo氏C languageノートの誤訳

seki_yo氏がいい加減な情報を発信しているので、添削。
1
seki_yo @seki_yo

(再掲) C language ノート togetter.com/li/1027251 今も 初心者ですが もしかして 役立つかも。 長いので お好きなところから どうぞ。 (^。^)

2017-08-21 00:21:28
まとめ C language ノート 備忘録です ... 2014 pv 11
園芸家 @engeikana

12.2以降の内部関数の翻訳は壊滅的で笑える。内部関数のコードを勝手に外に出しちゃってるし。 翻訳⇒ www4.kcn.ne.jp/~yoitiro/haten…...「C language ノート」togetter.com/li/1027251#c40…

2017-08-21 01:31:14
園芸家 @engeikana

registerを、レジスタと訳さずに記憶回路と訳したり、レキシカルスコープのことを全く理解せずにトンチンカンな訳をしていたりこの人のページは一切参考にしないほうがよい。「C language ノート」togetter.com/li/1027251#c40…

2017-08-21 01:35:37
園芸家 @engeikana

seki_yo氏の珍訳と原文を示す。 正しい訳:おそらくGCCで内部関数が使える主な理由は柔軟性のためですが、正しく使えば若干の性能向上ができます。内部関数はレキシカルスコープに従い、それを含む(外側の)関数の変数にアクセス可能です。 pic.twitter.com/CZiVvN7VGd

2017-08-21 01:59:21
拡大
拡大
園芸家 @engeikana

正しい訳:従って、通常ならポインタを引数にとる関数が必要な処理を、内部関数ならポインタを使わずに(効率よく)処理できます。ポインタを用いると性能が若干落ちます。ポインタを持つ変数はレジスタに格納できないためです。ポインタの動作原理上、ポインタはレジスタを指し示すことができません。 pic.twitter.com/BKIjIsSw4m

2017-08-21 02:12:05
拡大
拡大
園芸家 @engeikana

正しい訳:通常の関数のように内部関数を宣言する必要はありませんが、しても構いません。そうする理由は読みやすくするためだけなので、使用する場所の近くで内部関数を定義するほうがよいでしょう。判断はお任せします。ただし、内部関数を宣言する場合には明示的にautoをつける必要があります。 pic.twitter.com/aVylUDL2Nd

2017-08-21 02:27:21
拡大
拡大

12.3. The Benefits of Nested Functions

Probably the main reason for nested functions being allowed by GCC for flexibilities sake although small performance increases can be gained by using them correctly. Nested functions obey Lexical scoping, they have access to the variables of the function that contains them.

12.3. 内部関数の利点

seki_yo:GCC で与えられる内部関数の柔軟性の理由はおそらく、その性能の向上が小さいにもかかわらず、正確に用いることで効果が得られるためだ。内部関数は字義どおり(内部の) スコープに従いそれを含んだ関数の変数として使うことができる

おそらくGCCで内部関数が使える主な理由は柔軟性のためですが、正しく使えば若干の性能向上ができます。内部関数はレキシカルスコープに従い、それを含む(外側の)関数の変数にアクセス可能です。

(解説)Lexical scoping……変数の参照範囲が静的に決定される方式。seki_yo氏は知らないので「字義どおり(内部の) スコープ」と誤訳している。

For this reason, they can accomplish tasks that would usually require functions taking pointers as arguments. There is a slight performance loss when pointers are used because a variable that has a pointer cannot be stored in a machine register. Pointers never point to machine registers so how would the pointer work?

seki_yo:こうした理由によりそれは引数としてポインタをとる関数が要求されるたいていの仕事を成し遂げることができる。ポインタを使うとポインタをもつ変数は記憶回路 register で記憶できないという理由からほんのわずか実行時のロス performance loss ができる。ポインタはけっして機械の記憶回路を指し示さない、どうしてこのポインタが使えるだろう?

従って、通常ならポインタを引数にとる関数が必要な処理を、内部関数ならポインタを使わずに(効率よく)処理できます。ポインタを用いると性能が若干落ちます。ポインタを持つ変数はレジスタに格納できないためです。ポインタの動作原理上、ポインタはレジスタを指し示すことができません。

(解説)seki_yo氏は、内部関数を使えばポインタを使わずに外側の関数のローカル変数にアクセスできるという効用を理解できていないので、トンチンカンな訳をしている。

You don't have to declare nested functions like you do normal functions however you can if you like. The only reason for doing so would be for the sake of readability, you might like the function definition to appear near where it is used. It's up to you, but if you do decide to declare you nested function you must explicitly declare it as auto.

seki_yo:普通の関数のように内部関数を宣言する必要はないがもし望むなら (それは) 可能だ。そうすることの唯一の理由は読みやすさのためだろうから関数をそれが使われる位置の近くにもってくることは好ましいかもしれない。これは自分次第だが、内部関数の宣言を決めたのなら自分でそれを確実に correctly 宣言しないといけない。

通常の関数のように内部関数を宣言する必要はありませんが、しても構いません。そうする理由は読みやすくするためだけなので、使用する場所の近くで内部関数を定義するほうがよいでしょう。判断はお任せします。ただし、内部関数を宣言する場合には明示的にautoをつける必要があります。

(解説) you might like ~ …… you might want to ~と同様の、「~するとよいでしょう」の意味。また、seki_yo氏は、関数リンケージのautoを知らないため、「自分で」と誤訳している。explicitlyは省略して暗黙な指示に任せないで明示的に指示する意味。autoを省略するとexternリンケージになるため、リンク時にエラーになる。「確実に correctly」は原文にはないので、seki_yo氏が勝手に書いたと思われる。

園芸家 @engeikana

気になったので、9.5 registerも見てみるとなかなかの壊滅ぶり。 正しい訳:register記憶クラスは、頻繁に使用される変数をできるだけ最適化するようコンパイラに伝えるヒントとして使用される。通常、変数はメモリ(RAM)に格納され、必要に応じてCPUとの間を行き来する。 pic.twitter.com/2QEMLJqwi5

2017-08-21 02:41:15
拡大
拡大
園芸家 @engeikana

(続き)データの転送スピードはかなり速いが効率化が可能である。ほぼ全てのCPUにはレジスタという記憶領域が内蔵されており、そこにデータを格納すれば、メモリからデータを取得するオーバヘッドがかからない。レジスタは、メモリに比べて容量がかなり小さいので、数個の変数しか格納できない。

2017-08-21 02:47:41
園芸家 @engeikana

(続き)GCCは頻繁にアクセスされる変数を推定してレジスタに割り当てる。この推定は良好に動作するが、GCCにはプログラムの目的が分からないので完璧ではない。そこで、registerキーワードを用いれば、最適化が必要な変数をGCCに伝えることができるのである。

2017-08-21 02:56:20
園芸家 @engeikana

以上、seki_yo氏の珍訳の一部を指摘し、正しい訳を述べた。 元の英文は文法的にかなり崩れているため、英文が意味するところを理解するには、C言語や計算機やプログラミング言語に関する基礎知識と、GCC特有の機能を使った経験が必要である。seki_yo氏にはそれがない。

2017-08-21 03:01:39

9.5. register

The register storage class is used as a hint to the compiler that a variable is heavily used and access to it should be optimised if possible.

seki_yo:register という記憶クラスは頻繁に使用しアクセスする変数をコンパイラによって効率化させる手がかり hint として使われる。

register記憶クラスは、頻繁に使用される変数をできるだけ最適化するようコンパイラに伝えるヒントとして使用される。

(解説)a hint to the compiler that a variable ... should be optimised ……変数を最適化するようにコンパイラに指示するヒント。「ヒント」とは、必ずしも指示した通りにはならないことがある設定のこと。optimize は「最適化」と訳すのが慣習。「コンパイラによって効率化させる」は「コンパイラ効率化させる」か「コンパイラによって効率化される」なら可。

Variables are usually stored in normal memory (RAM) and passed back and forth to the computers processor as needed, the speed the data is sent at is pretty fast but can be improved on.

seki_yo:変数は通常メインメモリ normal memory (RAM) に記憶され必要になるとコンピュータの処理装置 processor のあちらこちらに渡される。データの送信速度は相当高速だが改良を加えることができる。

通常、変数はメモリ(RAM)に格納され、必要に応じてCPUとの間を行き来する。データの転送スピードはかなり速いが効率化が可能である。

(解説)be passed back and forth ……いったりきたり。この文では、CPUとメモリ間のデータの移動のこと。「あちらこちらに渡される」は、いったいどこにいくんですか?という珍訳。

Almost all computer processors contain cpu registers, these are memory slots on the actual processor, storing data there gets rid of the overhead of retrieving the data from normal memory.

seki_yo:ほとんど全てのコンピュータ処理装置は cpu 記憶回路 cpu register からなり実際は処理装置上のメモリスロットだ。ここに記憶されたデータはメインメモリからデータを取り出すという付加 overhead (処置) を免れる。

ほぼ全てのCPUにはレジスタという記憶領域が内蔵されており、そこにデータを格納すれば、メモリからデータを取得するオーバヘッドがかからない。

(解説)register ……「レジスタ」と訳すのが慣習。「記憶回路」ではキャッシュも含まれるので、ここでは意味が抽象的になりすぎる。
overhead ……「オーバーヘッド」と訳すのが慣習。本来の処理に付帯する余分な処理のことで通常は削減したい。「取り出すという付加処置」は、データ取得という本来の処理がオーバーヘッドであるかのように読めるので誤訳。

This memory is quite small compared to normal memory though so only a few variables can be stored there.

seki_yo:このメモリはメインメモリと比べて非常に小さいのだがほんのわずかな変数のみを記憶することができる。

レジスタは、メモリに比べて容量がかなり小さいので、数個の変数しか格納できない。

GCC will always make use of registers by deciding what variables it thinks will be accessed often, this works well but will never be perfect because GCC doesn't know the purpose of your program.

seki_yo:GCC は常にアクセス数の多い変数がなにかを考え決めて記憶回路 register を使用する。それはうまく働くがけっして完全ではない。なぜなら GCC にはそのプログラムの目的はわからないからだ。

GCCは頻繁にアクセスされる変数を推定してレジスタに割り当てる。この推定は良好に動作するが、GCCにはプログラムの目的が分からないので完璧ではない。

By using the register keyword you can tell GCC what needs to be optimised.

seki_yo:register というキーワードを用いることで効率化にはなにが必要かを GCC に知らせることができる。

そこで、registerキーワードを用いれば、最適化が必要な変数をGCCに伝えることができるのである。

(解説)what needs to be optimised ……最適化すべきもの。whatはここでは変数のことを指す。「効率化にはなにが必要か」は、効率化の対象ではなく効率化の必要条件のように読めるので誤訳。

内部関数の例をむやみに改変

内部関数の例を、ふつうの関数として改変。これでは原文の意味が通じない。

seki_yo氏によるもの

    Example 12-2. simple_nested_function.c

#include <stdio.h>

int swap(int *, int *);

int
main()
{
    int first = 12, second = 34;

    printf("f is %d and s is %d\n", first, second);
    swap (&first, &second);
    printf("f is %d and s is %d\n", first, second);

    return 0;
}

int swap(int *a, int *b)
{
    int tmp;

    tmp = *a;
    *a = *b;
    *b = tmp;

    return 0;
}

原文のコード

Example 12-2. simple nested function

#include <stdio.h>

int
main()
{
  int swap (int *a, int *b)
    {
      int c;

      c = *a;
      *a = *b;
      *b = c;

      return 0;
    }

  int first = 12, second = 34;

  printf("f is %d and s is %d\n", first, second);

  swap(&first, &second);

  printf("f is %d and s is %d\n", first, second);

  return 0;
}

さらに詳しい説明

レキシカルスコープ

内部関数から外の関数の変数を直接アクセスしてポインタを使わないで済ます例としては、下記のコードが適当である。

#include <stdio.h>

int
main()
{
  int first = 12, second = 34;

  int swap ()
    {
      int c;

      c = first;
      first = second;
      second = c;

      return 0;
    }

  printf("f is %d and s is %d\n", first, second);

  swap();

  printf("f is %d and s is %d\n", first, second);

  return 0;
}

内部関数の宣言

ふつうは宣言しないものだが、もしするなら auto をつける。つけないとエラーになる。上記の例では、下記のように宣言する。

int
main()
{
  auto int swap();
  int first = 12, second = 34;
  ...