赋值使得整型指针没有强制转换

来自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);
  • 返回从指针没有转换的整数
    • 返回cString;

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

Cstring不像Javastring。 他们基本上是字符数组。

你正在得到错误,因为strToLower返回一个字符。 char是C中的一个整数forms。将它分配给一个char [],它是一个指针。 因此“将整数转换为指针”。

你的strToLower做了所有的改变,没有理由返回任何东西,特别是不是字符。 你应该“返回”无效或char *。

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

根据我的经验,C语言中的Strings是学习任何来自Java / C#背景C的人最难的部分。人们可以与内存分配相处(因为即使在Java中你也经常分配数组)。 如果你的最终目标是C ++而不是C,那么你可能更less关注Cstring,确保你理解了基础知识,而只是使用STL中的C ++string。

strToLower的返回types应该是char*不是char (或者它根本不应该返回任何东西,因为它不会重新分配string)

  • 1)不要使用gets ! 您正在引入缓冲区溢出漏洞。 改用fgets(..., stdin)

  • 2)在strToLower你正在返回一个char而不是一个chararrays。 要么返回char*作为Autopulatedbuild议,要么只是返回void因为无论如何你正在修改input。 因此,只写

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

正如其他人已经指出的那样,在一种情况下,您试图从被声明为返回一个char (这是一个整数)的函数返回cString (在这个上下文中是一个char *值 – 一个指针)。 在另一种情况下,你可以做相反的事情:你将一个char返回值赋给一个char *指针。 这是触发警告的原因。 你当然需要声明你的返回值为char * ,而不是char

注意,从语言的angular度来看,这些赋值事实上是约束违反 (即它们是“错误”),因为混合C中的指针和整数(除了整数常量零)是非法的。 你的编译器在这方面太简单了,把这些违规报告为“警告”。

我也想注意的是,在几个答案中,你可能会注意到相对奇怪的build议,从你的函数返回void ,因为你正在修改string就地。 虽然它肯定会起作用(因为你确实是在就地修改string),从函数返回相同的值没有任何问题。 实际上,在适用的情况下,这是一个相当标准的C语言实践(看一下像strcpy和其他标准函数),因为如果你select使用函数调用,它可以“链接”函数调用,如果你不要使用“链接”。

也就是说,在你的compareString实现中的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 *返回将派上用场)。 请记住,这样的“链接”函数调用有时难以用分步debugging器进行debugging。

作为一个额外的,未经实践的说明,我会说,以这种破坏性的方式(它修改inputstring)实现string比较函数可能不是最好的主意。 一个非破坏性的function在我看来会更有价值。 除了将inputstring显式转换为小写外,通常更好的办法是实现一个自定义逐个字符的不区分大小写的string比较函数,并使用它来代替调用标准的strcmp

你不需要这两个分配:

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

你正在修改string。

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

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

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

strToLower应该返回一个char *而不是char。 像这样的事情会做。

 char *strToLower(char *cString) 
 char cString1[] 

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

 char strToLower(...) 

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

 cString1 = strToLower(cString1); 

在赋值运算符的每一边有不同的types..实际上,将一个“char”(整数types)赋值给一个数组,这可以parsing为一个简单的指针。 由于C ++的隐式转换规则,这是有效的,但结果垃圾,进一​​步访问数组会导致未定义的行为。

解决办法是让strToLower返回char*