基本復習char*とchar[]について(回転)


C言語でrevert関数を実現し、入力した文字列を元の列に逆順して返す機能を果たします.
 
ネット上にコードがあります.
char *revert(char * str)
{
  int n=strlen(str);
  int i=0;
  char c;
  for(i=0;i < n/2; ++i)
    {
      c=str;
      str=str[n-i];
      str[n-i]=c;
    }
  return str;
}
       str       c=str         

自分のコード
char* reversed(char inputStr[])
{
    if(inputStr == NULL)
    {
       return NULL;
    }
    else
    {
       int n = strlen(inputStr);/
       char c;
       for(int i = 0;i       {
 
           c = inputStr[i];
           inputStr[i] = inputStr[n-i-1];
           inputStr[n-i-1] = c;
 
       }
       return inputStr;
    }
}
 
char*とchar[]について話します(回転)
 
問題導入:実習中に以前からデフォルトであったエラーが発見され、同様にchar*c=“abc”とchar c[]=“abc”であり、前者はその内を変更する
容量プログラムはクラッシュしますが、後者は完全に正しいです.プログラムデモ:テスト環境Devc++コード実行結果2293628 4199056 abc 2293624 2293624 abc 2293620 4199056 abc
#include using namespace std;
main(){   char *c1 = "abc";   char c2[] = "abc";   char *c3 = ( char* )malloc(3);   c3 = "abc";   printf("%d %d %s/n",&c1,c1,c1);   printf("%d %d %s/n",&c2,c2,c2);   printf("%d %d %s/n",&c3,c3,c3);   getchar();}   
 
参考資料:まずコンパイラが占有するメモリのパーティション形式を明らかにしなければならない:一、予備知識-プログラムのメモリはc/C++でコンパイルされたプログラムが占有するメモリを割り当てて以下のいくつかの部分1、スタック区(stack)-コンパイラが自動的に分配して解放し、関数のパラメータ値、局所変数の値などを格納する.操作方法は
データ構造内のスタック.2、ヒープエリア(heap)—一般的にプログラマーによってリリースが割り当てられ、プログラマーがリリースしない場合、プログラム終了時にOSによって回収される可能性がある.データに注意
構造の中のスタックは別物で、分配方式はチェーンテーブルに似ていて、ほほほ.3、グローバル領域(静的領域)(static):グローバル変数と静的変数の記憶は一つに配置され、初期化されたグローバル変数と静的変数
変数は1つの領域にあり、初期化されていないグローバル変数と初期化されていない静的変数は隣接する別の領域にある.プログラム終了後システム
釈放する.4、文字定数領域-定数文字列はここにあります.プログラムが終了するとシステムから解放されます.5、プログラムコードエリアこれは先輩が書いたもので、とても詳しいです//main.cpp  int a=0;//グローバル初期化区char*p 1;//グローバル未初期化領域main(){int b;スタックchar s[]=「abc」//スタックchar*p 2;//スタックchar*p 3=「123456」;//123456/0定数領域でp 3がスタック上.static int c=0;//グローバル(静的)初期化領域p 1=(char*)malloc(10);p 2=(char*)malloc(20);//10バイトと20バイトが割り当てられた領域はスタック領域にあります.   strcpy(p1,"123456");//123456/0は定数領域に配置され、コンパイラはp 3から「123456」に最適化される可能性があります.}二、スタックとスタックの理論知識2.1申請方式stack:システムによって自動的に割り当てられる.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間heapを開きます:プログラマーが自分で申請して、そして大きさを指定して、cの中でmalloc関数はp 1=(char*)malloc(10)のようです;C++では、p 2=(char*)malloc(10)などのnew演算子を使用します.ただし、p 1、p 2自体はスタック内にあることに注意してください.2.2申請後のシステムの応答スタック:スタックの残りの空間が申請した空間より大きい限り、システムはプログラムにメモリを提供する.そうしないと、異常提示スタックがオーバーフローする.≪ヒープ|Heap|emdw≫:まず、オペレーティング・システムに空きメモリ・アドレスを記録するチェーン・テーブルがあることを知っておく必要があります.システムがプログラムの申請を受信すると、チェーン・テーブルを巡回し、申請した空間よりも大きな最初のヒープ・ノードを探し、その後、そのノードを空きノード・チェーン・テーブルから削除します.
このノードの空間はプログラムに割り当てられ、また、ほとんどのシステムでは、このメモリ空間のヘッダアドレスに今回の割り当ての大きさが記録されます.
小さく、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックの大きさは必ずしも正ではない
申請の大きさと同じで、システムは自動的に余分な部分を空きチェーンテーブルに再入れます.2.3申請サイズの制限スタック:Windowsでは、スタックは低アドレスに拡張されたデータ構造であり、連続したメモリの領域である.この言葉の意味は桟頂の地です
アドレスとスタックの最大容量はシステムで予め定められており、WINDOWSではスタックの大きさは2 M(1 Mということもあるが、とにかく1つのコンパイルである
場合によって決定される定数)は、申請された空間がスタックの残りの空間を超えるとoverflowが提示されます.したがって、スタックから取得できる空間
より小さい.ヒープ:ヒープは高アドレスに拡張されたデータ構造で、不連続なメモリ領域です.これは、システムがチェーンテーブルで格納される空きメモリであるためである.
アドレスは、自然に不連続であり、チェーンテーブルの遍歴方向は低アドレスから高アドレスに向かう.スタックのサイズは、コンピュータシステムで有効な
仮想メモリ.このことから,スタックが得られる空間は比較的柔軟であり,比較的大きいことが分かる.2.4申請効率の比較:スタック:システムによって自動的に割り当てられ、速度が速い.しかし、プログラマーはコントロールできません.スタック:newで割り当てられたメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.また、WINDOWSでは、Virtual Allocでメモリを割り当てるのが一番です.彼はスタックではなく、スタックではなく、直接入っています.
プログラムのアドレス空間にはメモリが1枚残っていますが、最も使いにくいです.しかし、スピードが速く、最も柔軟です.2.5スタックおよびスタック内のストレージコンテンツスタック:関数呼び出し時に、最初にスタックされたのは、メイン関数の次の命令(関数呼び出し文の次の実行可能文)の
アドレス、それから関数の各パラメータで、大多数のCコンパイラの中で、パラメータは右から左へスタックに入って、それから関数の中の局所的な変化です
量.静的変数はスタックに入らないことに注意してください.今回の関数呼び出しが終了すると、ローカル変数は先にスタックを出て、それからパラメータで、最後にスタックトップポインタは最初に保存したアドレス、つまりメインを指します.
関数の次のコマンドで、プログラムはそのポイントで実行されます.ヒープ:通常、ヒープのヘッダにヒープのサイズを1バイトで格納します.スタックの具体的な内容はプログラマーが手配します.2.6アクセス効率の比較char s 1[]=「aaaaaaaaa」;char *s2="bbbbbbbbbbbbbbbbb";aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbはコンパイル時に確定した.しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.例えば、#includevoidmain(){char a=1;char c[]="1234567890";char*p="1234567890";a=c[1];a=p[1];return;}対応するアセンブリコード10:a=c[1];004010678A4DF1movcl,byteptr[ebp-0Fh]0040106A884DFCmovbyteptr[ebp-4],cl11:a=p[1];0040106 D 8 B 55 ECmovedx,dwordptr[ebp-14 h]004010708 A 41201 moval,byteptr[edx+1]004010738845 FCMovbyteptr[ebp-4],al第1種は読み出し時に文字列中の要素をレジスタclに直接読み出し,第2種はポインタ値をedxに先に読み出し,
edxは文字を読み取り、明らかに遅い.2.7まとめ:スタックとスタックの違いは以下の比喩で見ることができる:スタックを使うのは私たちがレストランで食事をするように、注文(申請を出す)、お金を払う、食べる(使用する)だけで、満腹になったら行って、気にしないでください.
野菜を切る、野菜を洗うなどの準備や茶碗を洗う、鍋を洗うなどの掃除は、彼のメリットは速いが、自由度は小さい.山を使うのは自分で好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて、自由度が高いです.
自己総括:char*c 1=“abc”;実際には、文字定数領域に1つのブロックを割り当てて「abc」を格納し、スタックにc 1にアドレスを割り当てて指向する
このアドレスは、定数「abc」を変えると自然に崩壊します
しかしchar c 2[]=「abc」であり、実際にはabcがメモリを割り当てる場所は上とは異なり、41990562293624から見ると、完全に2つの場所であり、4199056は定数領域にあり、2293624はスタック領域にあると推定される
229362822936242293620この出力は、3つのポインタが割り当てられた領域がスタック領域であり、高アドレスから低アドレスまでであることを示している.
2293620 4199056 abcコンパイラがc 3を定数領域に最適化する「abc」を見る
考え続けます:コード:出力:2293628 4199056 abc 2293624 2293624 abc 2293620 4012976 gbcを注釈に書くように、後で変更するとstrcpy(c 3、「abc」)が崩壊します.abcは別の場所で割り当てられており、変更可能であり、上記の参考ドキュメントの言い方とは必ずしも必ずしもそうではありません.
#include using namespace std;
main(){   char *c1 = "abc";   char c2[] = "abc";   char *c3 = ( char* )malloc(3);  //  *c3 = "abc"//error   strcpy(c3,"abc");   c3[0] = 'g';   printf("%d %d %s/n",&c1,c1,c1);   printf("%d %d %s/n",&c2,c2,c2);   printf("%d %d %s/n",&c3,c3,c3);   getchar();}