153

しばらく前に、新しい C++ 開発者と一緒に仕事をしていたときに、彼が「なぜ変数名を数字で始められないのですか?」という質問をしました。

一部の数値にはテキストを含めることができ(123456L、123456U)、コンパイラがアルファ文字を含むすべてのものを変数名と見なしていた場合、それは不可能であることを除いて、答えを思いつくことができませんでした。

それは正しい答えでしたか?他に理由はありますか?

string 2BeOrNot2Be = "that is the question"; // Why won't this compile?
4

24 に答える 24

129

数字の文字列は、有効な識別子であると同時に有効な数値でもあるためです。

int 17 = 497;
int 42 = 6 * 9;
String 1111 = "Totally text";
于 2008-12-04T21:43:22.447 に答える
127

これについてよく考えてください:

int 2d = 42;
double a = 2d;

とは何ですか?2.0? または42?

ヒント、わからない場合は、数字の後の d は、二重リテラルである前の数字を意味します

于 2008-12-04T21:38:01.727 に答える
62

今では慣習になっていますが、技術的な要件として始まりました。

昔は、FORTRAN や BASIC などの言語のパーサーは、スペースの使用を必要としませんでした。したがって、基本的に、以下は同じです。

10 V1=100
20 PRINT V1

10V1=100
20PRINTV1

ここで、数字の接頭辞が許可されたとします。これをどう解釈しますか?

101V=100

なので

10 1V = 100

またはとして

101 V = 100

またはとして

1 01V = 100

だから、これは違法にされました。

于 2011-04-26T16:58:10.790 に答える
44

コンパイル中の字句解析でバックトラックが回避されるためです。次のような変数:

Apple;

コンパイラは、文字「A」に出会うとすぐにそれが識別子であることを認識します。

ただし、次のような変数:

123apple;

コンパイラは、「a」に到達するまで、それが数値か識別子かを判断できず、結果としてバックトラックが必要になります。

于 2014-10-13T11:16:51.317 に答える
15

コンパイラー/パーサー/字句解析器は私にとってずっと昔のことですが、コンパイル単位の数字がリテラルを表すのか識別子を表すのかを明確に判断するのが難しいことを覚えていると思います。

スペースが重要でない言語 (私の記憶が正しければ、ALGOL や元の FORTRAN など) は、そのため、識別子の先頭に数字を使用できませんでした。

これは、ストレージまたは数値ベースを示す特別な表記法の前にさかのぼります。

于 2008-12-04T21:43:56.767 に答える
11

識別子を数字で開始できるようにすると便利だと思います。1 人か 2 人が、識別子の先頭にアンダースコアを追加することでこの制限を回避できると述べていますが、それは本当に見苦しいものです。

問題の一部は、0xdeadbeef などの数値リテラルに起因していると思います。これにより、数字で始まる識別子のルールを覚えやすくすることが難しくなっています。それを行う 1 つの方法は、キーワードまたは数値リテラルではない [A-Za-z_]+ に一致するものをすべて許可することです。問題は、0xdeadpork は許可されているが 0xdeadbeef は許可されていないなどの奇妙なことにつながることです。最終的には、私たちはすべての肉に対して公平であるべきだと思います :P.

C を初めて学習したとき、変数名の規則は恣意的で制限的だと感じたのを覚えています。何よりも、覚えるのが難しく、覚えるのをあきらめました。私は正しいと感じたことをしただけで、かなりうまくいきました。もっと多くのことを学んだので、それほど悪くはないように思えます。そして、ようやく正しく学ぶことができました.

于 2009-05-25T22:29:19.457 に答える
7

変数名は数字で始めることはできません。これは、次のような問題を引き起こす可能性があるためです。

int a = 2;
int 2 = 5;
int c = 2 * a; 

cの値は何ですか?は4、または10です!

もう一つの例:

float 5 = 25;
float b = 5.5;

最初の5は数値、またはオブジェクト(。演算子)です。2番目の5にも同様の問題があります。

