C 斯特伦并不总是一个好主意

C 斯特伦并不总是一个好主意,c,C,我不确定我是否选择了正确的标题,但今天我发现(作为C语言的初学者),对于我来说,斯特伦并不总是在我需要它的时候做出正确的决定 因此,我尝试了以下方法: #include<stdio.h> #include<string.h> int foo(char *s){ int len = strlen(s); /* code here */ return len; } int main(void){ char *name = "Mich

我不确定我是否选择了正确的标题,但今天我发现(作为C语言的初学者),对于我来说,斯特伦并不总是在我需要它的时候做出正确的决定

因此,我尝试了以下方法:

 #include<stdio.h>
 #include<string.h>

 int foo(char *s){
    int len = strlen(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    int len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%d)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%d)\n",c,len);
    }

    return 0;
}
#include<stdio.h>
#include<string.h>

unsigned int size(char *s){
    unsigned int len;
    /* code here */
    len = (unsigned int)strlen(s);

    return len;
}

int main(void){
    char *name = "Michi";
    unsigned int len = size(name);
    int a = 20, b = 10, c = a - b;

    if(c < (signed int)len){
        printf("True:  C(%d) < Len(%d)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%d)\n",c,len);
    }

    return 0;
}
一个快速解决方案是施特伦:

int len = (int)strlen(s);
但我不同意,所以我决定我真的需要其他东西,也许另一种方法? 我尝试了以下方法:

 #include<stdio.h>
 #include<string.h>

 int foo(char *s){
    int len = strlen(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    int len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%d)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%d)\n",c,len);
    }

    return 0;
}
#include<stdio.h>
#include<string.h>

unsigned int size(char *s){
    unsigned int len;
    /* code here */
    len = (unsigned int)strlen(s);

    return len;
}

int main(void){
    char *name = "Michi";
    unsigned int len = size(name);
    int a = 20, b = 10, c = a - b;

    if(c < (signed int)len){
        printf("True:  C(%d) < Len(%d)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%d)\n",c,len);
    }

    return 0;
}
#包括
#包括
无符号整数大小(字符*s){
无符号整数len;
/*代码在这里*/
len=(无符号整数)strlen(s);
回程透镜;
}
内部主(空){
char*name=“Michi”;
无符号整数长度=大小(名称);
INTA=20,b=10,c=a-b;
如果(c<(签名整数)len){
printf(“True:C(%d)Len(%d)\n”,C,Len);
}
返回0;
}
但是我仍然需要强制转换strlen,因为它的返回类型(size\t,我知道它是无符号类型(typedef long unsigned int size\t;))

最后,我决定采用另一种方法,创建我自己的函数,使事情变得更简单,未来可能出现的问题更少,我得到:

#include<stdio.h>

long int stringLEN(char *s){
    int i = 0;
    long int len = 0;

    while (s[i] != '\0'){
        len++;
        i++;
    }

    return len;
 }

 long int foo(char *s){
    long int len = stringLEN(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    long int len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%ld)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%ld)\n",c,len);
    }

    return 0;
}
#包括
长整型字符串(字符*s){
int i=0;
长整数len=0;
而(s[i]!='\0'){
len++;
i++;
}
回程透镜;
}
长整型foo(字符*s){
长整数长度=长整数长度;
/*代码在这里*/
回程透镜;
}
内部主(空){
char*name=“Michi”;
long int len=foo(名称);
INTA=20,b=10,c=a-b;
if(cLen(%ld)\n”,C,Len);
}
返回0;
}
不再需要石膏的地方

所以我的问题是: 这(对我来说)是更好的方法吗? 如果不是,我需要一些解释,我的书(我有3本)并没有以我能理解的方式来解释我

我只知道在某个时刻,演员阵容可能会成为一个大问题

编辑: 此代码也不会使用-Wconversion编译:

#include<stdio.h>
#include<string.h>

 size_t foo(char *s){
    size_t len = strlen(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    size_t len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%zu)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%zu)\n",c,len);
    }

    return 0;
}
#包括
#包括
大小\u t foo(字符*s){
尺寸长度=标准长度;
/*代码在这里*/
回程透镜;
}
内部主(空){
char*name=“Michi”;
大小\u t len=foo(名称);
INTA=20,b=10,c=a-b;
if(cLen(%zu)\n”,C,Len);
}
返回0;
}
输出:

错误:有符号和无符号整数表达式之间的比较[-Werror=符号比较]|


但是如果我投下的话,len会起作用。我意识到,如果大小大于int,它将永远不适合。

