C言語char s[]とchar**sの違い


C言語ポインタは配列の代わりに使用できます。
1、行列の本質
配列は複数の要素のセットであり、アドレスが連続するセルにメモリ内に分布しているので、その下付きで配列の異なる配列にアクセスすることができる。
たとえば:
いくつか展示します

char s[3] = "0x1";
printf("s2   :
"); printf("%c
", s[0]); printf("%c
", s[1]); printf("%c
", s[2]);
2、ポインタ
ポインタも変数です。メモリユニットに保存されているのは他の位置を識別するアドレスです。アドレスも整数です。32ビットプラットフォームの下では32ビット、4バイトです。
針の指すところ
ポインタとは、ポインタ変数が保存している他のアドレスユニットに格納されているデータの種類を指します。
たとえば:

int *ptr;//ptr                      
float *p;//  p                     
指し示すデータタイプがどちらであっても、ポインタ自体の値は常に整数です。
3、文字配列
文字配列はまず配列で、配列の要素はすべて文字です。

char s[10];//       10      ,        %c
C言語で変数を定義すると、以下のように初期化できます。

char s[10] = {"hello world"};
コンパイラが上の定義と割り当てに出会うと、hello worldと\0を逐次連続配列メモリに記入します。
C言語には本当の文字列タイプがありません。文字配列で文字列を表し、文字配列の要素アドレスも連続しています。C言語では配列が配列のあるメモリ位置の先頭アドレスを表すと規定されています。つまり、str文字列はstr[0]に等しく、str=&str[0]です。
printf("%s",str);なぜ最初の住所で文字列を出力できますか?
C言語における文字列定数の本質はアドレスであるため、例えば、

char  *s ;
s = "Hello";
ここで文字列を一つの文字列ポインタ変数に割り当てます。最初はC言語でコンパイラが文字列定数に住所を割り当てます。もし「ハロー」なら、メモリに記憶されている0 x 3000 1 0 x 3000 2 0 x 3000 3 0 x 3000 4 0 x 3005です。本当の意味が分かります。
s=「ハロー」=0 x 3000
したがって、私たちはハローを文字列と見なすことができます。コンパイラは彼を住所0 x 3000と見なします。すなわち文字列定数の本質はその最初の文字の住所を表しています。

char *s;
s = "Hello";
printf("%p
",s);//%p , 8 , 0
出力00796 BD 0、つまり「ハロー」の先頭アドレスです。
文字配列:
char str[10]=「ハロー」
つまりstr=&str[0]
C言語での文字列操作は、メモリ内の記憶部の先頭アドレスを介して行われ、文字列の究極の本質です。
4、char*とchar a[]
char*sとchar a[]:
aは文字列の最初のアドレスを表していますが、sは文字列の最初のアドレス(最初の文字の住所)を保存しています。つまり、s=aと見なすことができます。つまり、配列名をポインタに値を付けて住所を表してもいいですが、a=sを与えてはいけません。つまり、ポインタの値を配列名に与えてはいけません。
配列名は定数ですので、変更できません。
配列要素には次のようにアクセスできます。

char a[] = "Hello";
char*s = a;
int i;
for(i = 0;i < strlen(a);i++)
{
printf("%c",s[i]);
//printf("%c",*s++);   
}
文字ポインタは間接オペレータ*で内容を取ることができます。また、配列の下付き形式[]、配列名も*で操作することができます。
例えばprintf("%c"、**a);を印刷します。
char*sとchar a[]の本質的な違い
char a[10]を定義すると、コンパイラは配列に10個のユニットを割り当て、各ユニットのデータタイプは文字であり、char*sを定義すると、sはポインタ変数であり、4バイト、32ビットのみを占めて、アドレスを保存するために使用される。
sizeof(a)=10,sizof(s)=4
aの長さは10で、sの長さは4です。sはint型ですから。
printf("%p",s)------これはsを表すユニットに保存されているアドレスです。
printf("%p"、&s);-----------------これは変数自体のメモリユニットのアドレスを表します。。。いい加減にしないでください。
まとめ:char**sは文字列の先頭アドレスを保存するポインタ変数だけで、char a[]は多くの連続メモリユニットであり、ユニットの要素はchar型、char*とchar a[]は同じ効果を持っています。文字列の本質から、つまり文字列のアドレスを与えると文字列を操作できますが、char*とchar a[]の本質的な属性は違います。
5、char**とchar*a[]
char*a[]
*より優先度が高いので、a[]は配列であり、配列の要素はcharタイプであり、char要素は変数であり、アドレスを保存します。
char*a=「{Dug}Cat」「Chicken」
配列の要素は文字列であり、sizef(a)は12であり、4+4+8ではなく、文字列定数の本質はアドレスであり、a配列の要素はchar*ポインタであり、ポインタ変数は整数タイプで、4バイトを占めると、3つの要素は12バイトである。

char *a[] = { "Dog","Cat","Chicken" };
printf("%p %p %p 
", a[0], a[1], a[2]);

配列中の3つの要素は3つのメモリアドレスを保存していることが見られます。この3つのアドレスは3つの文字列の最初のアドレスを表しています。文字列自体ではなく、3つのアドレスは連続していません。それはコンパイラが「Docg」、「Cat」、「Chicken」に割り当てられたメモリ間のアドレスです。

char *a[] = { "Dog","Cat","Chicken" };
printf("           :%p %p %p 
", &a[0], &a[1], &a[2]);//

3つの要素要素要素要素要素要素要素の所在地は連続的であり、各アドレスは4バイトの違いがあることがわかる。
char**s
char*は二級のポインタで、sは一級のポインタchar*の住所を保存します。
たとえば:

char *a [ ] = { "Dog","Cat","Chicken" };
char **s =   a;//---   
配列aは配列要素メモリユニットの最初のアドレス、すなわちa=&a[0]=010 FFD 44を表し、すなわち**s=001 D 6 BE 0=「Dug」、
これはsを通じてa中のデータにアクセスできます。

printf(“%s”,*s);
printf("%s",a[0]);
printf("%s",*a);
三つは同じですが、a=sは一つの定数です。
char**s=「ハローワールド」間違いです
sのタイプはchar**、「hello world」のタイプはchar*。
全部住所ですが、指し示すタイプが違っていますので、このように使えません。その本質から分析すると、「ハローworld」は0 x 00001のような住所を表しています。この住所の内容は「H」であり、char型であり、sも住所を保存しています。この住所の内容はchar*で、ポインタタイプです。

char  **s;
*s = "hello world";
コンパイルは大丈夫ですが、printf("%s",s)は崩壊します。printf("%s",s);時に、まずs保存の住所があって、またこの住所の中でchar*の住所を探し当てて、つまり**sです。
s=0 x 1000の場合
0 x 1000のメモリユニットに「hello world」のアドレスを保存しました。***s=0 x 00001、このprintf(%s、**s)はまず0 x 1000を見つけて、その後0 x 00001を見つけます。もし直接char**sを使えば、**s=「hello world」、s変数に保存されているのは効果がないランダムで使えない値です。彼にメモリアドレスを割り当てるつもりです。

char  **s ;
s = (char **) malloc(sizeof(char**));
*s =  "hello world";
このようにsは利用可能なアドレスを割り当てて、s=0 x 1234、そしてアドレス0 x 1234があるメモリの中の位置を返して、「hello world」の値を保存しました。
以下の手順では、文字ポインタsが定義され、文字列「メッセージ」のアドレスが格納されています。

#include  <stdio.h>
void  buf( char **s)
{
 *s = "message";
}
int main()
{
 char *s ;
 buf(&s);
 printf("%s
",s); }
すなわち、2段階のポインタは1段階のポインタのアドレスを保持しています。そのタイプはポインタ変数で、1段階のポインタはデータがあるメモリユニットのアドレスを保存しています。
参考:
https://blog.csdn.net/daiyutage/article/details/8604720
6、C言語におけるchar s[]とchar**sの違い
この両者の違いについては、Stock Overflowからの説明が非常にはっきりしています。
http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c
The difference here is that
char**s=「ハローワールド」
will place Hello world in the read-only parts of the memory and making s a pointer to that、making any writing operation on this memory illegal.While dong:
char[]=[Hello world]
pust the lighteral string in read-only memory and copies the string to newly allocated memory on the stack.Thus making s [0] = 'J' legal.
まとめてみます。ポイントは以下の通りです。
  • char []によって定義されているのは文字列配列であり、この文字配列の記憶は新しい空間を割り当ててから充填されるので、配列の内容は変更可能であり、すなわちs[0] = 'J'を介して合法的である。
  • char *sで定義されているのは文字列ポインター変数で、ポインタの値は文字列のメモリ中のアドレスです。このポインタ変数では、値を変更する=アドレスを変更する=ポインタの向きを変更する、例えば最初の文字から第二の文字を指すようになります。その後、文字ポインタ変数を変更する権限はありませんでした。*(s+1) = 'J'などの文字の値を変更します。つまり、ポインタの値は変更できますが、ポインタの値は変更できません。
  • ここでC言語char s[]とchar**sの違いについての文章を紹介します。C言語char s[とchar**sの内容については以前の文章を検索してください。または下記の関連記事を引き続きご覧ください。これからもよろしくお願いします。