一、文字ポインタ、文字配列

文字ポインタ

文字列ポインタ変数自体は変数であり、文字列の先頭アドレスを格納するために使用されます。文字列自体はその先頭アドレスを先頭とする連続したメモリ空間に格納され、\0文字列の終わりとします。

char *ps="C Language";

は、1次元に10個の要素を置き、2次元に20個の要素を置くことを示し、値の格納場所は連続したメモリ領域であり、ポインタはありません。

char *ps;  // ps 字符串指针,是指针,是一个变量

ps="C Language"; // ps は文字列の先頭アドレスであり、ps++ を使って文字列を走査できます。文字列は ps を開始アドレスとする連続したメモリ空間に格納され、\0文字列の終わりとなります。

ここでは、明確に考えておくべき点が2つあります:

1、*a は単に1つの文字を指すだけです。

例を示すと次のとおりです:

例

#include <stdio.h> #include <stdlib.h> int main(void){ char *a= "bcd" ; printf("文字を出力:%c\n", *a); /*文字を出力するには、「%c」を使用します。*/ printf("文字を出力:%c\n", *(a+1) ); /*文字を出力するには、「%c」を使用します。*/ printf("文字列を出力:%s\n", a); /*文字列を出力するには、「%s」を使用します。また、a の前にはアスタリスク「*」を付けてはいけません。*/ system("pause"); /*出力結果を見るためには*/ }

実行結果は次のとおりです:

输出字符:b 
输出字符:c 
输出字符串:bcd 

2、文字列定数が式に現れる場合、その値はその文字列定数の最初の文字のアドレスを表します。したがって、hello は単にそのアドレスを表すだけです。元の宣言方法は、次の宣言方法と同等です:

char *a;  
a="hello"; /*这里字符串"hello"仅仅代表其第一个字符的地址*/

文字配列

文字配列は複数の配列要素によって構成されており、文字列全体を格納するために使用できます。(つまり、文字配列を使用して文字列を格納します)。

C言語では、文字列は文字配列として扱われます。(C++ではそうではありません)

文字配列の初期化方法:

1). 文字列定数を使って文字配列を初期化できます:

char  str[]={"Iamhappy"};

波括弧は省略できます。

char  str[]="Iamhappy";  # 系统自动加入 \0 

注意:上記のような文字配列全体への代入は、文字配列の初期化時のみ使用でき、文字配列への代入には使用できません。文字配列への代入は、その要素に1つずつ代入することしかできません。

以下の代入方法は誤りです:

char str[20];
str="Iamhappy";

文字配列の各要素に一つずつ代入します。

char str[10]={'I','','a','m','','h','a','p','p','y'};

C言語では、文字列を表現して格納する方法は2つあります:

(1)文字配列を使用して文字列を格納する

char str[]="IloveChina";

(2)文字ポインタを使用して文字列を指す

char *str="IloveChina";

両方の表現方法での文字列出力はどちらも次を使用します:printf("%s\n", str);

%s文字列を1つ出力することを表します。文字ポインタ変数名 str を指定すると(最初の表現方法では、文字配列名は文字配列の先頭アドレスであり、2番目の方法のポインタと同じ意味です)、システムはまずそれが指す1つの文字データを出力し、次に自動的に str を +1 させて、次の文字を指すようにします... このようにして、文字列の終了を示す識別子に遭遇するまで続けます。\0 。


二、文字列ポインタ

string* str代入できます:

string* str = {"hello", "world"}; 
//  对比与 char *name = "wang" = {'w','a','n','g'}
//  *(str) = "hello", *(str+1) = "world"
//  *(*(str)+1) = 'e'

つまり、各要素は string 型であり、char* とは異なります。ただし、string* は char** で置き換えることができます:

string = char*, string* = char**

三、(文字列)ポインタ配列

例

#include <stdio.h> void main() { char *str[] = {"Hello", "C++", "World"}; //char (*str)[] = ... int i; for(i=0; i<3; i++) printf("%s\n", str[i]); } // str // str // str