解决这个问题的正常方法是使用键入的变量
size\u t
,并选择适当的格式来打印它们。那么就不需要石膏了。有关printf,请参见以下内容:


字符串的长度永远不能为负,而整数可以为负-警告是因为
size\u t
的值范围不同于
int
,如果将
size\u t
的某些正值转换为
int
,则将被视为负值。更好的选择是让返回类型与函数匹配,在本例中,让
foo
返回一个
size\t
-您很快就会看到数据类型将允许大部分代码,并留下一些其他可能会做奇怪事情的异常(
size\t-size\t
可能会下溢…)

我认为不同的编译器之间一定存在差异……因为我在在线编译器上尝试了它,但没有显示任何警告

有两个问题:

  • strlen()
    返回类型
    size\t
    size\u t
    是一些无符号整数类型,可能与
    int
    一样宽或更宽。它依赖于编译器/平台

  • 代码需要比较并intsize\u t。由于
    size\u t
    是无符号的,为了防止出现有符号/无符号混合比较的警告,请将
    int
    显式更改为无符号整数。要将非负的
    int
    更改为无符号整数,请强制转换为
    (无符号)

  • 要进行比较,请测试
    c
    是否为负值,如果不是,则直接将
    (无符号)c
    len
    进行比较。编译器将根据需要转换类型,并生成算术正确的答案

    size\u t len=strlen(“SomeString”);
    int c=20;//一些智力
    如果(c<0 | |(无符号)c=len”);
    
    这将在没有警告的情况下编译:

     #include<stdio.h>
     #include<string.h>
    
     size_t foo(char *s){
        size_t len = strlen(s);
        /* code here */
        return len;
     }
    
    int main(void){
        char *name = "Michi";
        size_t len = foo(name);
        size_t a = 20, b = 10, c = a - b;
    
        if(c < len){
            printf("True:  C(%zu) < Len(%zu)\n",c,len);
        } else {
            printf("False:  C(%zu) > Len(%zu)\n",c,len);
        }
    
        return 0;
    }
    
    #包括
    #包括
    大小\u t foo(字符*s){
    尺寸长度=标准长度;
    /*代码在这里*/
    回程透镜;
    }
    内部主(空){
    char*name=“Michi”;
    大小\u t len=foo(名称);
    尺寸a=20,b=10,c=a-b;
    if(cLen(%zu)\n”,C,Len);
    }
    返回0;
    }
    
    正如@thomasdickey、@rolandshaw、@andreaghidini、@olaf、@juanchopanza和其他人在回答和评论中所解释的那样

    你真的采取了更好的方法吗?否:为什么stringlen函数要返回可能为负值的值?不存在大小为负的字符串


    标准strlen函数已经存在,效率更高,能够处理最大大小为stringLEN处理的最大大小两倍的字符串,并且对返回类型有更精确的定义。

    仔细研究所有其他答案,您真正的问题似乎是如何处理这样的情况:

    #include <string.h>
    #include <libfoo.h>
    
    extern void foo(void);
    extern void bar(void);
    
    void pick_foo_or_bar(const char *s)
    {
       size_t slen = strlen(s);
       int   value = libfoo_api_returning_an_int();
    
       if (slen > value) // -Wconversion warning on this line
          foo();
       else
          bar();
    }
    
    之所以存在
    静态断言
    ,是因为如果我没记错的话,C标准不能保证
    大小t
    至少与
    无符号整数
    一样大。例如,我可以想象80286的ABI,其中
    int
    是四个字节宽的b
    #include <assert.h>
    #include <limits.h>
    #include <string.h>
    #include <libfoo.h>
    
    extern void foo(void);
    extern void bar(void);
    
    // Code below is correct only if size_t is at least as large as int.
    static_assert(SIZE_MAX >= INT_MAX);
    
    void pick_foo_or_bar(const char *s)
    {
       size_t slen = strlen(s);
       int   value = libfoo_api_returning_an_int();
    
       if (value < 0 || (size_t)value < slen)
          foo();
       else
          bar();
    }
    
    void pick_foo_or_bar(unsigned short a, long b)
    {
        if (b < 0 || b < (long)a)
            foo();
        else
            bar();
    }
    
    void pick_foo_or_bar(uid_t a, gid_t b)
    {
        if (a < 0 && b < 0) {
            if ((intmax_t)a < (intmax_t)b)
                bar();
            else
                foo();
        } else if (a < 0) {
           bar();
        } else if (b < 0) {
            foo();
        } else {
            if ((uintmax_t)a < (uintmax_t)b)
                bar();
            else
                foo();
        }
     }