必ず覚えるべきC言語の古典的な練習問題

目次

演習 1: 1 次元配列 sizeof に関する関連計算

答え:

実行結果(エディタのバージョンはx64環境)

演習 2: 文字配列とライブラリ関数 strlen に関する関連計算

注: ライブラリ関数 strlen の概要

答え:


演習 1: 1 次元配列 sizeof に関する関連計算

int main()
{
//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//(一)
printf("%d\n",sizeof(a+0));//(二)
printf("%d\n",sizeof(*a));//(三)
printf("%d\n",sizeof(a+1));//(四)
printf("%d\n",sizeof(a[1]));//(五)
printf("%d\n",sizeof(&a));//(六)
printf("%d\n",sizeof(*&a));//(七)
printf("%d\n",sizeof(&a+1));//(八)
printf("%d\n",sizeof(&a[0]));//(九)
printf("%d\n",sizeof(&a[0]+1));//(十)
return 0;
}

注: 配列名について知っておくべき非常に重要なことが 2 つあります。

①:sizeof(配列名)、ここでの配列名は配列全体を表すので、配列全体のサイズが計算されます。

②: & 配列名。ここでの配列名は配列全体を表します。

③: 上記 2 つの場合を除き、それ以外の場合の配列名は先頭要素のアドレスを表します。

答え:

(1) は sizeof(a) で、 a は配列全体を表すため、答えは16 バイトになります。

(2) sizeof(a+0) について、多くのパートナーは a と a+0 が同じものではないと考えるかもしれません。実際には同じではありません。sizeof に配列名が 1 つしかない場合、配列全体のサイズが計算されます。ここでは、最初の要素のアドレス + 0 を表す a+0 が表示されます。結果は依然としてアドレスです。最初の要素なので、答えは4 または 8 バイト(x86 環境では 4、x64 環境では 8) になります。

(3) 上記 2 つの特殊なケースではなく、sizeof(*a) であるため、最初の要素の値を取得するための最初の要素のアドレス逆参照は次のとおりです。これは整数配列であるため、答えは 4 バイトです

(4)は(2)と同様にsizeof(a+1)で、第1要素のアドレス+1で第2要素のアドレスが得られます。アドレスサイズは4バイトまたは8バイトなので、答えは 4 バイトまたは 8 バイトです。

(5) sizeof(a[1]) ですが、これは明らかに 2 番目の要素なので、答えは4 バイトです。

                                                           a[n]=*(a+n)

(6) sizeof(&a) です。上記 2 つの特殊なケースを混同しないでください。ここで &a は配列全体のアドレスを取得しますが、配列のアドレスは依然としてアドレスではありませんか? アドレス サイズは 4 または8 バイトなので、答えは4 または 8 バイトです。

(7) sizeof(*&a) については、この質問について 2 つの考え方があります。

①: 演算子の観点から: * と & は互いに打ち消し合うことができるため、sizeof(*&a) は sizeof(a) と等価です。したがって、ここでの配列名 a は配列全体を表すため、答えは 16 バイトになります

②: 配列ポインタの観点から: &a は配列のアドレスを取得するので、配列ポインタに配置する必要があります。配列ポインタを逆参照すると何が得られますか? 整数ポインタを逆参照すると整数が得られ、文字ポインタを逆参照すると文字が得られることがわかっているため、配列ポインタを逆参照すると当然配列が得られるため、答えは 16 バイトになります

(8) は sizeof(&a+1) で、(6) と同様です。&a は配列全体のアドレスを受け取ります。アドレス + 1 は依然としてアドレスです。アドレス サイズは 4 または 8 バイトなので、答えは 4 です。または 8 バイト

(9) sizeof(&a[0]) です、&a[0] が最初の要素のアドレスであることは明らかで、アドレスのサイズは 4 または 8 バイトですので、答えは 4 または 8 バイトです

(10) は、(9) と同様に sizeof(&a[0]+1) です。&a[0] は最初の要素のアドレス、&a[0]+1 は 2 番目の要素のアドレスです。したがって、答えはは4 または 8 バイトです

実行結果(エディタのバージョンはx64環境)

これで最初の問題は終わりました。何問正解できますか?

