指针的温故知新

C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组很有必要.

重新认知几个概念

数组:数组变量实际是指针变量.数组是多个元素的集合,在内存中分布在地址相连的单元中,所以可以通过其下标访问不同单元的元素。所以是在内存地址的概念讨论数组.但是,内存地址就是指针.哈哈,你大爷还是你大爷.

关于证明,详见文章https://mp.csdn.net/postedit/94859895中间动态数组部分.

指针:指针也是一种变量,只不过它的内存单元中保存的是一个标识其他位置的地址。由于地址也是整数,在32位平台下,指针默认为32位.关于其指向,就是指针变量所保存的地址单元中所存放的数据类型。

字符数组:不就是存字符的数组吗,地址连续.

#include <string.h>
#include <iostream>
#include <stdio.h>
using namespace std;

int main(int argc, char** argv)
{
	char  str[10]="Amercian"; 
	cout<<str<<endl;
	
	char  *p ;
    p = str;//为什么可以把一个字符串赋给一个指针变量?
    //其实真正的意义是 p="American" = 00000000006ffe30;首地址,地址连续,直到发现\0结束.

    
	printf("%p\n",p);
    printf("%s\n",p);
    
    return 0;
}

%s可能的输出机制:

#include <string.h>
#include <iostream>
#include <stdio.h>
using namespace std;

int main(int argc, char** argv)
{
	char  str[10]="Amercian"; 
    char *s =str;
        for(int i= 0; i < strlen(str) ; i++)
        printf("%c\n", s[i]);
        //while(*s!='\0')
        //printf("%c",*s++);
    return 0;
}

char  * a[ ]

由于[ ] 的优先级高于* 所以a先和 [ ]结合,他还是一个数组,数组中的元素才是char * ,前面讲到char * 是一个变量,保存的地址。

#include <iostream>
#include <stdio.h>
using namespace std;

int main(int argc, char** argv)
{
	char* a [ ] = {"China","French","America","German"};
	
	printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]); //数组元素中保存的地址 ,即指针
    printf("%p %p %p %p\n",&a[0],&a[1],&a[2],&a[3]);//数组元素单元本身的地址,即指针的指针

	cout<<a[0]<<endl; 

	char** arg;
	arg=a+2; 
	printf("%p\n",arg);

	cout<<*arg<<endl; 
	return 0;
}

附:二级指针保存的是一级指针的地址,它的类型是指针变量,而一级指针保存的是指向数据所在的内存单元的地址,虽然都是地址,但是类型是不一样.

**指向指针的指针

#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int p=1;//int型变量 

	int* a;	//定义一个指向int型变量的指针 
	a=&p;   //指针a存储了变量p的首地址
	cout<<&p<<endl; 
	cout<<a<<endl; //打印首地址
	cout<<*a<<endl;//打印在该地址上所存储的变量
	
	int** arg;//定义一个指向int型变量的指针的指针 
	arg=&a;   //指针arg存储了指向p的指针变量a的地址
	
	cout<<**arg<<endl; //两次提领操作
	return 0;
}

解释一下两次提领操作:因为指针变量a存储了int变量p的地址,所以第一次提领操作先根据a的地址找到获得a.(前提是,arg=&a);第二次相当于做了一次*a操作,显而易见.

#include <iostream>
#include <stdio.h>
using namespace std;

int main(int argc, char** argv)
{
	char* a [ ] = {"China","French","America","German"};
	
	char** s;//char **为二级指针, s保存一级指针 char *的地址
	s=a+0; 
	//printf("%p\n",arg);
	printf("%s",*s);
    printf("%s",a[0]);
    printf("%s",*a);


	return 0;
}

 

一个有趣的现象

#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
    cout<<**argv<<endl; 
	cout<<*argv<<endl; 
	cout<<argv<<endl; 

	cout<<argc<<endl; 
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值