1.sizeof用法总结

①与strlen比较

      strlen  计算字符数组的字符数,以"\0"为结束判断,但不包括。
  sizeof 计算数据(数组、变量、类型、结构体等)所占内存空间,用字节数表示。

②指针与静态数组的sizeof操作

  指针均可看为变量类型的一种。因此:
      :int *p; 
                    sizeof(p)=4;
                    sizeof(*p)=4;//相当于sizeof(int)      
  对于静态数组,sizeof可直接计算数组大小:
      例:int a[10];char b[]="hello";
                    sizeof(a)=40;//4*10=40;
                    sizeof(b)=6;
  数组做型参时,数组名称当作指针使用:
             例: void  fun(char p[]);
                     sizeof(p)=4;

③格式的写法

sizeof为操作符而非函数,对变量或对象可以不加括号,但若是类型,须加括号。

④操作string的注意事项

        string   str[]={"hello", "world", "CHB","\n"};
    cout<<sizeof(str)<<endl;//输出128
    cout<<sizeof(str[0])<<endl;//输出32,即对象的大小
    cout<<sizeof(str[0].c_str())<<endl;//输出4,c_str()返回 const char*指针,指向str[0]
    cout<<strlen(str[0].c_str())<<endl;//输出5,str[0]字符串的长度

⑤经典问题:

        double* (*a)[3][6]; 
        cout<<sizeof(a)<<endl; // 4,a为指针
        cout<<sizeof(*a)<<endl; // 72 ,*a为一个有3*6个指针元素的数组
        cout<<sizeof(**a)<<endl; // 24, **a为行指针
        cout<<sizeof(***a)<<endl; // 4 ,***a为一维的第一个指针
        cout<<sizeof(****a)<<endl; // 8 ,****a为一个double变量
    
  解析:a为指向double*[3][6]类型二维指针数组(数组元素为double*
指针类型)的指针。既然是指针,所以sizeof(a)就是4。*a就表示二维指针数组double*[3][6],因此sizeof(*a)=3*6*sizeof(double*)=72。**a为行指针,指向一维指针数组double*[6],sizeof(**a)=6*sizeof 
(double*)=24。***a就表示行指针数组的第一个指针元素,也就是double*了,所以sizeof(***a)=4。至于****a,则是一个double类型,所以sizeof(****a)=sizeof(double)=8。

 
   看看以下情况:
	double**b[3][6]; 
        cout<<sizeof(b)<<endl; // 72,b为数组类型,数组元素为double**;
        cout<<sizeof(*b)<<endl; // 24,行指针
        cout<<sizeof(**b)<<endl; // 4,b[0][0]的值,double**类型
        cout<<sizeof(***b)<<endl; // 4,double* 
        cout<<sizeof(****b)<<endl; // 8 double
double (*c)[3][6];
cout<<sizeof(c)<<endl;//4,指针变量,指向double[3][6]
cout<<sizeof(*c)<<endl;//144,double[3][6]的数组类型
cout<<sizeof(**c)<<endl;//48,行指针,指向c[0],实际指向为&c[0][0]
cout<<sizeof(***c)<<endl;//8,c[0][0]的值
double* d[3][6];
        cout<<sizeof(d)<<endl; // 72,指针数组类型,元素为double*的[3][6]数组
        cout<<sizeof(*d)<<endl; // 24,行指针
        cout<<sizeof(**d)<<endl; // 4,d[0][0]的元素值,即double*
        cout<<sizeof(***d)<<endl; // 8

⑥操作struct的内存对齐问题

     (1)整体空间是占用空间最大的成员(的类型)所占字节数的整倍数
    (2)内存按结构成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整倍数,如果不够则补齐,以此向后类推。
    (3)数组按照单个变量一个一个的摆放,而不是看成整体。如果成员中有自定义的类、结构体,也要注意数组问题。

例子1

struct s1{
char a;
double b;
int c;
char d;}; struct s2{
char a;
char b;
int c;
double d;}; cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 16

占空间的最大成员是double类型变量,故对齐空间大小为8。s1中的c和d,s2中a,b,c可以放进一个“8”位空间中。

例子2

