以char类型为例:

char a[100];     //a类型为char[100]    &a类型为 char (*)[100]    *a类型为char

char *p = a;    //p类型为 char*, *p类型为char。 也可以写成char *p = &a; 类型char[100]和char (*)[100]可隐式到char*转化,指向第一个元素的地址。不包含隐式转换的写法应该:char *p  = &a[0];   而它们的区别:

再看

#include <iostream>

void test(char *p) //即使形参为char p[]或char p[100]
{
//p类型为char *,一指针类型。即使传递的实参类型是char[100],也会退化到char*
std::cout << sizeof(p) << std::endl; //编译时计算,指针大小为4 p[] = 'z';
} int main()
{
char a[] = "abcdef";
test(a); std::cout << a << endl;//"zbcdef"
return ;
}

要想test函数里sizeof正确输出大小,test函数的形参可以改为char (*p)[100]或 char (&p)[100] ,指定大小为100是必要的,因为char[100]不能转为char (&)[],char (*)[100]也不能转为char (*)[] 。那么定义a时改为char a[] = "abcdef";可不可以呢~~~不行,a的数组大小编译时计算,它的实际类型为char[7]而不是char[]

#include <iostream>

void test(char (*p)[])
{
std::cout << sizeof(*p) << std::endl; //形参已经显示指定大小了,可以肯定输出100了。 (*p)[] = 'z';
} int main()
{
char a[] = "abcdef";
test(&a); std::cout << a << std::endl;//"zbcdef"
return ;
}

使用char (*p)[100]

#include <iostream>

void test(char (&p)[])
{
std::cout << sizeof(p) << std::endl; //形参已经显示指定大小了,可以肯定输出100了。 p[] = 'z';
} int main()
{
char a[] = "abcdef";
test(a); std::cout << a << std::endl;//"zbcdef"
return ;
}

使用char (&p)[100]


传递指针变量时,有时可能需要传递的是指针的指针或指针的引用
有时,如果直接传递指针,结果可能不是你想要的,如:

#include <iostream>

void AllocMem(char *p, int size)
{
if(p != NULL)
delete []p; p = new char[size];
} int main()
{
char *pstr = NULL;
AllocMem(pstr, ); //然而pstr依旧为NULL,执行下面的语句将运行出错
//strcpy(pstr, "hello world");
//... delete []pstr;
return ;
}

若传递指针的引用,正常工作:

#include <iostream>

void AllocMem(char *&p, int size)
{
if(p != NULL)
delete []p; p = new char[size];
} int main()
{
char *pstr = NULL;
AllocMem(pstr, ); strcpy(pstr, "hello world");
std::cout << pstr << std::endl;//正常输出 hello world delete []pstr;
return ;
}
#include <iostream>

void AllocMem(char **p, int size)
{
if(*p != NULL)
delete [](*p); *p = new char[size];
} int main()
{
char *pstr = NULL;
AllocMem(&pstr, ); strcpy(pstr, "hello world");
std::cout << pstr << std::endl;//"hello world" delete []pstr;
return ;
}

指针的指针

指针的指针使用较繁琐,而指针的引用在语法操作上和指针相似,而且还有上面例子里使用时的好处。不使用指针直接用指针的引用多好啊~~~然而:

//假设Windows编程/MFC下~

char* RectToStr(char *&p /*指针的引用*/, RECT rc)
{
//将RECT结构体里的left top right bottom转为一定格式的字符串,如"左上:(30, 40) 宽:100 高:70"
//... return p;
} int ShowPosition()
{
RECT rc;
GetWindowRect(&rc); //有时为了方便,你不想用new/delete操作,直接使用局部数组
char str[];
AfxMessageBox(RectToStr(str, rc)); //编译出错,会提示:无法将参数 1 从“char [100]”转换为“char *&”
return ;
}

  为了方便和重复使用,将RECT转化为字符串的操作封装为一个函数是合理的。参数char *&p用指针的引用似乎也是合理的,因为函数封装者可能希望传递进来的指针为NULL或者指针指向的内存大小不够时,函数里面重新p = new char[xxx]分配一下(如上文中的AllocMem函数),操作完后返回p,至于delete操作,将假设由调用者自己调用了。

  然而上例中,编译出错了,调用者传递的是个字符数组,char[100]不能转换为char *&。 当然:

    char str[];