たぶん、他のいくつかの理由があります。したがって、変数名の先頭に数字を使用しないでください。

于 2013-01-13T23:56:30.367 に答える
7

トークンを解析するときは、最初の文字を見て、それが識別子かリテラルかを判断し、それを正しい関数に送信して処理する必要があるため、いくつかの理由で決定した可能性があります。これがパフォーマンスの最適化です。

もう1つのオプションは、それがリテラルではないかどうかを確認し、識別子のドメインをユニバースからリテラルを引いたものにすることです。しかし、これを行うには、すべてのトークンのすべての文字を調べて、それを分類する方法を知る必要があります。

また、識別子はニーモニックであると想定されているため、数字よりも単語の方がはるかに覚えやすいという文体上の意味合いもあります。元の言語の多くが、次の数十年間のスタイルを設定するために書かれていたとき、「to」を「2」に置き換えることは考えていませんでした。

于 2008-12-04T21:50:02.107 に答える
5

制限は任意です。さまざまな Lisp では、シンボル名を数字で始めることができます。

于 2012-01-12T05:04:58.977 に答える
4

COBOL では、変数を数字で始めることができます。

于 2014-12-14T11:10:10.667 に答える
4

キーワードと識別子が数字で始まることを許可した場合、レクサー (コンパイラの一部) は、数値リテラルとキーワードの開始を簡単に区別できず、さらに複雑化 (および低速化) する必要があります。

于 2011-04-26T16:57:05.713 に答える
4

変数名の先頭に数字を使用すると、コンパイル中または解釈中のエラー チェックが非常に複雑になります。

数字のように始まる変数名の使用を許可すると、おそらく言語設計者に大きな問題を引き起こすでしょう。ソースコードの解析中に、コンパイラ/インタープリターは、変数名が期待される数字で始まるトークンに遭遇するたびに、巨大で複雑な一連のルールを検索して、トークンが本当に変数なのかエラーなのかを判断する必要があります。 . 言語パーサーに追加された追加の複雑さは、この機能を正当化しない場合があります。

私が覚えている限り (約 40 年)、変数名の先頭に数字を使用できる言語を使用したことはないと思います。これは少なくとも一度は行われたと確信しています。たぶん、ここの誰かが実際にどこかでこれを見たことがあります。

于 2008-12-04T21:55:18.727 に答える
4

何人かの人々が気付いているように、変数名の有効なフォーマットについては歴史的な問題がたくさんあります。また、言語設計者は、新しい言語を作成する際に常に知識に影響を受けます。

そうは言っても、言語が変数名を数字で始めることを許可していないのは、ほとんどの場合、それが言語設計のルールだからです。多くの場合、そのような単純なルールにより、言語の解析と字句解析が非常に簡単になるためです。ただし、すべての言語設計者がこれが本当の理由であることを知っているわけではありません。最新の字句解析ツールが役立ちます。これを許容できるものとして定義しようとすると、構文解析の競合が発生するからです。

OTOH、言語に変数名を知らせる一意に識別可能な文字がある場合、数字で始まるように設定することができます。同様のルールのバリエーションを使用して、変数名にスペースを許可することもできます。しかし、結果として得られる言語は、一般的な従来の言語とはまったく似ていない可能性があります。

変数が数字で始まり、スペースが埋め込まれていることを許可するかなり単純な HTML テンプレート言語の例については、Qomposeを見てください。

于 2008-12-04T22:26:22.113 に答える
2

言語設計者がルールを作ったので、C++ はそれを持つことができません。独自の言語を作成する場合は、確かにそれを許可できますが、おそらく彼らと同じ問題に遭遇し、許可しないことにするでしょう. 問題を引き起こす変数名の例:

0x、2d、5555

于 2008-12-04T22:42:22.517 に答える
2

構文規則の緩和に関する主な問題の 1 つは、コーディング プロセスに認知的不協和が導入されることです。コードについての考え方は、これによってもたらされる明確さの欠如によって深く影響を受ける可能性があります。

