繁体   English   中英

在 C 中传递空字符串 ("") 是不好的做法吗?

[英]Is passing empty strings ("") in C bad practice?

在我们将 Visual Studio 更新到 2017 版后,我正在尝试修复最近在 Windows 上出现的非常旧的 C 代码中的一个错误。该代码仍可在多个 Linux 平台上运行。 这告诉我我们可能依赖于一些未定义的行为,而且我们之前很幸运。

我们有一堆这样的函数调用:

get_some_data(parent, "ge", "", type);

在调试中运行时,我注意到在进入该函数时,在该函数执行任何操作之前,该空字符串立即被垃圾填满。 函数声明如下:

static void get_some_data(
KEY  Parent,
char *Prefix,
char *Suffix,
ENT  EntType)

那么直接传递字符串(“ge”,“”)是不明智的吗? 我知道通过声明 char *suffix="" 并传递后缀而不是 "" 来解决这个问题很简单,但我现在怀疑我是否需要通过整个代码套件来寻找这种类型的函数调用。

那么直接传递字符串(“ge”,“”)是不明智的吗?

一般来说,将字符串文字传递给函数并没有本质上的错误。

但是,将指向字符串文字的指针(传入)专门传递给声明为指向非const字符的指针的参数是不明智的,因为 C 指定尝试修改字符串文字会导致未定义行为,并且在实践中,UB 通常表现为程序突然终止。 如果一个函数将一个参数声明为const char *那么您可以合理地将其视为它不会尝试修改该指针的目标的承诺——这是您需要确保的——但是如果它声明一个参数只是char *那么没有这样的承诺,并且该函数甚至没有办法在运行时检查参数是否可写。

可能你可以依靠文档来代替const限定,因为在这方面你没问题,只要在实践中没有尝试修改字符串文字,但这仍然会让你更容易受到错误的影响,否则你会这样做.

我知道通过声明 char *suffix="" 并传递后缀而不是 "" 来解决这个问题是微不足道的

这样的更改可能会掩盖编译器正在执行的操作,因此它不会发出有关函数调用的警告,但不会修复任何内容 相同的指针值以任何一种方式传递给函数,并且应用相同的语义和约束。 此外,如果编译器警告函数调用,那么它也应该警告赋值。

顺便说一下,这在 C++ 中不是问题,或者至少不是同一个问题,因为在 C++ 中,字符串文字首先表示const char数组。

,但我现在怀疑我是否需要通过整个代码套件来寻找这种类型的函数调用。

更好的方法是修改被调用函数的签名。 如果您打算传递字符串文字是可以的,请确保参数的类型为const char * ,如下所示:

static void get_some_data(
KEY  Parent,
const char *Prefix,
const char *Suffix,
ENT  EntType)

但请注意,这很可能会导致有关违反常量正确性的新警告。 为了确保安全,您还需要修复这些问题,而不要丢弃const ness 这可以广泛地级联,但该练习肯定会帮助您识别和修复您的代码错误处理字符串文字的地方。

另一方面,一个可能不太普遍的真正修复是将指针传递给可修改的数组,而不是(不可修改的)字符串文字。 也许这就是您提出的修复方案的想法,但正确的方法是:

char prefix[] = "ge";
char suffix[] = "";

get_some_data(parent, prefix, suffix, type);

在这里, prefixsuffix是单独的(可修改的)本地数组,使用字符串文字内容的副本进行初始化。


尽管如此,我倾向于怀疑,如果您使用 VS 编译的可执行文件而不是 GCC 编译的可执行文件遇到与这些参数相关的真正运行时错误,那么这些错误的来源可能是其他原因。 我的第一个猜测是数组边界被超限了。 我的第二个猜测是,您正在将 C 代码编译为 C++,并且与它们之间的一个或多个(其他)差异发生冲突。

这并不是说您不应该仔细研究这里涉及的const性/可写性问题,但是如果仅仅通过整个练习就发现您可以开始,那就太糟糕了。 你仍然可以得到更好的代码,但是当老板问为什么这个错误还没有被修复时,把它卖给老板有点棘手。

不,传递字符串文字绝对没有错,无论是否为空。 恰恰相反——如果你试图通过做一些微不足道的改变来“修复”你的代码,你就会隐藏错误,并使将来修复它的人更难。

我遇到了同样的问题,原因是最近执行的函数中出现了类似的情况,其中至关重要的是,字符串的内容正在被更改。

在观察到这种奇怪行为的调用之前,有一个对带有 PSTR 类型参数的旧代码的调用。 程序员没有意识到该参数的内容将被更改,而是提供了一个空字符串。 代码只更新第一个字符,因此声明一个 char 类型参数并提供它的地址足以解决后来调用中出现的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM