web-dev-qa-db-ja.com

文字列へのポインタをprintfで使用できますか?

私は次のようなものを考えています:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

int main(void) {
    //test pointer to string
    char s[50];
    char *ptr=s;
    printf("\nEnter string (s): ");
    fgets(s, 50, stdin);
    printf("S: %s\nPTR: %s\n", s, *ptr);

    system("PAUSE");
    return 0;
}

または、*(s + i)と書式指定子%cでforループを使用する必要がありますか?それは、ポインターと単純なprintfを介して文字列を印刷する唯一の方法ですか?

更新:printfは配列の最初の要素のアドレスで動作するため、* ptrを使用すると、実際にはアドレスではなく最初の要素で動作します。ありがとう。

19
andreihondrari

printfalways"%s"形式指定子は、char*引数を必要とします。

与えられた:

char s[] = "hello";
char *p = "world";
printf("%s, %s\n", s, p);

it looks最初の%sの配列と2番目のポインターを渡すようですが、実際には両方にポインターを(正しく)渡します。

Cでは、配列型の式は暗黙的に配列の最初の要素へのポインタに変換されますnless次の3つのコンテキストのいずれかにあります。

  • 単項「&」(アドレス)演算子の引数です
  • 単項「sizeof」演算子の引数です
  • これは、配列オブジェクトを初期化するために使用される初期化子の文字列リテラルです。

(C++には1つまたは2つの例外があると思います。)

printf()の実装は、"%s"を参照し、対応する引数がcharへのポインターであると想定し、そのポインターを使用して文字列を走査して出力します。

comp.lang.c FAQ のセクション6には、これに関する優れた議論があります。

34
Keith Thompson
_printf("%s\n", ptr);
_

これは、あなたの望むことですか?

ところで、 printf(3) から、ここにs変換指定子(つまり_%s_)のドキュメントがあります:

L修飾子が存在しない場合:const char *引数は、文字型の配列へのポインター(文字列へのポインター)であることが期待されます。配列の文字は、終端のヌルバイト(「\ 0」)まで(ただし、含まれません)書き込まれます。精度が指定されている場合、指定された数以下が書き込まれます。精度が指定されている場合、nullバイトが存在する必要はありません。精度が指定されていない場合、または配列のサイズより大きい場合、配列には終端のヌルバイトが含まれている必要があります。

7
Bertrand Marron

"printf(" S:%s\nPTR:%s\n "、s、ptr);"の代わりにprintf( "S:%s\nPTR:%s\n"、s、* ptr);

ptrと* ptrの違いは次のとおりです。ptrは、ポイントしている変数のメモリ内のaddressを提供し、* ptrはポイントされた変数の値この場合、* ptr = ptr [0]

このコードは私が意味することを示します:

printf("\tS: %s\n\tPTR: %s\n\tAddress of the pointed Value: %x\n\tValue of the whole String: %s\n\tValue of the first character of the String: %c\n", s, ptr,ptr,ptr,*ptr);
1
arthur

私の経験では、* sで%sディレクティブを使用しようとすると、セグメンテーション違反が発生するはずです。

0
MAIGA