「ツールの最も重要な側面は、そのユーザーへの影響です」と言ったのはダイクストラではありませんか?

于 2009-11-05T21:46:36.620 に答える
2

コンパイラには、次の 7 つのフェーズがあります。

  1. 字句解析
  2. 構文解析
  3. セマンティック分析
  4. 中間コード生成
  5. コードの最適化
  6. コード生成
  7. 記号表

コード片をコンパイルする際の字句解析フェーズでバックトラッキングが回避されます。Apple のような変数は、字句解析フェーズで文字 'A' 文字に遭遇すると、コンパイラはすぐにそれが識別子であることを認識します。ただし、123apple のような変数の場合、コンパイラは、'a' に到達するまで、それが数値なのか識別子なのかを判断できず、変数であることを識別するために字句解析フェーズに戻るためにバックトラックが必要です。ただし、コンパイラではサポートされていません。

トークンを解析するときは、最初の文字を見て、それが識別子かリテラルかを判断し、それを正しい関数に送信して処理するだけです。これがパフォーマンスの最適化です。

于 2018-08-05T07:08:58.253 に答える
1

おそらく、それが数字なのか識別子なのかを人間が見分けやすくするためと、伝統のためです。数字で始まる識別子を使用しても、字句スキャンがそれほど複雑になることはありません。

すべての言語で、数字で始まる識別子が禁止されているわけではありません。Forth では、それらは数値である可能性があり、小さな整数は通常、Forth ワード (本質的には識別子) として定義されていました。これは、"2" を数値として認識するよりも、2 をスタックにプッシュするルーチンとして "2" を読み取る方が高速であるためです。その値は 2 でした (プログラマーまたはディスク ブロックからの入力を処理する際に、Forth システムはスペースに従って入力を分割します。定義された単語であるかどうかを確認するために辞書でトークンを検索しようとし、そうでない場合はそれを数値に変換しようとし、そうでない場合はエラーのフラグを立てます。)

于 2009-05-01T21:20:55.837 に答える
1

シンボル名が数字で始まることを許可したとします。ここで、変数に 12345foobar という名前を付けたいとします。これを 12345 とどのように区別しますか? 実際、正規表現を使用することはそれほど難しくありません。問題は実際にはパフォーマンスの 1 つです。なぜこれを詳細に説明することはできませんが、基本的には、12345foobar と 12345 を区別するにはバックトラックが必要であるという事実に要約されます。これにより、正規表現が非決定的になります。

これについては、はるかに優れた説明があります

于 2009-05-20T19:54:08.940 に答える
0

もともとは、変数名を数字ではなく文字列として覚えやすい (より意味を与えることができる) という単純な理由でしたが、文字列の意味を強化したり、同じ変数名を使用できるようにするために、文字列内に数字を含めることができますが、別個の、しかし密接な意味または文脈を持つものとして指定してもらいます。たとえば、loop1、loop2 などは、ループ内にいること、および/またはループ 2 が loop1 内のループであることを常に知らせます。アドレスと 1121298 のどちらを変数として使用しますか? 覚えやすいのはどっち?ただし、言語が単なるテキストや数字 ($ の $ など) ではないことを示すために何かを使用する場合、実際には違いはありません。これは、コンパイラーに、その後に続くものが変数として扱われることを伝えるためです (この場合)。

于 2012-02-22T21:21:53.430 に答える
0

変数は、コンパイラによってコンパイル時にも値と見なされる可能性があるため、値は値を再帰的に何度も呼び出す可能性があります

于 2015-04-08T13:38:52.293 に答える
0

簡単な答えは、できるということだと思います。制限は言語ベースです。C++ や他の多くの言語では、言語がサポートしていないためできません。それを許可するルールは組み込まれていません。

この質問は、チェスで王様が一度に 4 つのマスを移動できないのはなぜでしょうか? という質問に似ています。それは、チェスではそれが違法な動きだからです。確かに別のゲームでそれはできますか。それは、プレイされているルールに依存します。

于 2008-12-04T21:54:57.493 に答える