web-dev-qa-db-ja.com

代入は、キャストなしで整数からポインターを作成します

Javaバックグラウンドから来ていますが、私はCを学習していますが、これらの曖昧なコンパイラーのエラーメッセージはますますイライラしています。私のコードは次のとおりです。

/*
 * PURPOSE
 *      Do case-insensetive string comparison.
 */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int compareString(char cString1[], char cString2[]);
char strToLower(char cString[]);

int main() {
    // Declarations
    char cString1[50], cString2[50];
    int isEqual;

    // Input
    puts("Enter string 1: ");
    gets(cString1);
    puts("Enter string 2: ");
    gets(cString2);

    // Call
    isEqual = compareString(cString1, cString2);
    if (isEqual == 0)
        printf("Equal!\n");
    else
        printf("Not equal!\n");

    return 0;
}

// WATCH OUT
//      This method *will* modify its input arrays.
int compareString(char cString1[], char cString2[]) {
    // To lowercase
    cString1 = strToLower(cString1);
    cString2 = strToLower(cString2);

    // Do regular strcmp
    return strcmp(cString1, cString2);
}

// WATCH OUT
//      This method *will* modify its input arrays.
char strToLower(char cString[]) {
    // Declarations
    int iTeller;

    for (iTeller = 0; cString[iTeller] != '\0'; iTeller++)
        cString[iTeller] = (char)tolower(cString[iTeller]);

    return cString;
}

これにより、2つの警告が生成されます。

  • 代入は、キャストなしの整数からポインターを作成します
    • cString1 = strToLower(cString1);
    • cString2 = strToLower(cString2);
  • returnは、キャストなしでポインターから整数を作成します
    • return cString;

誰かがこれらの警告を説明できますか?

22
Pieter

C文字列は、Java文字列のようなものではありません。本質的に文字の配列です。

StrToLowerが文字を返すため、エラーが発生します。 charはCの整数の形式です。ポインタであるchar []に割り当てています。したがって、「整数からポインターへの変換」。

StrToLowerはすべての変更をその場で行います。特にcharではなく、何かを返す理由はありません。 voidまたはchar *を「返す」必要があります。

StrToLowerの呼び出しでは、割り当ての必要もありません。基本的にcString1のメモリアドレスを渡すだけです。

私の経験では、Cの文字列は、Java/C#バックグラウンドからCに戻ってくる人にとって学ぶのが最も難しい部分です。人々はメモリの割り当てに慣れることができます(Java )。最終的な目標がCではなくC++である場合は、C文字列にあまり注意を向けず、基本を理解し、STLのC++文字列を使用することをお勧めします。

37
Uri

strToLowerの戻り値の型はchar* not char(または、文字列を再割り当てしないため、何も返さないはずです)

5
James

他の人が既に指摘したように、ある場合には、cString(を返すように宣言された関数からchar(このコンテキストではchar *値-ポインター)を返そうとしています。これは整数です)。別のケースでは、逆の操作を行います。char戻り値をchar *ポインターに割り当てます。これが警告をトリガーします。戻り値をcharではなくchar *として宣言する必要があります。

ところで、これらの割り当ては実際には言語の観点から制約違反(つまり、「エラー」)であることに注意してください。ゼロ)。あなたのコンパイラは、この点に関して単純に寛容すぎており、これらの違反を単なる「警告」として報告しています。

また、いくつかの答えでは、文字列をインプレースで変更しているため、関数からvoidを返すという比較的奇妙な提案に気付くかもしれないということです。確かに機能しますが(実際に文字列をその場で変更しているので)、関数から同じ値を返すことは本当に悪いことではありません。実際、C言語では、使用することを選択した場合に関数呼び出しの「連鎖」を可能にし、コストがかかるため、該当する場合はstrcpyなどの標準関数を見てください。 「連鎖」を使用しない場合、実質的には何もありません。

そうは言っても、compareStringの実装内の割り当ては、完全に余分なものに見えます(それらが何も壊さないとしても)。私はそれらを取り除くか

int compareString(char cString1[], char cString2[]) { 
    // To lowercase 
    strToLower(cString1); 
    strToLower(cString2); 

    // Do regular strcmp 
    return strcmp(cString1, cString2); 
} 

または「連鎖」を使用して

int compareString(char cString1[], char cString2[]) { 
    return strcmp(strToLower(cString1), strToLower(cString2)); 
} 

(これはchar *のリターンが便利になるときです)。このような「連鎖」関数呼び出しは、ステップバイステップデバッガーではデバッグが難しい場合があることに注意してください。

追加の非現実的なメモとして、このような破壊的な方法で文字列比較関数を実装すること(つまりmodifies入力文字列)は、最良のアイデアではないかもしれません。私の意見では、非破壊機能ははるかに価値があります。入力文字列を小文字に明示的に変換する代わりに、通常、大文字と小文字を区別しないカスタム文字列比較関数を実装し、標準のstrcmpを呼び出す代わりに使用することをお勧めします。

2
AnT
  • 1)getsを使用しないでください!バッファオーバーフローの脆弱性を導入しています。代わりにfgets(..., stdin)を使用してください。

  • 2)strToLowerでは、char- arrayではなく、charを返します。 char* Autopulatedが示唆したように、またはとにかく入力を変更しているので、単にvoidを返します。結果として、ただ書く

 strToLower(cString1);
 strToLower(cString2);
  • 3)大文字と小文字を区別しない文字列を比較するには、strcasecmp(LinuxおよびMac)またはstricmp(Windows)を使用できます。
1
kennytm

次の2つの割り当ては必要ありません。

cString1 = strToLower(cString1); 
cString2 = strToLower(cString2);

所定の場所で文字列を変更します。

警告は、charを返し、char [](char *と同等)に割り当てているためです。

0
Ariel

配列の最初の文字へのポインタであるchar *ではなく、charを返しています。

インプレース変更を行う代わりに新しい文字配列を返したい場合は、パラメータとして割り当て済みのポインタ(char *)または初期化されていないポインタを要求できます。この最後のケースでは、新しい文字列に適切な数の文字を割り当てる必要があります。Cパラメーターでは、常に値によって渡されるため、関数によって内部的に割り当てられた配列の場合はchar **をパラメーターとして使用する必要があります。もちろん、呼び出し元は後でそのポインターを解放する必要があります。

0
Hernán

strToLowerは、charではなくchar *を返す必要があります。このような何かがするだろう。

char *strToLower(char *cString)
0
Suresh Krishnan