0

私は K&R を読んでいて、ポインターに関する章をほぼ読み終えました。それらを正しい方法で使用しようとしているかどうかは完全にはわかりません。ポインターを使用して itoa(n) を実装してみることにしました。私が行った方法に明らかに間違っていることはありますか?何かを行うために文字列バッファーとして機能する大きな配列を取っておく必要があることは特に好きではありませんが、それが実際にCで正しい方法であるかどうかはわかりません.

コードでポインターを使用することを決定する際に従うべき一般的なガイドラインはありますか? 以下のコードで改善できる点はありますか? 静的文字列バッファーなしで文字列を操作する方法はありますか?

/*Source file: String Functions*/
#include <stdio.h>

static char stringBuffer[500];
static char *strPtr = stringBuffer;

/* Algorithm: n % 10^(n+1) / 10^(n) */
char *intToString(int n){
    int p = 1;
    int i = 0;

    while(n/p != 0)
        p*=10, i++;

    for(;p != 1; p/=10)
       *(strPtr++) = ((n % p)/(p/10)) + '0';  
    *strPtr++ = '\0';

    return strPtr - i - 1;
}

int main(){
    char *s[3] = {intToString(123), intToString(456), intToString(78910)};
    printf("%s\n",s[2]);
    int x = stringToInteger(s[2]);

    printf("%d\n", x);

    return 0;
}

最後に、誰かが配列とポインタの違いを明確にしてくれますか? K&R には、私が非常に混乱しているセクションがあります。「5.5 - 文字ポインターと関数。」ここに引用します:

「定義には重要な違いがあります。

char amessage[] = "now is the time"; /*an array*/
char *pmessage = "now is the time"; /*a pointer*/

amessage は配列で、一連の文字とそれを初期化する '\0' を保持するのに十分な大きさです。配列内の個々の文字は変更される場合がありますが、メッセージは常に同じストレージを参照します。一方、pmessage はポインターであり、文字列定数を指すように初期化されます。その後、ポインターは別の場所を指すように変更される可能性がありますが、文字列の内容を変更しようとした場合の結果は未定義です。」

それは一体何の意味ですか?

4

5 に答える 5

1

最後の質問について:

char amessage[] = "now is the time";- 配列です。配列は、(ポインタとは異なり) 他のものを指すように再割り当てすることはできません。メモリ内の固定アドレスを指します。配列がブロックに割り当てられた場合、ブロックの最後でクリーンアップされます (つまり、関数からそのような配列を返すことはできません)。ただし、配列のサイズを超えない限り、配列内のデータを好きなだけいじることができます。

たとえば、これは合法ですamessage[0] = 'N';

char *pmessage = "now is the time";- はポインターです。ポインタはメモリ内のブロックを指すだけです。"now is the time"文字列リテラルです。つまり、実行可能ファイル内の読み取り専用の場所に格納されます。どのような状況でも、それが指しているデータを変更することはできません。ただし、ポインターを別のものを指すように再割り当てすることはできます。

これは正当ではありません - *pmessage = 'N';- おそらく segfault になります (ポインターで配列構文を使用できることに注意してください。*pmessageは と同等ですpmessage[0])。

-Sフラグを使用して gcc でコンパイルすると、実際"now is the time"にはアセンブリ実行可能ファイルの読み取り専用部分に格納されていることがわかります。

指摘すべきもう 1 つのことは、関数に引数として渡されると、配列がポインターに減衰することです。次の 2 つの宣言は同等です。

void foo(char arr[]);

void foo(char* arr);

于 2013-06-17T03:13:48.953 に答える
0

ポインタの使い方や配列とポインタの違いについては「エキスパートCプログラミング」( http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298/ref= sr_1_1?ie=UTF8&qid=1371439251&sr=8-1&keywords=expert+c+programming )。

于 2013-06-17T03:21:33.663 に答える
0

関数から文字列を返すより良い方法は、(malloc を使用して) 動的メモリを割り当て、必要な文字列で埋めることです...このポインタを呼び出し元の関数に返してから解放します。

サンプルコード:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#define MAX_NAME_SIZE 20

char * func1()
{
    char * c1= NULL;
    c1 = (char*)malloc(sizeof(MAX_NAME_SIZE));
    strcpy(c1,"John");
    return c1;
}

main()
{
    char * c2 = NULL;
    c2 = func1();
    printf("%s \n",c2);
    free(c2);
}

そして、これは静的文字列なしで機能します。

于 2013-06-17T05:42:08.903 に答える