【问题标题】:Assignment makes pointer from integer without cast赋值使指针从整数而不强制转换
【发布时间】:2011-01-05 15:37:34
【问题描述】:

我有 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;
}

这会产生两个警告。

  • 赋值使指针从整数不进行强制转换
    • cString1 = strToLower(cString1);
    • cString2 = strToLower(cString2);
  • return 从没有强制转换的指针中生成整数
    • 返回 cString;

有人可以解释这些警告吗?

【问题讨论】:

    标签: c warnings


    【解决方案1】:

    正如其他人已经指出的那样,在一种情况下,您试图从声明为返回 char(这是一个整数)。在另一种情况下,您执行相反的操作:您将 char 返回值分配给 char * 指针。这就是触发警告的原因。您当然需要将返回值声明为char *,而不是char

    注意顺便说一句,从语言的角度来看,这些赋值实际上是违反约束(即它们是“错误”),因为在 C 中混合指针和整数是非法的(除了从积分常数零)。您的编译器在这方面过于宽容,并将这些违规行为仅报告为“警告”。

    我还想指出的是,在几个答案中,您可能会注意到从函数返回 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 * 返回会派上用场)。请记住,这种“链式”函数调用有时很难使用逐步调试器进行调试。

    作为一个额外的、不真实的说明,我想说以这种破坏性的方式实现一个字符串比较函数(它修改输入字符串)可能不是最好的主意。在我看来,非破坏性功能将具有更大的价值。与其将输入字符串显式转换为小写,不如实现一个自定义的逐字符不区分大小写的字符串比较函数并使用它而不是调用标准的strcmp,这通常是一个更好的主意。

    【讨论】:

      【解决方案2】:

      C 字符串与 Java 字符串不同。它们本质上是字符数组。

      您收到错误是因为 strToLower 返回一个字符。 char 是 C 中的一种整数形式。您将其分配给 char[] ,它是一个指针。因此“将整数转换为指针”。

      您的 strToLower 进行了所有更改,没有理由返回任何内容,尤其是不返回字符。您应该“返回” void 或 char*。

      在调用 strToLower 时,也不需要赋值,您实际上只是传递了 cString1 的内存地址。

      根据我的经验,对于从 Java/C# 背景回到 C 的任何人来说,C 中的字符串是最难学习的部分。人们可以与内存分配相处融洽(因为即使在 Java 中您也经常分配数组)。如果您的最终目标是 C++ 而不是 C,您可能更愿意较少关注 C 字符串,确保您了解基础知识,并且只使用来自 STL 的 C++ 字符串。

      【讨论】:

      • 这并没有直接解决你的问题——它是一个间接的解决方案:D消除编译器警告自动的答案更贴切:D
      • 好的,在这里澄清了答案。
      • 感谢您的简单陈述,您为我提供了正确的信息级别 - 来自另一个 Java 思考者
      【解决方案3】:

      strToLower 的返回类型应该是char* 而不是char (或者它应该什么都不返回,因为它不会重新分配字符串)

      【讨论】:

      • (+1, 几乎 -1 =D ) 你的意思是改变返回类型.....它返回 char * ,但是这与返回类型冲突......
      【解决方案4】:

      strToLower 应该返回一个 char * 而不是一个 char。像这样就可以了。

      char *strToLower(char *cString)
      

      【讨论】:

        【解决方案5】:

        您返回的是 char,而不是 char*,它是指向数组第一个字符的指针。

        如果你想返回一个新的字符数组而不是进行就地修改,你可以要求一个已经分配的指针 (char*) 作为参数或一个未初始化的指针。在最后一种情况下,您必须为新字符串分配适当数量的字符,并记住在 C 参数中始终按值传递,因此在函数内部分配的数组的情况下,您必须使用 char** 作为参数。当然,调用者必须稍后释放该指针。

        【讨论】:

          【解决方案6】:
          char cString1[]
          

          这是一个数组,即指向同一数据类型的一系列元素的第一个元素的指针。请注意,您不是按值传递数组,而是按指针传递。

          char strToLower(...)
          

          但是,这会返回一个字符。所以你的任务

          cString1 = strToLower(cString1);
          

          在赋值运算符的每一侧都有不同的类型。你实际上是在将一个“char”(整数排序)分配给一个数组,它解析为一个简单的指针。由于 C++ 的隐式转换规则,这是可行的,但结果 垃圾,进一​​步访问数组会导致未定义的行为。

          解决办法是让strToLower返回char*

          【讨论】:

            【解决方案7】:

            你不需要这两个任务:

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

            您正在就地修改字符串。

            警告是因为您正在返回一个 char,并分配给一个 char[](相当于 char*)

            【讨论】:

              【解决方案8】:
              • 1) 不要使用gets!您正在引入缓冲区溢出漏洞。请改用fgets(..., stdin)

              • 2) 在strToLower 中,您返回的是char,而不是char 数组。要么按照 Autopulated 的建议返回 char*,要么只返回 void,因为无论如何您都在修改输入。结果,就写

               

               strToLower(cString1);
               strToLower(cString2);
              
              • 3) 要比较不区分大小写的字符串,您可以使用strcasecmp(Linux 和 Mac)或stricmp(Windows)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2017-05-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-10-19
                • 2013-09-14
                相关资源
                最近更新 更多