2

K&R を使用していますが、配列名は変数ではなく、a=pa や a++ などの構造では使用できないと表示されます。

sここに配列名はありませんか?

    #include<stdio.h>
    main(){
        printf("%d", strlen("test"));
    }

    int strlen(char s[])
    {
        int n;
        for (n = 0; *s!= '\0';s++) // why is s++ valid even though it is declared as an array
            n++;
        return n;
    }
4

4 に答える 4

3

馬の口から:

6.3.2.1 左辺値、配列、および関数指定子

... 3演算子、演算子、または単項演算子
のオペランドである場合、または配列の初期化に使用される文字列リテラルである場合を除き、 ''の配列'' 型を持つ式は式に変換されます配列オブジェクトの最初の要素を指し、左辺値ではない「型へのポインター」を使用します。配列オブジェクトに ストレージ クラスがある場合、動作は未定義です。 sizeof_Alignof&register

"test"は文字列リテラルで、型は「5 要素配列char」です。"test"のパラメータとしてを渡す場合strlen、上記の規則により、実際に渡されるのはポインタであり、その値は の最初の文字のアドレスです"test"

それは私たちに...

6.7.6.3 関数宣言子 (プロトタイプを含む)

... 7 「
の配列」としてのパラメーターの宣言は、「への修飾ポインター」に調整されるものとします 。ここで、型修飾子 (存在する場合) は、配列型派生の and ]内で指定されたものです。 . キーワードが配列型派生のand内にも現れる場合、関数の呼び出しごとに、対応する実引数の値によって、少なくともサイズで指定された数の要素を持つ配列の最初の要素へのアクセスが提供されます。表現。 [static[]

したがって、 のプロトタイプではstrlen、は;char s[]と同等です。の配列ではなく、へのポインタとして宣言されています。 char *sscharchar

C の配列の扱いは、他の言語に比べて少しバロック的です。これは、一部には BCPL と B の遺産によるものです。その理由に興味がある場合は、dmr のThe Development of the C Languageを読んで洞察を得ることができます。

于 2012-09-15T13:52:44.247 に答える
3

いいえ、この文脈では へのポインタcharです。関数宣言は、次のものと完全に同等です。

int strlen(char *s)

ご覧のとおり、配列を関数に渡すことは実際には不可能です。最初の要素へのポインターが実際に渡されます。

したがって、sは実際には配列ではなくポインターであるため、自由に変更できます。

于 2012-09-15T06:32:22.443 に答える
1

Char s[]={...} が宣言されている場合、アドレスは s にアタッチされ、(定数ポインターのように) 決して変更されず、このプロパティを変更しようとすると、s++ などの不正な操作になります。

しかし、関数呼び出しint strlen(char s[])では、配列がポインターとして渡されます。

于 2012-09-15T06:58:48.847 に答える
1

いいえ、実際sにはポインター名です。宣言int strlen(char s[])は以下と同じint strlen(char *s)

于 2012-09-15T06:34:36.540 に答える