17

文字列の constness をキャストすることをstrtol()効果的に許可 (および強制) しているようです。strtod()

#include <stdlib.h>
#include <stdio.h>

int main() {
  const char *foo = "Hello, world!";
  char *bar;
  strtol(foo, &bar, 10); // or strtod(foo, &bar);
  printf("%d\n", foo == bar); // prints "1"! they're equal
  *bar = 'X'; // segmentation fault
  return 0;
}

上記では、自分でキャストを実行しませんでした。ただし、基本的には、警告などなしで、 myをfor mestrtol()にキャストします。(実際には、 として入力することはできないため、安全でない型の変更が強制されます。) 本当に危険ではありませんか?const char *char *barconst char *

4

4 に答える 4

14

代替案の方が悪かったので、私はそれを推測します。プロトタイプが次のように変更されたとしconstます。

long int strtol(const char *nptr, const char **endptr, int base);

ここで、非定数文字列を解析したいとします。

char str[] = "12345xyz";  // non-const
char *endptr;
lont result = strtol(str, &endptr, 10);
*endptr = '_';
printf("%s\n", str);  // expected output: 12345_yz

しかし、このコードをコンパイルしようとするとどうなるでしょうか? コンパイルエラー!直感的ではありませんが、 achar **を a に暗黙的に変換することはできませんconst char **。理由の詳細な説明については、 C++ FAQ Liteを参照してください。技術的にはC++について話していますが、引数はCでも同様に有効です。C/C++では、「型へのポインター」から「型へのポインター」への暗黙的な変換のみが許可されます。 perform は from to 、または同等に from "pointer to (pointer to )" to "pointer to ( pointer to )" です。const char **char * const *charconstchar

非定数文字列を解析することは、定数文字列を解析することよりもはるかに可能性が高いと推測するのでconst、一般的なケースをコンパイラエラーにするよりも、ありそうもないケースの不正確さが望ましいと仮定します。

于 2009-06-14T21:02:30.510 に答える
7

はい、他の関数にも同じ「コンスト ロンダリング」の問題があります (たとえば、strchr、strstr、すべて)。

まさにこの理由で、C++ はオーバーロード (21.4:4) を追加します。関数シグネチャstrchr(const char*, int)は 2 つの宣言に置き換えられます。

const char* strchr(const char* s, int c);
      char* strchr(      char* s, int c);

しかし、もちろん C では、const が正しいバージョンの両方を同じ名前で持つことはできないため、const が正しくないという妥協が生じます。

C++ では、strtol と strtod の同様のオーバーロードについて言及されておらず、実際、私のコンパイラ (GCC) にはそれらがありません。理由はわかりません: 暗黙的にキャストできないという事実char**(const char**オーバーロードがないことと一緒に) は、C について説明していますが、C++ オーバーロードの何が問題なのかよくわかりません。

long strtol(const char*, const char**, int);
于 2009-06-15T00:53:46.260 に答える
1

C++ モードでコンパイルするときに提供するコンパイラがあります。

extern "C" {
long int strtol(const char *nptr, const char **endptr, int base);
long int strtol(char *nptr, char **endptr, int base);
}

明らかに、これらは両方とも同じリンク時のシンボルに解決されます。

編集: C++ 標準によれば、このヘッダーはコンパイルされません。コンパイラがこれをチェックしなかっただけだと思います。定義は、実際にはシステム ヘッダー ファイルでこのように表示されます。

于 2009-06-15T01:00:03.327 に答える
1

最初の引数の「const char *」はstrtol()、文字列を変更しないことを意味します。

返されたポインターをどうするかはあなた次第です。

はい、タイプ セーフ違反とみなされる可能性があります。C++ はおそらく別の方法で処理を行うでしょう (ただし、私が知る限り、ISO/IEC 14882:1998 では<cstdlib>C と同じ署名で定義されています)。

于 2009-06-14T20:41:16.770 に答える