指针初始化字符串文字
Pointer initialization string literals
假设我有一个需要调用几次的函数,该函数将字符串文字作为其第一个也是唯一一个参数。像这样:
func( "things_i_like\turtles\fresh_water" );
/* some code */
if ( turtleFred.mood == happy )
{
func( "things_i_like\turtles\fresh_water" );
}
/* more code */
func( "things_i_like\turtles\fresh_water" );
现在,如果我需要更改该字符串文字,我将不得不在 3 个不同的地方进行更改。如果我在更改其中一个字符串文字时输入错误,可能会发生一些不好的事情。为避免这种情况,我可以使用变量来存储字符串文字的位置。像这样:
const char* turtlesPath = "things_i_like\turtles\fresh_water";
func( turtlesPath );
/* some code */
if ( turtleFred.mood == happy )
{
func( turtlesPath );
}
/* more code */
func( turtlesPath );
这种方法有 3 个问题。让我们假设我有大约 20-30 而不是一个字符串文字。
问题 #1:
如果所有保存字符串文字位置的指针都按照它们的定义进行了初始化,因此在范围的开头。并且程序进入了一个永远不会使用这些字符串文字的条件,这是否意味着执行的将字符串文字分配给指针(初始化)的代码是不必要的和浪费的?
问题 #2:
如果在可以递归调用的回调函数中定义和初始化保存字符串文字位置的指针,那不会对堆栈的存储产生重大影响吗?space?
我的具体意思是:当只使用几个保存字符串文字位置的指针时,这可能根本不是问题,但当使用大量指针时,它可能会成为问题。因此,当添加越来越多的指针时,最终可能会导致堆栈溢出。
此外,这是否意味着每次调用函数时都必须初始化指针?如果它们很多并且该函数每天被调用数千次怎么办,那不会产生很多开销吗?
问题 #3:
一种可能的解决方案是对字符串文字使用宏,如下所示:
#define TURTLES_PATH "things_i_like\turtles\fresh_water"
但这似乎不是一件很了不起的事情。
感觉好像错过了什么。将不胜感激关于如何处理此问题的一些建议或一般方法。重构可以在一定程度上避免问题,但它并没有为实际问题提供解决方案。
您怀疑
形式的变量是正确的
const char *turtlesPath = "things_i_like/turtles/fresh_water";
相对于将字符串文字内联而言,隐藏了开销,如果您需要数千个,这将变得很重要。不过,您对 开销是多少 的看法是不正确的。它不是运行时初始化操作,也不是堆栈 space。这是一个叫做 dynamic relocations 的东西,我无法简明扼要地解释,我只能为你指出一整本书:Linkers and Loaders by约翰·莱文。
事实上,最好的解决方法是在头文件中使用 #define
宏,
#define turtlesPath "things_i_like/turtles/fresh_water"
None C 预处理器宏的缺点适用于此特定用法,none 替代方案为编译器提供了尽可能多的优化自由。
P.S。不要将 space 放在括号内。当你把 spaces 放在括号里面时,它会让婴儿耶稣哭泣。
假设我有一个需要调用几次的函数,该函数将字符串文字作为其第一个也是唯一一个参数。像这样:
func( "things_i_like\turtles\fresh_water" );
/* some code */
if ( turtleFred.mood == happy )
{
func( "things_i_like\turtles\fresh_water" );
}
/* more code */
func( "things_i_like\turtles\fresh_water" );
现在,如果我需要更改该字符串文字,我将不得不在 3 个不同的地方进行更改。如果我在更改其中一个字符串文字时输入错误,可能会发生一些不好的事情。为避免这种情况,我可以使用变量来存储字符串文字的位置。像这样:
const char* turtlesPath = "things_i_like\turtles\fresh_water";
func( turtlesPath );
/* some code */
if ( turtleFred.mood == happy )
{
func( turtlesPath );
}
/* more code */
func( turtlesPath );
这种方法有 3 个问题。让我们假设我有大约 20-30 而不是一个字符串文字。
问题 #1: 如果所有保存字符串文字位置的指针都按照它们的定义进行了初始化,因此在范围的开头。并且程序进入了一个永远不会使用这些字符串文字的条件,这是否意味着执行的将字符串文字分配给指针(初始化)的代码是不必要的和浪费的?
问题 #2: 如果在可以递归调用的回调函数中定义和初始化保存字符串文字位置的指针,那不会对堆栈的存储产生重大影响吗?space?
我的具体意思是:当只使用几个保存字符串文字位置的指针时,这可能根本不是问题,但当使用大量指针时,它可能会成为问题。因此,当添加越来越多的指针时,最终可能会导致堆栈溢出。
此外,这是否意味着每次调用函数时都必须初始化指针?如果它们很多并且该函数每天被调用数千次怎么办,那不会产生很多开销吗?
问题 #3: 一种可能的解决方案是对字符串文字使用宏,如下所示:
#define TURTLES_PATH "things_i_like\turtles\fresh_water"
但这似乎不是一件很了不起的事情。
感觉好像错过了什么。将不胜感激关于如何处理此问题的一些建议或一般方法。重构可以在一定程度上避免问题,但它并没有为实际问题提供解决方案。
您怀疑
形式的变量是正确的const char *turtlesPath = "things_i_like/turtles/fresh_water";
相对于将字符串文字内联而言,隐藏了开销,如果您需要数千个,这将变得很重要。不过,您对 开销是多少 的看法是不正确的。它不是运行时初始化操作,也不是堆栈 space。这是一个叫做 dynamic relocations 的东西,我无法简明扼要地解释,我只能为你指出一整本书:Linkers and Loaders by约翰·莱文。
事实上,最好的解决方法是在头文件中使用 #define
宏,
#define turtlesPath "things_i_like/turtles/fresh_water"
None C 预处理器宏的缺点适用于此特定用法,none 替代方案为编译器提供了尽可能多的优化自由。
P.S。不要将 space 放在括号内。当你把 spaces 放在括号里面时,它会让婴儿耶稣哭泣。