gpt4 book ai didi

c - 使用 strlen 并不总是一个好主意

转载 作者:行者123 更新时间:2023-11-30 21:47:22 26 4
gpt4 key购买 nike

我不确定我是否选择了正确的标题,但今天我发现(作为 C 初学者),对我来说,strlen 并不总是我需要时做出的正确决定。

所以我尝试了以下方法:

 #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;
}

输出:

False: C(10) > Len(5)

但是当我用“-Wconversion”编译时,我得到:

program.c:5:19: warning: conversion to ‘int’ from ‘size_t’ may alter its value [-Wconversion]
int len = strlen(s);
^

一个快速修复方法是强制转换 strlen:

int len = (int)strlen(s);

但我不同意,所以我决定我真的需要别的东西,也许另一种方法?我尝试了以下方法:

#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;
}

但我仍然需要强制转换 strlen,因为它的返回类型(size_t,我知道它是无符号类型(typedef long unsigned int size_t;))

最后我决定采用另一种方法,创建我自己的函数,这使事情变得更容易并且 future 可能出现的问题更少,我得到了:

#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;
}

不再需要 Actor 。

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

我只知道在某种程度上 Actor 可能会成为一个大问题。

编辑:此代码也无法使用 -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;
}

输出:

error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]|

但是如果我投 len 作品。我意识到,如果尺寸大于 int 它永远不会适合。

最佳答案

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

#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();
}

...您无法更改 slen 的类型或value ,因为对于它们接收结果的 API 来说,两者都是正确的。

-Wconversion warning 试图告诉你一些有意义的事情。 C 中有符号和无符号整数类型的比较会产生一些非常奇怪的结果,不是您从 中的算术定律中所期望的结果;像我上面写的那样的天真的比较可能并且已经导致了灾难性的错误。但治愈方法不是类型转换或发明自己的strlen ;解决方法是修复比较,使其达到您对算术定律的期望。其原则是:

  • 首先检查签名数量是否为负数。如果是,则将其视为小于无符号数量。
  • 否则,在比较它们之前,将较小类型转换为较大类型。

在本例中,size_t几乎肯定大于或等于 int ,所以你会写

#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();
}

static_assert存在是因为,如果我没记错的话,C 标准保证 size_t至少与unsigned int一样大。例如,我可以想象 80286 的 ABI,其中 int是四个字节宽,但是 size_t只有两个。在这种情况下,您需要以相反的方式进行转换:

void pick_foo_or_bar(unsigned short a, long b)
{
if (b < 0 || b < (long)a)
foo();
else
bar();
}

如果您不知道这两种类型中哪一个更大,或者您不知道其中哪一个有符号,则标准 C 中您唯一的资源是 (u)intmax_t :

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();
}
}

...而且,考虑到 C99 wrt long 设定的极其不幸的先例,可能有一天(u)intmax_t不是编译器支持的最大整数类型,那么你就完蛋了。

关于c - 使用 strlen 并不总是一个好主意,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32417194/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com