-8

次の行をさらに詳しく調べようとしています。

char* filename="file.txt";    

fopen()これは、 ;を使用するときに行います。

私の質問は次のとおりです。

  1. filename文字のアドレス(core2Duo では 36 ビット)を保持することになっています。なぜ「文字列」を入れるのですか?

  2. 存在しないアドレスを格納している可能性があるため、コンパイラがエラーを生成しないのはなぜですか?

4

4 に答える 4

2

filename は文字 (core2Duo では 36 ビット) のアドレスを保持するはずですが、なぜ「文字列」を入れるのでしょうか?

char* filename="file.txt";は有効な式です。理由は、C の文字列リテラルの型が、、 、と互換性があるchar[N]ことです。したがって、この式で行っているように、ポインター変数に文字列アドレスを割り当てることができます。char*char[N]char*char*

存在しないアドレスを格納している可能性があるため、コンパイラがエラーを生成しないのはなぜですか?

以下の3点をお読みください。

  • その有効なアドレス:

いいえ、式char* filename="file.txt";ではfilename、有効なアドレスが割り当てられています。概念的には次のようになります (アドレスが 21 で始まると仮定):

filename   21  22   23  24  25  26  27  28  29
+---+     +------------------------------------+
|21 |---> |'f'|'i'|'l'|'e'|'.'|'t'|'x'|'t'|'\0'|
+---+     +------------------------------------+

filename pointing to string, a valid address.

エラーや警告は表示されません。以下のコード例を試してください。

例-1:

#include<stdio.h>
int main(int argc, char **argv){
    char* filename = "filename.txt";
    printf("%s", filename);
    return 0;
}

それをコンパイルします。

:~$ gcc y.c  -Wall -pedantic 
~$ ./a.out 
filename.txt

エラーやワーリングはなく、コンパイルと実行は完璧です。

私の答えに対するあなたのコメントについて:

の文字列はC、少し複雑なデータ構造intであり、 、char、などの単純な値変数ですfloat

基本的なデータ型の場合:

int i = 5;  You are assigning value 5, to variable i
char c = 'A'; You are assigning value 'A' to char variable c. 
float f = 5.5f; You are assigning value 5.5f to float variable f.

ただし、文字列の場合は、次のようにします。

  char* filename = "filename.txt"; 

次に、実際に文字列のアドレス"filename.txt" を char* ポインター変数に割り当てていますfilename

一方、次の場合:

  char filename[] = "filename.txt"; 
      //        ^ notice [] in declaration 

次に、文字列「filename.txt」を割り当てています。char の配列に変換します。filename[]ここでfilenameは type はchar[]です。

両方の宣言の詳細については、以下を参照してください: sizeof(&arr) は何を返しますか?

文字列リテラルは、使用するコンテキストで値またはアドレスの依存関係を示す場合があります。たとえば、試してみてください:printf(" address: %p, value: %s", "Hello", "Hello");

  • コンパイラはアドレスを検証しませんが、構文をチェックします。

コンパイラは、アドレスが正当であることを検証する責任を負いません。コンパイラはコードを移植し、構文エラー (コンパイルできない型の不一致など) をチェックします。偽のアドレスをポインターに割り当てても、警告が表示されないとします (キャストアドレスを正しく入力した場合)。以下の例を考えてみましょう:

例-2:

#include<stdio.h>
int main(int argc, char **argv){
    char* filename = "filename.txt";
    char* ptr = (char*)0x020202;
    printf("%s %s\n", filename, ptr);
    return 0;
}

コンパイル:

$ gcc y.c  -Wall -pedantic 

また、エラーやワーリングも発生しません。構文的にはすべて問題なく有効だからです。
ptr存在しない可能性のある偽のアドレスが割り当てられているのに対し)。

  • 無効なアドレスにより実行時に未定義の動作が発生する

まあ、ptr偽のアドレスが割り当てられている example-2 コードをコンパイルするのは問題ありません。コンパイラは、スティックチェックフラグオプションを使用してもエラー/警告を生成しません-Wall -pedantic

しかし、このコードを実行するのは間違っています。printf ステートメントで割り当てられたメモリアドレスにアクセスしようとするptrと、プログラムが異常な動作をします (別の実行インスタンスで)。-LanguageC標準では、 Undefined behaviorと呼ばれています。

このコードを実行すると、OS (コンパイラではなく) がプロセスによるメモリ権利侵害を検出します -- 有効なメモリへの無効なアクセスは次のようになります: SIGSEGV 無効なアドレスへのアクセスは次のようになります: SIGBUS. これにより、セグメンテーション違反とコアダンプが発生してプロセスが終了/クラッシュする可能性があります。

不正なメモリ読み取りにアクセスしたときに何が起こるかを学び、知るには: strcat() 実装は機能しますが、最後にコア ダンプが発生します。

于 2013-07-13T05:55:33.393 に答える
1

filename は文字 (core2Duo では 36 ビット) のアドレスを保持するはずですが、なぜ「文字列」を入れるのでしょうか?

悲しいことに、私たちはそうではありません。文字列リテラルの最初の文字へのポインターを入れています。文字列"file.txt"の型char[9]は であり、ポインターに割り当てられると、 に減衰しchar *ます。const charただし、それを変更することは違法であるため (未定義の動作が発生する)、へのポインターに割り当てる必要があります。これを読む。

存在しないアドレスを格納している可能性があるため、コンパイラがエラーを生成しないのはなぜですか?

すみませんが、どんな実在しないアドレスについて話しているのですか? 文字列リテラルの最初の文字のアドレスは、常に明示的に有効です!

(しかし、たとえそうであったとしても、コンパイラはセマンティクスについてほとんど知っていません。無効なポインタを使用する可能性がある場合、常に警告することはできません。確かに、できる場合もありますが、期待は高くありません.)

于 2013-07-13T05:54:53.813 に答える
1

良い C プログラミングの本を読んでください。ポインターと配列とは何かを説明しています。

文字列リテラル like"file.txt"char[]配列です (ただし、const char[]文字列リテラル like 内での代入"abc"[1]='D';未定義の悪趣味な動作であり、gcc -Wall警告されるためと考えてください)。配列は、(通常は) 最初のセル (インデックス 0) へのポインターとして理解できます。つまり、配列はポインターに分解されます。つまり、文字列リテラルをcharポインターに割り当てることができます。

ただし、C では配列はポインターではありません。たとえば、sizeofいくつかの配列は、特に各要素のサイズの適切な倍数ですsizeof("abcde") == 6(すべての文字列リテラルの終端の null バイトのため)。しかし、sizeofいくつかのポインターは、ポイントされたゾーンのサイズとは無関係であり、ほとんどのシステムでは、すべてのポインターが同じサイズ、つまり機械語のサイズを持っています。

gcc -Wallすべての警告 ( Linux など) を取得するには、コンパイラに明示的に要求する必要があります。

于 2013-07-13T05:55:05.423 に答える
1
  1. はい、アドレスを保持していますが、アドレスの後に隣人のアドレス、隣人のアドレスなどが続くこともあります。このアドレスの「文字列」を介して、値が実際に発見。
  2. 「filename.txt」ファイルが将来のある時点で作成されfopen、プログラムが実際に実行されるまで呼び出しが評価されない可能性が非常に高いため、コンパイラはエラーを生成しないはずです。
于 2013-07-13T05:56:04.557 に答える