或

#include <stdio.h> #include <string.h> int main() { char *str[] = {"Hello", "C++", "World"}; char **p; for(p=str; p<str+3; p++) puts(*p); #*p文字列の先頭アドレスを表し、*p[0]は文字列の最初の文字のアドレスを表します。}

例

#include<stdio.h> #include<stdlib.h> int main() { char *str[3]={"Hello","C++","World"}; printf("%s,%s,%c",str[0],str[0]+1,*(*(str+2)+1)); system("pause"); }

結果は次のとおりです:

Hello,ello,o

形式:char* na[N] = {"li", "zh", "li", "zh", "li"};

char *a[]:aが配列であることを示し、配列の要素はポインタで、char型を指します(配列内のすべての要素は連続したメモリに格納されます)。配列名は配列の最初のバイトのメモリアドレスであり、配列名aもポインタを表します。したがって、aはaアドレスに格納されている内容を表すのではなく、aアドレスそのものを表します。

a+1:aの2番目の要素のメモリアドレスを表すので、8バイト加算されます。(aの要素はcharポインタであり、必要な領域は8バイト(64ビットメモリアドレス)だからです。)

*(a+1):aという配列の2番目の要素の内容(char型のポインタであり、この例ではworld文字列のアドレス)を表します。

*(*(a+1)):aという配列の2番目の要素の内容(charポインタ)が指す内容(w文字)を表します。

char * a[10]:この配列は最大10個の要素(charポインタ)を格納できることを示します。つまり、この配列は10*8 = 80バイトを占有します。

#w:        a+1   =>   *(a+1)  =>   *(a+1)[0]
           指针(地址)   指针内容(字符串)      字符

四

char *argv:理解为字符串
char **argv:理解为字符串指针
char *argv[]:字符串指针数组

int main(int argc, char*argv[])これは、配列名(あるいはポインタ配列)を関数パラメータとして使う典型的な例であり、しかもサイズが指定されていない仮パラメータ配列です。

呼び出された関数内で配列要素を処理する必要がある場合は、別の仮引数を設定して、処理が必要な配列要素の数を渡すことができます。また、配列名を関数の実引数として使用する場合、配列要素の値を仮引数に渡すのではなく、実引数配列の先頭要素のアドレスを仮引数配列に渡します。これにより、2つの配列は同じメモリ領域を共有します。これは、変数を関数の引数として使用する場合とは作用が異なります。

配列を関数パラメータとして使う例や、ポインタ配列をmain関数の仮パラメータとして使う例を参照してみてください。谭浩强のあの本は非常に詳しく、これについて詳細に説明されています。

1. char [] が関数のパラメータとして使われる場合、char * を表します。関数のパラメータとして渡される場合、実際には配列の最初の要素のアドレスがコピーされます。

したがって、void test (char a[]) は void test ( char * a ) と同等です。

 char x[10] ;

そして、test(x) を呼び出すことは、x の最初の要素のアドレスをパラメータ a に与えることと同等です。

2. char * a と char a[]

  • 共通点:aはどちらもポインタであり、char型を指します。
  • 相違点:char a[] は内容をスタックに格納します。char *a はポインタをスタックに格納し、内容を constants に格納します。

3. char * a

  • 共通点:aはどちらも2級ポインタであり、*a は1級ポインタを表し、**a はメモリに格納されている内容を表します。
  • 相違点:char * a

4. ちょっとしたコツ:[] と * の数は対応しています。例えば char a[][] のポインタの階層は2であり、char **a に相当します。char *a[] も同様に、2層のポインタです。混乱したときは、* がいくつあるか、[] がいくつあるかを数えれば、どの場合に内容が格納され、どの場合にアドレスが格納されるかがわかります。例えば char a[][] の場合、&a、a、*a はすべてアドレスであり、**a は内容です。

原文アドレス:https://www.cnblogs.com/cj2014/p/3726380.html