演習 2: 文字配列とライブラリ関数 strlen に関する関連計算

#include<string.h>
#include<stdio.h>

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("(一):%d\n", strlen(arr));//(一)
	printf("(二):%d\n", strlen(arr + 0));//(二)
	printf("(三):%d\n", strlen(*arr));//(三)
	printf("(四):%d\n", strlen(arr[1]));//(四)
	printf("(五):%d\n", strlen(&arr));//(五)
	printf("(六):%d\n", strlen(&arr + 1));//(六)
	printf("(七):%d\n", strlen(&arr[0] + 1));//(七)
	return 0;
}

注: ライブラリ関数 strlen の概要

①: ライブラリ関数 strlen の機能は文字列の長さを計算することであり、パラメータには文字列の先頭アドレスが与えられます。

②: 計算規則: 文字列中の「\0」より前の文字数を数え、\0 が見つからない場合は逆算します。

③:関数宣言:

size_t strlen ( const char * str );

答え:

(1) は strlen(arr) で、 arr は最初の要素のアドレスを表しますが、文字配列の初期化にはさまざまな種類があります。たとえば、ユースケースの初期化など、多くのパートナーは答えが 6 であると考えるでしょうが、実際にはそうです。この初期化メソッドでは最後に '\0' が自動的に追加されないため、strlen は '\0' が見つかるまでカウントし続けるため、答えはランダムな値になります

(2)はstrlen(arr+0)で、arrは最初の要素のアドレスを表し、arr+0も最初の要素のアドレスを表すので、(1)と同様に答えもランダムな値になります

(3) strlen(*arr)こう思われる方も多いと思いますが、arr は先頭要素のアドレス、arr の逆参照は先頭要素、strlen は文字列の長さを求めるものなので、結果は 1 になります。s trlen 関数の宣言の仮パラメータは「const char* str」であることに気付きます。これは、渡す必要がある実際のパラメータは、長さが次の文字列の最初のアドレスであることを意味しますしたがって、最初の要素を strlen に渡すと、つまり、文字 'a' が strlen に渡され、文字 'a' の ASCII コードは 97 であるため、文字 'a' が strlen に渡された場合、 , strlen は '97' をアドレス 00 00 00 97 としてカウントしますが、この空間は私たちのものではないため、メモリへの不正アクセスの問題があるためこの書き方は間違っています

(4) は strlen(arr[1]) ですが、この書き方は (3) と似ていますが、 strlen に文字'b' を渡しているため、メモリ不正アクセスの問題がありこの書き方は間違っています

(5) は strlen(&arr) で、&arr は配列全体のアドレスを受け取り、配列のアドレスは配列の最初の要素のアドレスと同じであるため、strlen は最初の要素からカウントを開始して ' \0' が見つかったので、状況はランダムな値の場合の (1) と同じになります

(6) strlen(&arr+1) です。多くのパートナーは、&arr+1 が 2 番目の要素のアドレスであると考えています。実際にはそうではありません。まず、&arr は配列のアドレスを受け取り、そして配列のアドレスは配列ポインタに配置する必要があります。内部では、ポインタの型によってポインタ逆参照のアクセス権と、整数の加算または減算時にスキップできるステップが決定されることもわかっています。整数逆参照は整数と整数ポインタにアクセスします。 +1 は整数のスペースをスキップします (4 ワード セクション)。同じ原則がここにも当てはまります。配列ポインタ +1 は配列スペースをスキップするため、strlen は配列の末尾、つまり後ろのスペースからカウントを開始します。文字 'f'。いつ '\ 0' に遭遇するかわからないため、結果もランダムな値になります

(7) これは strlen(&arr[0]+1) です。ここで、&arr[0] は最初の要素のアドレスを受け取るため、文字ポインターによって受信されます。そのため、文字ポインター +1 は 1 バイトのみスキップします。したがって、&arr [0 ]+1 は 2 番目の要素のアドレスにアクセスしますが、いつ '\0' に遭遇するかはまだわからないため、結果もランダムな値になります

この知識はここにあり、編集者は今後も更新し続けます。

おすすめ

転載: blog.csdn.net/hffh123/article/details/132279621