二维char**指针用法

在linux下编程时会发现main的控制台输入命令行参数写法有两种

  • int main(int argc,char*argv[])
  • int main(int argc,char**argv)

控制台可以方便地在终端中输入参数对程序进行控制,这在Java和linux内核的ioctl中也有相似的体现。

其中,argc是命令行总的参数个数,argv[]存储argc个对应的参数,其中第0个参数是程序的全名,第1、2、3..个参数分别是跟在.\program后面对应的参数。[1]

那么,为什么char *argv[]和char**argv等价呢?

char* []指针数组(字符数组),每一个数组元素包含一个指向字符的指针。

而char **是一个指向指针的指针。

##char **的意义## 为了说明char* 和char **的区别,写下面的测试程序说明。

<!-- lang: cpp -->
#include <stdio.h>
void main()
{
char buffer[4]={'w','z','l','d'};
char **argv=buffer;
printf("The address of char** increases\n");
printf("%p\n",argv);
argv++;
    printf("%p\n",argv);

    printf("The address of char* increases\n");
    printf("%p\n",*argv);
(*argv)++;
    printf("%p\n",*argv);
getchar();

}

分别打印出char** 和char*类型的变量加一后的地址变化,我们可以看到:

在此输入图片描述 就是说char**加1,地址加四个字节(32bit)

char*加1,地址加一个字节(8bit)。

这是因为char *指向的地址存储的是指向存储char *类型的地址,它里面是一个地址。所以在32位PC机上是4个字节,假设是一个int类型。那么(char*)++的话指针会跨越一个字节。

而char*指向的是字符,它占用空间大小是一个字节。

##元素访问## 写下面一段测试程序:

<!-- lang: cpp -->
#include <stdio.h>
void main()
{
char *p[]={'wqyy','zq','lq','dq'};
printf("%x\n",p[0]);
}

打印出77717979,这分别是wqyy对应的ASCII码值。也就是说打印p[0]指针所指向的四个字节的内容。这是不是因为p[1]和p[0]的地址相差四个字节?printf("%x\n",*p)的结果同上。

但是有一个问题,是*p[]数组中的元素不能超过四个,比如不能写为char p[]={'wqqyy','zq','lq','dq'}。会出现报错:too many characters in constant。这是说在控制台程序里int main(int argc,charargv[])输入的参数值长度要小于4?等待考证。

写下面的代码进行验证。 <!-- lang: cpp --> #include <stdio.h> void main() {
char buff[4][4]={"abcd","wert","retr","rttt"}; char **argv=buff; printf("%c\n",argv[0]); printf("%c\n",argv[1]); printf("%c\n",argv[2]); printf("%c\n",argv[3]); } 打印出a,w,r,r。可是用argv[0][0]访问会出现程序错误,为什么不能访问?这个还没想清楚。这么说在控制台中键入参数时会自动生成适应大小的数组,就像buff[4][4]。然后用实参的大小去确定arg[m][n]大小,这样就可以像《Expert C Programming》 Page44里面一样if(argv[argc-1][0]=='-' || (argv[argc-2][1] =='f') )一样调用了。

##char **p和char *p[]##

先看一段程序[2].

<!-- lang: cpp -->
#include <iostream>
using namespace std;
void main()
{
 // 第一种初始化方法
 char **p = new char *[10]; 
 // 赋值后正常使用
 p[0] = "aaa";
 cout<<p[0]<<endl;
 // 值可以改变
 p[0] = "bbb";
 // 未赋值使用会崩。编译能过。
 //cout<<p[1]<<endl;
 // 越界赋值,编译能过,运行能过,输出时崩。

 // 第二种初始化方法
 unsigned int i = 0;
 char** pP = NULL;
 pP = (char**)calloc(128, sizeof(char*));
 for (i = 0; i < 128; ++i)
 {
    pP[i] = (char*)calloc(128, sizeof(char));
 }
 // 这种初始化方法,好像不存在越界。
 pP[1000] = "ddd";
 cout<<pP[1000]<<endl;

}

很奇怪的是第二种方法不存在“越界”,pP[1000]可以改为pP[3000]。pP是一个指针,不是数组,应该不存在所谓的越界。

##Reference##

[1].http://www.cnblogs.com/avril/archive/2010/03/22/1691477.html

[2].http://blog.csdn.net/hackbuteer1/article/details/6706562

[3].http://www.cnblogs.com/greatverve/archive/2012/11/23/cpp-char-string.html

[4].http://blog.163.com/digoal@126/blog/static/163877040201271195312138/

[5].http://blog.sina.com.cn/s/blog_95bf1ccc01017c2h.html

转载于:https://my.oschina.net/lvyi/blog/227542

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值