struct s1
{char a[8];}; struct s2
{double d;}; struct s3{
s1 s;
char a;}; struct s4{
s2 s;
char a; }; cout<<sizeof(s1)<<endl; // 8
cout<<sizeof(s2)<<endl; // 8
cout<<sizeof(s3)<<endl; // 9
cout<<sizeof(s4)<<endl; // 16

虽然s1和s2大小都是8,但是s1的对齐空间大小是1(char),s2是8(double)。所以定义结构体的时候,如果空间紧张的话,最好考虑对齐因素来排列结构体里的元素。这里结构体中定义的数组可以当做多个同类数据顺序排列,以此确定对齐的空间大小。

例子3

struct s1 {
 int i: 8;
 int j: 4;
 double b;
 int a:3;}; struct s2 {
 int i;
 int j;
 double b;
 int a;}; struct s3 {
 int i;
 int j;
 int a;
 double b;}; struct s4 {
 int i: 8;
 int j: 4;
 int a:3;
 double b;}; cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 24
cout<<sizeof(s3)<<endl; // 24
cout<<sizeof(s4)<<endl; // 16

在结构体和类中,可以使用位域来规定某个成员所能占用的空间,所以使用位域能在一定程度上节省结构体占用的空间。double存在会干涉到位域。所以使用位域的的时候,最好把float类型和double类型放在程序的开始或者最后。

    如上。以double--8字节为单位,分配位,以s1为例。i,j占据一个double长度,b自己占据一个double长度,a占据另外一个double。

⑦基本操作结果

sizeof  int:4

     sizeof  short:2

     sizeof  long:4

     sizeof  float:4

     sizeof  double:8

     sizeof  char:1

     sizeof  *p:4

     sizeof  WORD:2

     sizeof  DWORD:4

2.同类对象之间和结构体变量之间的相互赋值

struct student
{
int number;
char name[8];
float score;
}a[3],temp;
temp=a[0];
a[0]=a[1];
a[1]=temp;

同类型的对象之间或结构体变量之间可以相互赋值。而字符串或者字符数组不行。

  • 对象的赋值只对其中的数据成员赋值,而不对成员函数赋值。数据成员是占存储空间的,不同对象的数据成员占有不同的存储空间,赋值的过程是将一个对象的数据成员在存储空间的状态复制给另一对象的数据成员的存储空间。而不同对象的成员函数是同一个函数代码段,不需要、也无法对它们赋值。
  • 类的数据成员中不能包括动态分配的数据,否则在赋值时可能出现严重后果。

3.setw()和setfill()的使用

   set(int n),在输出时分配了n个字符的输出宽度,然后默认的是在n个字符宽度中右对齐setiosflags(ios::rigth)输出,可以使用setiosflags(ios::left)设置为左对齐输出可以使用。配套使用setfill(char
x)使用x来填充空下的空格。VS2008中编译时,必须包括头文件【#include "iomanip"】。
#include "stdafx.h"
#include"iostream"
#include "iomanip"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cout<<"方法一: "<<endl;
cout << setw(8) << setiosflags(ios::left) <<setfill('0') << 8 << endl;//左对齐,即从右边填充
cout << setw(8) << setiosflags(ios::right) <<setfill('0') << 9 << endl;//右对齐,从左边填充
cout << setw(8) << setfill('0') << 10 << endl;//默认右对齐,即从左边填充
cout<<"使用以下这种形式来调用显得更加整齐并简洁: "<<endl;
cout.setf(ios::right,ios::adjustfield);//标志位设置
cout.fill('0');
cout << setw(8) << 11 <<endl;
cout << setw(8) << 12 << endl;
return 0;
}
结果如下:
              
 
分析:1)倘若用于用cout输出的话,被填充的仅仅应该是int值;
      2)第一种方法三个函数setw(8),setiosflags(ios::right),setfill('0')的位置可以任意调换。

4.字符串流stringstream

