作为文本指针的 C/C++ 覆盖函数参数

C/C++ overwriting function argument that is a text pointer

提问人:Ingo 提问时间:8/19/2023 最后编辑:Ingo 更新时间:8/19/2023 访问量:75

问:

我发现了这个结构,我不确定它是否有效。

#include <iostream>
#define DEFAULT_TEXT "hello world"

void print_text(const char* custom_text) {

    if(!custom_text) {
        custom_text = DEFAULT_TEXT;
    }

    std::cout << custom_text << std::endl;
}

int main() {
    print_text(nullptr);
    return 0;
}

这编译时没有错误,其输出为“hello world”,正如预期的那样。

函数参数是包含指针的变量。通过调用该函数,它包含一个 nullptr。在函数中,参数变量被指向默认文本“hello world”的指针覆盖。它由预处理器宏定义,并在 if 语句中展开,该语句在 if 块中具有有限的范围。

这是一个有效的稳定结构吗?“hello world”的终止 null 字符是怎么回事?我必须添加一个吗?

C++ 函数 参数

评论

1赞 Thomas Matthews 8/19/2023
恕我直言,不是一个有效的稳定结构。如果参数由函数修改,则使用“按引用传递”,如果函数不修改参数,则使用“引用传递”。如果使用 ,则不需要终止 nul 字符。std::stringconststd::string
1赞 John Bollinger 8/19/2023
C 字符串文本表示以 null 结尾的数组。无需添加额外的 nul 字节,也无需担心可能会丢失一个字节。或者另一方面,是的,需要 nul 终止才能通过 打印它。cout.<<
1赞 Keith Thompson 8/19/2023
您不需要宏定义中的 。它碰巧不会像您使用它的方式那样引起问题,但它可能会导致语法错误或更糟。;
2赞 Eljay 8/19/2023
是的,它是一个有效的稳定结构。编译器生成的终止 null 字符是必需的。(我不知道你会如何压制它。决赛不应该在那里。没有理由使用 ,而是使用 来避免流正在做的额外工作。如果可能的话,我建议避免使用宏,在这种情况下是可能的。;#definestd::endl"\n"
0赞 Ingo 8/19/2023
@Eljay稳定还是不稳定,是否需要空字符,这就是问题所在。什么评论是对的?

答:

2赞 Keith Thompson 8/19/2023 #1

是的,它是有效的(尽管在某些方面不是很好的风格)。

custom_text是一个参数,这使它成为函数内部的局部变量。使用调用中相应参数的值初始化参数(在本例中为 )。print_text()nullptr

函数可以自由更改其任何局部变量的值。

C 样式字符串包含终止 null 字符 。您无需担心它,因为它隐含在字符串文字中。'\0'"hello world"

使用它可能比原始 C 样式字符串更好,但 C++ 处理 C 样式字符串没有太多问题。std::string

您还可以使用默认参数值定义函数,而不是将该逻辑写入函数的主体中。

您应该更改的一件事是删除宏定义中的分号。分号成为宏扩展的一部分,因此您的语句

custom_text = DEFAULT_TEXT;

成为

custom_text = "hello world";;

在这种情况下,额外的分号不会导致任何问题,但在其他上下文中可能会导致语法错误或更糟。宏的扩展应该是一个有效的表达式。(宏可以扩展到其他内容,但表达式可能是最常见的情况。

评论

0赞 Eljay 8/19/2023
您还可以使用默认参数值定义函数,而不是将该逻辑写入函数的主体中。但是,如果调用者可以传入(作为 OP 代码中的文字,或通过变量),那么就会发生坏事。nullptr
0赞 Ingo 8/19/2023
悬空指针仍然存在问题,但 Ben Voigt 已经在评论中回答了这个问题。这不是我的构造。我只是因为不确定是否应该修复它而问。
1赞 Keith Thompson 8/19/2023
@Eljay 是的,所以函数应该识别一个参数,或者文档应该说它需要一个非空指针。使用默认参数时,示例中的调用将是 。nullptrprint_text();
1赞 Vlad from Moscow 8/19/2023 #2

In fact the function looks the following way

void print_text(const char* custom_text) {

    if(!custom_text) {
        custom_text = "hello world";
    }

    std::cout << custom_text << std::endl;
}

There is nothing wrong with the function.

String lietarls have static storage duration and types of constant character arrays

That is in memory the string literal is stored similarly to the character array"hello world"

static char hello_world[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', \0' };

评论

0赞 Ben Voigt 8/19/2023
"String literals have static storage duration" is true and important to OP, but I don't think he knows how that affects his code.
1赞 ABaumstumpf 8/19/2023 #3

I think the biggest source of confusion is the parameter-type it self:

void print_text(const char* custom_text)

const is a bit special with to which thing it belongs: This is a function called "print_text" that takes a pointer to a constant . It is not the pointer that is constant but the value pointed too that is not allowed to be changed. (there is the whole east-const vs west-const). So you are allowed to change were points to, as in changing it from pointing to a nullptr to point towards some string-literal, but you would not be allowed to change the content of what it is pointing at (and you can't change the content of string-literals to begin with).charcustom_text