char *p = str;//////////
AfxMessageBox(RectToStr(p, rc)); //ok,正常工作了

但竟让调用者来适应RectToStr函数......这函数就是个失败的封装

你可能想,如果不用指针的引用作判断,那么传入到RectToStr的指针是个空指针甚至是个野指针怎么办??这不是你该管的事了,是调用者的事情,你可以做个判断或简单的加个断言 assert(p != NULL) 或抛出异常。strcpy strcat等标准函数对这些情况处理了吗?你strcpy(NULL, "abc")试试~。

所以何时使用指针,何时使用指针的引用,需要你根据实际情况和用途去判断,,,


sizeof一些更特殊的用法:---引见http://www.cnblogs.com/lidabo/archive/2012/08/27/2658519.html

  • 可对函数类型--但不能对函数名使用sizeof              ----对函数使用sizeof,在编译阶段会被函数返回值的类型取代
int f1(){return ;};
double f2(){return 0.0;}
void f3(){} cout<<sizeof(f1())<<endl; // f1()返回值为int,因此被认为是int
cout<<sizeof(f2())<<endl; // f2()返回值为double,因此被认为是double
cout<<sizeof(f3())<<endl; // 错误!无法对void类型使用sizeof
cout<<sizeof(f1)<<endl; // 错误!无法对函数名使用sizeof
cout<<sizeof*f2<<endl; // *f2,和f2()等价,因为可以看作object,所以括号不是必要的。被认为是double
  • 这个很好
double* (*a)[][];
cout<<sizeof(a)<<endl; // 4 , a类型为double* (*)[3][6],是个指针,指向double* [3][6]
cout<<sizeof(*a)<<endl; // 72 , *a类型为double* [3][6],一个多维数组,数组里的数据类型是指针 3*6*4=72
cout<<sizeof(**a)<<endl; // 24 , **a类型为double* [6]
cout<<sizeof(***a)<<endl; // 4 , ***a类型为double*
cout<<sizeof(****a)<<endl; // 8 , ****a类型为double
  • sizeof -- 是个关键字,不是函数,它在编译阶段求值

  使用:

  1. sizeof(object)   对对象使用sizeof,也可以写成sizeof object 的形式
  2. sizeof(typename)    对类型使用sizeof,注意这种情况下写成sizeof typename是非法的

int i = ;
cout<<sizeof(i)<<endl; // sizeof(object)的用法,合理
cout<<sizeof i<<endl; // sizeof object的用法,合理
cout<<sizeof <<endl; // 2被解析成int类型的object, sizeof object的用法,合理
cout<<sizeof()<<endl; // 2被解析成int类型的object, sizeof(object)的用法,合理
cout<<sizeof(int)<<endl;// sizeof(typename)的用法,合理
cout<<sizeof int<<endl; // 错误!对于操作符,一定要加()