C++标准库中的“sstream”提供了比ANSIC的<stdio.h>更高级的一些功能,即单纯性、类型安全和可扩展性。为什么要花额外的精力来学习基于“sstream”的类型转换呢?也许对下面一个简单的例子的回顾能够说服你。假设你想用sprintf()函数将一个变量从int类型转换到字符串类型。为了正确地完成这个任务,你必须确保证目标缓冲区有足够大空间以容纳转换完的字符串。此外,还必须使用正确的格式化符。但是,对上面代码的一个微小的改变就会使程序崩溃,如下:

int n=10000;
char s[10];
sprintf(s,”%d”,n);// s中的内容为“10000”
sprintf(s,”%f”,n);// 注意!错误的格式化符

由于错误地使用了%f格式化符来替代了%d。因此,s在调用完sprintf()后包含了一个不确定的字符串。

由于n和s的类型在编译期就确定了,所以编译器拥有足够的信息来判断需要哪些转换。“sstream”库中声明的标准类就利用了这一点,自动选择所必需的转换。而且,转换结果保存在stringstream对象的内部缓冲中。你不必担心缓冲区溢出,因为这些对象会根据需要自动分配存储空间。

“sstream”库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本。

<sstream>使用string对象来代替字符数组。这样可以避免缓冲区溢出的危险。而且,传入参数和目标对象的类型被自动推导出来,即使使用了不正确的格式化符也没有危险。

例子1 基本类型转换

#include "stdafx.h"
#include"iostream"
#include"sstream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a=10;double b=11.12;
string c;char d[10];
stringstream ss;
ss<<a;ss>>c;//输入到流并抽取
ss.clear();//多次转换的时候,必须调用stringstream的成员函数clear().
ss<<b;ss>>d;//输入到流并抽取
cout<<c<<"\n"<<d<<endl;
return 0;
}

 注意:1.不仅支持普通类型也支持char*;

2.多次转换使用一个sstream对象时,使用成员函数clear()。这里sstream对象的构造和析构函数一般比较耗时,因此一般重复使用一个;

3.转换更加安全,自动,直接。

例子2 模板转换函数

#include "stdafx.h"
#include"iostream"
#include"sstream"
using namespace std;
template<class T>
void to_string(string & result,const T& t)
{
ostringstream oss;//创建一个流
oss<<t;//把值传递如流中
result=oss.str();//获取转换后的字符转并将其写入result
}
template<class T1,class T2>
T2 typechange(T1& a)
{
stringstream ss;
T2 b;
ss<<a;ss>>b;
return b;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a=10;double b=11.12;
string c="123.45";
string d;
to_string(d,a);cout<<d<<endl;//int to string
to_string(d,b);cout<<d<<endl;//double to string
a=typechange<string,int>(c);cout<<a<<endl;// string to int,注意123.45->123
c=typechange<double,string>(b);cout<<c<<endl;//double to string
return 0;
}

注意:1.使用成员函数str()获取流内部缓冲的拷贝;

2.转换遵循从输入流中给变量赋值的规律,如string to int:“123.45”->123;

3.可以配合使用上文的setw(),setfill()进行到string的转换,如下所示:

stringstream ss;
ss<<"example:"<<setw(8)<<setfill('0')<<12;
ss>>d;
cout<<ss.str()<<endl;

部分参考自:sizeof()用法汇总

