本文简述了之前遇到的两则编程杂记
之前看到一段 C/C++ 代码:
void func(const char* str) {
// implementation ...
}
func("string" "params");
代码定义了一个参数为字符串指针的函数 func,调用时却使用了 “string” “params” 这种字符串连写的方式(中间没有逗号分隔符),初看时我一直怀疑调用代码存在"笔误",甚至认为这种写法会引起编译错误,但实际上, func(“string” “params”) 这种调用方式是正确无误的.
因为在编译期,像 “string” “params” 这种连写的字符串字面量会被合并为单个字符串字面量,所以上面 func(“string” “params”) 的调用代码经过编译后其实等价于 func(“stringparams”),这种被称为 隐式字符串字面量合并 的特性有两个注意点:
所以如果你尝试对字符串变量进行隐式合并,那么等待你的就是编译错误了:
void func(const char* str) {
// implementation ...
}
const char* params = "params";
// error here ...
func("string" params);
隐式字符串字面量合并的一大作用就是方便我们分隔大段的字符串代码文本,之前我们一般都会使用 行接续符(\) 来分隔长字符串:
const char* long_long_str = "long\
long\
string";
这种方式比较繁琐,格式上也不美观,使用隐式字符串字面量合并的话则会改善很多:
const char* long_long_str = "long"
"long"
"string";
之前简单用 C# 写了一些用于读取 excel 配置的代码,其中有段逻辑用于处理以下的功能需求:
excel 单元格中一般配置为整型值,但是也有情况会配置为字符串(譬如配置为"是",而"是"最终会被映射为 1(这种映射关系事先会有定义),总的来说,支持将整数值配置为字符串是为了方便配置人员进行更直观的配置)
相关(简化)代码如下:
var cellStr = getCellStr();
var cellNum = 0;
try
{
// first try parse int
cellNum = int.Parse(cellStr);
}
catch (...)
{
// then try map str to int
if (!TryMapCellStr(cellStr, out cellNum))
{
// config error
}
}
结果代码运行之后奇慢无比,简单看了一下 profile 发现消耗最大的就是这段 try … catch 代码,自己摸索了一番,大概确定了几点原因:
知道了原因,上述代码的调整方法也就明了了,我们首先尝试字符串映射(用以规避在 catch 块中进行正常的程序流处理)即可(使用 int.TryParse 直接规避 try … catch 应该是更好的一种做法):
var cellStr = getCellStr();
var cellNum = 0;
try
{
// first try map str to int
if (!TryMapCellStr(cellStr, out cellNum))
{
// then try parse int
cellNum = int.Parse(cellStr);
}
}
catch (...)
{
// config error
}
try … catch 尽量不要用于正常的程序流控制