数组类型与sizeof与指针的引用的更多相关文章

  1. 动态创建二维vector数组 C和C++ 及指针与引用的区别

    二维vectorvector<vector <int> > ivec(m ,vector<int>(n));    //m*n的二维vector 动态创建m*n的二 ...

  2. (C/C++)区别:数组与指针,指针与引用

    1.数组跟指针的区别 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变. 指针可以随时指向任意类型 ...

  3. C++中指针和引用、数组之间的区别

    指针指向一块内存,它的内容是所指内存的地址:而引用则是某块内存的别名,引用初始化后不能改变指向.使用时,引用更加安全,指针更加灵活. 初始化.引用必须初始化,且初始化之后不能呢改变:指针可以不必初始化 ...

  4. C++之指针与引用,函数和数组

    ]={,,}; //ptr是指针,该指针类型是int[3] ]=&arr; cout << **ptr << endl;//第一次解指针时得到数组地址,第二次解指针取数 ...

  5. delphi 数组类型与数组指针的巧妙利用

    {本例通过存取结构, 慢慢引入了数组类型与指针的一些使用方法; 其中六个小例子的测试内容和结果都是一样的. ---------------------------------------------- ...

  6. C++之指针,引用与数组

    引用只是对象的另一个名字,通过在变量名前面添加"&”符号来定义,而指针保存的是另一个对象的地址,它们两都提供了间接访问所服务变量的途径. 但是它们的差别还是挺大的: 先从它们的值说起 ...

  7. 别混淆了sizeof(数组名)和sizeof(指针)

    我们在挨个儿输出一个数组中的元素时,最常用的就是用一个for循环来实现,简单了事.比如类似下面的代码片段: for(i = 0; i< length; i++) { printf("数 ...

  8. C语言 数组类型与数组指针类型

    //数组类型与数组指针类型 #include<stdio.h> #include<stdlib.h> #include<string.h> void main(){ ...

  9. 为什么C++类定义中,数据成员不能被指定为自身类型,但可以是指向自身类型的指针或引用?为什么在类体内可以定义将静态成员声明为其所属类的类型呢 ?

    static的成员变量,不是存储在Bar实例之中的,因而不会有递归定义的问题. 类声明: class Screen: //Screen类的声明 1 类定义: class Screen{ //Scree ...

随机推荐

  1. DataTable/集合 转 Json

    前端用的jqueryUI框架获取json格式数据绑定显示表格. 后端通过WebService获取的数据是DataTable. 现将获取DataTable转Json,也支持将数据集合转Json. 一.项 ...

  2. Intellij 常用技巧-持续更新

    1.快速输入 System.out.println(); sout [TAB] 2.删除Module ctrl+alt+shift+s 调出  Project Structure ,也可点击菜单Fil ...

  3. GIT-查看本地html帮助文档

    GIT安装后可以直接在命令行中通过指令调取本地html帮助文档如下所示: 格式: git help remote--git help 指令名称 git help remote 显示结果 获取branc ...

  4. mac常用的命令

    1.递归查找⽂文件内容: grep -r target_string absolute_path 2.移动所有⽂文件(包括隐藏⽂文件): mv * .[^.]* targetDir 3.⽂文件分割合并 ...

  5. RabbitMQ学习总结 第七篇:RCP(远程过程调用协议)

    在http://www.cnblogs.com/leocook/p/mq_rabbitmq_2.html 这篇博文中我们实现了怎么去使用work queue来把比较耗时的任务分散给多个worker. ...

  6. 通过Maven将Web程序部署到远程Tomcat8服务器的一些注意事项

    1.环境变量检查(注意一定要做,否则会出现莫名其妙的错误):JAVA_HOMEM2_HOMECATALINA_HOME 2.开发环境检查,在Eclipse开发环境中最好做以下两方面的检查 2.1)Ma ...

  7. 002:IPC与system函数简介

    1:IPC名字mq_XXX,sem_XXX,shm_XXX. 消息队列 信号量 共享内存区 <mqueue.h> <semaphore.h> <sys.mman.h> ...

  8. js ajax同步请求造成浏览器假死的问题

    一.问题的起因 今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下: /** ...

  9. JAVA:通过poi读取excel

    POI是一个apache开源的jar包,可以通过搜索 java POI找到官网,并下载开发包. 包含的功能: 可以读取excel2003,2007,2010等. 读取excel2007/2010的代码 ...

  10. MySQL的下载与安装 和 navicat for mysql 安装使用

    新手上路-MySQL安装 目录结构 Windows平台 MySQL安装 示例数据导入 Linux平台 CentOS系统 Ubuntu系统 FAQ 密码生成工具-keepass 修改提示符 图形工具 删 ...