C++零碎知识点(一)的更多相关文章

  1. webdriver零碎知识点

    #零碎知识点,用于记录平时遇到的比较杂的知识点 driver.current_url 获取当前url phantomjs 实现无浏览器界面自动化测试(driver = webdriver.Phanto ...

  2. Android零碎知识点 1

    Android零碎知识点 1   Android在2.3版本上开始支持KeyEvent.KEYCODE_PAGE_DOWN以及KeyEvent.KEYCODE_PAGE_UP的操作.   Androi ...

  3. C++ 零碎知识点

    C++的一些知识点比较零碎,下面清单的形式做一些记录与归纳,以供参考. 1.赋值操作符重载(深复制): (1)由于目标对象可能引用了以前的一些数据,所以应该先delete这些数据: (2)注意到对象可 ...

  4. 大数据学习day19-----spark02-------0 零碎知识点(分区,分区和分区器的区别) 1. RDD的使用(RDD的概念,特点,创建rdd的方式以及常见rdd的算子) 2.Spark中的一些重要概念

    0. 零碎概念 (1) 这个有点疑惑,有可能是错误的. (2) 此处就算地址写错了也不会报错,因为此操作只是读取数据的操作(元数据),表示从此地址读取数据但并没有进行读取数据的操作 (3)分区(有时间 ...

  5. iOS开发零碎知识点

    记录一些常用和不常用的iOS知识点,防止遗忘丢失.(来源为收集自己项目中用到的或者整理看到博客中的知识点),如有错误,欢迎大家批评指正:如有好的知识点,也欢迎大家联系我,添加上去.谢谢! 一.调用代码 ...

  6. 11、网页制作Dreamweaver(补充:JS零碎知识点&&正则表达式)

    JS知识点 回车符/r和换行符/n的区别:/r 相当于enter,是段落与段落之间的区别, /n 相当于shift+enter,是行与行之间距离,比较小 几种window操作方法: 1.获取当前窗口大 ...

  7. salesforce零基础学习(八十八)项目中的零碎知识点小总结(二)

    通过做项目以及群里面的一些大神的聊天,总结一下关于项目中的两个知识点,以后当做参考. 一. 在custom setting中配置集成接口信息后刷sandbox的问题 我们做项目时,经常会遇见和其他平台 ...

  8. 整理OD一些快捷键和零碎知识点

    第一次记录:2019.9.15 完成了近期基本知识点的记录 第二次记录:2019.9.16 更新VB和的Delphi的汇编代码特点 介绍几个快捷键: Alt+B 断点编辑器,空格键可切换断点状态 ct ...

  9. salesforce零基础学习(一百一十二)项目中的零碎知识点小总结(四)

    本篇参考: https://trailblazer.salesforce.com/issues_view?id=a1p4V0000003znDQAQ https://salesforce.stacke ...

  10. python零碎知识点一

    dir(object),列出对象所有可以用的的方法(参数可以为任意对象,例如class,func等) >>>dir('str') ['__add__', '__class__', ' ...

随机推荐

  1. static_new

    <?php //在::操作符的左边写上类的名称来静态地访问某个成员,这样就可以避免创建类的实例. //这样不仅可以省略掉实例化类的代码,而且还会更高效,因为类的每个实例都会占用一小部分的系统资源 ...

  2. 【leetcode刷题笔记】Edit Distance

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

  3. jquery 初篇

    一.什么是jQuery对象? jQuery 对象就是通过jQuery包装DOM对象后产生的对象. jQuery 对象是 jQuery 独有的. 如果一个对象是 jQuery 对象, 那么它就可以使用  ...

  4. Android OTA在线升级一(架构分析)【转】

    本文转载自:http://blog.csdn.net/yanleizhouqing/article/details/50234213 1.前言 OTA(Over-the-Air Technology) ...

  5. 【转】RMQ-ST算法详解

    地址:http://blog.csdn.net/z287438743z/article/details/8132806 RMQ(Range Minimum/Maximum Query)问题就是求区间最 ...

  6. 圆方树&广义圆方树[学习笔记]

    仙人掌 圆方树是用来解决仙人掌图的问题的,那什么是仙人掌图呢? 如图,不存在边同时属于多个环的无向连通图是一棵仙人掌 圆方树 定义 原先的仙人掌图,通过一些奇妙的方法,可以转化为一棵由圆点,方点和树边 ...

  7. CSS3按钮效果制作

    CSS3按钮效果制作 首先附上效果图,按下去有一种下沉的效果, 未按效果 按下去效果 原理:第一个按钮相对比较简单,就直接是一个双重阴影效果,然后鼠标按下去让他的margin-top值为-3px,阴影 ...

  8. 再次理解WCF以及其通信(附加一個編程小經驗)

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  9. Selenium-免登录的实现

    场景: 经常会遇到登录需要验证码这样类似的情况 解决方案: 1.万能验证码 2.利用cookies来实现,问开发哪个cookies值是登录后需要的,把这个值带上即可 3.利用火狐浏览器的profile ...

  10. Java微信开发_00_资源汇总贴

    1.微信公众平台技术文档(https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432) 2.微信企业号开发接口文档(ht ...