- 第一章 CPU 简介
- 第二章 Hello,world!
- 第三章 函数开始和结束
- 第四章 栈
- Chapter 5 printf() 与参数处理
- Chapter 6 scanf()
- CHAPER7 访问传递参数
- Chapter 8 一个或者多个字的返回值
- Chapter 9 指针
- Chapter 10 条件跳转
- 第 11 章 选择结构 switch()/case/default
- 第 12 章 循环结构
- 第 13 章 strlen()
- Chapter 14 Division by 9
- chapter 15 用 FPU 工作
- Chapter 16 数组
- Chapter 17 位域
- 第 18 章 结构体
- 19 章 联合体
- 第二十章 函数指针
- 第 21 章 在 32 位环境中的 64 位值
- 第二十二章 SIMD
- 23 章 64 位化
- 24 章 使用 x64 下的 SIMD 来处理浮点数
- 25 章 温度转换
- 26 章 C99 的限制
- 27 章 内联函数
- 第 28 章 得到不正确反汇编结果
- 第 29 章 花指令
- 第 30 章 16 位 Windows
- 第 31 章 类
- 三十二 ostream
- 34.2.2 MSVC
- 34.2.3 C++ 11 std::forward_list
- 34.3 std::vector
- 34.4 std::map and std::set
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
MSVC
MSVC 的实现中,字符串存储在适当的位置,不一定位于指针指向的缓冲区(如果字符串的长度小于 16 个字符)。 这意味着短的字符串在 32 位环境下至少占据 16+4+4=24 字节的空间,在 64 位环境下至少占据 16+8+8=32 字节,当字符串长度大于 16 字符时,相应的需要增加字符串自身的长度。
#include <string>
#include <stdio.h>
struct std_string
{
union
{
char buf[16];
char* ptr;
} u;
size_t size; // AKA ’Mysize’ in MSVC
size_t capacity; // AKA ’Myres’ in MSVC
};
void dump_std_string(std::string s)
{
struct std_string *p=(struct std_string*)&s;
printf ("[%s] size:%d capacity:%d\n", p->size>16 ? p->u.ptr : p->u.buf, p->size, p->
capacity);
};
int main()
{
std::string s1="short string";
std::string s2="string longer that 16 bytes";
dump_std_string(s1);
dump_std_string(s2);
// that works without using c_str()
printf ("%s\n", &s1);
printf ("%s\n", s2);
};
通过源代码可以清晰的看到这些。 如果字符串长度小于 16 个符号,存储字符的缓冲区不需要在堆上分配。实际上非常适宜这样做,因为大量的字符串确实都较短。显然,微软的开发人员认为 16 个字符是好的临界点。 在 main 函数尾部,虽然没有使用 c_str() 方法,但是如果编译运行上面的代码,所有字符串都将打印在控制台上。 当字符串的长度小于 16 个字符时,存储字符串的缓冲区位于 std::string 对象的开始位置,printf 函数将指针当做指向以 0 结尾的字符数组,因此上述代码可以正常运行。 第二个超过 16 字符的字符串的打印方式比较危险,通常程序员犯的错误是忘记写 c_str()。这在很长的一段时间不会引起人的注意,直到一个很长的字符串出现,然后程序崩溃。而上述代码可以工作,因为指向字符串缓冲区的指针位于结构体的开始。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论