C语言学习(五)——指针

Ps:相信学过C语言的同学都知道,指针是C语言中最重要也是最难攻克的部分,下面的代码中的注释部分请同学们要仔细阅读

一、指针&指针变量

 

#include
#include
#include
#include


//32位编译器(0x0000 0000-0xffff ffff):
//指针变量:
//存放指针(地址)的变量
//因为地址编号(0x0000 0000)如此,所以我们指针变量占4个字节就可以存下
//64位编译器(0x0000 0000 0000 0000-0xffff ffff ffff ffff):
//指针变量占8个字节


//指针变量的定义和初始化
//指针变量的定义:

int main01()
{
	using namespace std;
	int a = 10;
定义指针的步骤:
	1.*与符号结合代表是一个指针变量
	2.要保存谁的地址,将他的定义形式放在此处
	3.用*p替换掉定义的变量
	定义指针变量的格式:
	数据类型   *    变量名
	!!注意!!指针变量的类型是  数据类型*(例:int *p的指针变量类型是int*,p是变量!!)
	int* p;
	分析
	与*结合代表这是一个指针变量
	p是变量,p的类型是将变量p本身拖黑,剩下的类型就是指针变量的类型
	指针变量p用来保存什么类型数据的地址,将指针变量p和指针变量p最近的*一起拖黑,
	//剩下什么类型就保存什么类型数据的地址
	p = &a;
	int* i_porint = &a;
	system("pause");
	return (0);

}


//指针的使用
//指针变量保存了谁的地址就指向了谁
int main02()
{
	//在使用(最常见是赋值时,因为等号两边数据类型要匹配)时,对一个表达式取*,就会对表达式减一级*,如果对表达式取&,就会加一级*
	using namespace std;
	int a = 10;
	int* p = &a;
	*p = 100;//在使用时,*与p结合代表,取p指针所指向的那块空间的内容
	cout << *p << endl;//*p:  p指向地址中的内容
	cout << p << endl;//p: p指向的地址空间
	cout << a << endl;
	//注意!!!&可以取得一个变量在内存中的地址,但是,不能取寄存器变量,因为寄存器变量不在内存里,而在CPU里面,所以是没有地址的
	system("pause");
	return (0);
}


//指针变量的大小sizeof()
//不管什么类型的指针,大小只和系统或编译器的位数有关
int main03()
{
	using namespace std;
	char* p1;
	short* p2;
	int* p3;
	int** p4;
	cout << sizeof(p1) << endl;
	cout << sizeof(p2) << endl;
	cout << sizeof(p3) << endl;
	cout << sizeof(p4) << endl;
	system("pause");
	return (0);
}

//指针的宽度和步长  宽度也可以理解成步长
int main04()
{
	using namespace std;
	int num = 0x01020304;
	char* p1 = (char*)#
	short* p2 = (short*)#
	int* p3 = #
	int** p4;
	printf("%x\n", *p1);//4
	printf("%x\n", *p2);//304
	printf("%x\n", *p3);//01020304
	//通过*取指针指针变量所指向的那块空间内容时,取的内存的宽度和指针变量本身的类型有关
	//指针的宽度(步长)=sizeof(将指针变量与指针变量最近的*拖黑,剩下的类型)
	//步长:指针+1跨过的字节数
	printf("%p\n", p1);
	printf("%p\n", p2);
	printf("%p\n", p3);

	printf("%p\n", p1 + 1);
	printf("%p\n", p2 + 1);
	printf("%p\n", p3 + 1);

	system("pause");
	return (0);
}


//野指针
int main05()
{
	using namespace std;
	int* p;
	//*p=200;
	//printf("%d\n",*p)
	//野指针:就是没有初始化的指针,指针的指向时随机的不可以操作野指针
	//指针变量保存的地址一定是定义过的(向系统申请过)
	system("pause");
	return (0);
}

//空指针
int main06()
{
	using namespace std;
	int a;
	//将指针的值赋值给0,0x00000000 = NULL
	int* p = NULL;//给指针p的内容赋值为0
	if (p != NULL)
	{
		p = &a;
	}


	*p = 200;//错误    因为p保存了0x0000的地址,这个地址是不可以被赋值的

	printf("%d\n", *p);
	system("pause");
	return (0);
}

//万能指针
int main07()
{
	using namespace std;
	//void b;  不可以定义void类型的变量,因为编译器不知道给变量分配多大的空间
	//但是可以定义void*类型,因为指针都是4个字节
	int a = 10;
	short b = 20;
	void* q = (void*)&b;
	void* p = (void*)&a;//万能指针可以保存任意的地址,在不知道所指向变量的数据类型时,
						//需要强制转换数据类型(为了保持赋值=两边数据类型匹配)
	printf("%d\n", *(int *)p);//*((int *)地址)
	system("pause");
	return (0);
}

//const修饰的指针
int main08()
{
	using namespace std;
	const int a = 10;//修饰变量a,不能再通过a修改a内存里面的内容
	/* int *p;
	p = &a;
	*p = 100;*/

	

	system("pause");
	return (0);
}


int main09()
{
	using namespace std;
	const int* p;//const在这里修饰的是*
	int a = 10;
	p = &a;//不能通过*p,改p所指向空间的内容
	//*p = 100;err  因为不能通过p改p所指向的内容


	//const修饰的指针变量p
	//p保存的地址不可以被修改,不能通过*p修改p所指向的那块空间的内容
	int* const p = &a;
	//p=&b;err  p本身的值不能被改变

	//不想被改变的数据,就用const修饰即可

	system("pause");
	return (0);
}


 

二、多级指针&数组与指针

#include
#include
#include
#include



//1.多级指针
int main10()
{
	using namespace std;
	int a = 10;
	int* p = &a;
	//现在需要定义一个指针去指向指针变量p所在的地址
	//p的数据类型是int*,  用新指针*q代替指针变量p,  数据类型是int*
	int** q = &p;
	//*q代表指针变量p中的内容--变量a的地址
	//**q代表的是a的值
	//**q==*(*q)==*(&a)==*(p)==a
	//如果*和&相遇则抵消
	int*** k = &q;
	//*与符号结合,代表这个k是一个指针变量
	//k是一个变量
	//k的类型,将变量k拖黑,整下的类型
	//k用来保存谁的地址,将变量k和k最近的*一起拖黑,剩下什么类型就保存什么类型数据的地址
	system("pause");
	return (0);
}


//2.数组与指针
//通过指针操作数组元素
int main11()
{
	using namespace std;
	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int b[10] = { 0 };
	//a 数组名,首元素的地址
	int* p = a;//指针p保存的是首元素的地址
	for (int i = 0; i 

 

 三、指针与函数

#include
#include
#include
#include

//1.指针与函数
//指针作为形参
int main15()
{
	using namespace std;
	void swap(int*, int*);
	int a = 10;
	int b = 20;
	int* p1 = &a;
	int* p2 = &b;
	swap(p1, p2);
	cout << "a=  " << a << endl;
	cout << "b=  " << b << endl;
	system("pause");
	return (0);
}
void swap(int* a, int* b)
{
	int temp;
	temp = (*a);
	(*a) = (*b);
	(*b) = temp;
	return;
}


int main16()
{
	using namespace std;
	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
	return 0;
}

 (续)

#include
#include
#include
#include

using namespace std;
int num = 0;//在函数外面定义的变量是全局变量,整个工程都可以使用
//这个变量程序启动开辟空间,知道程序结束时才释放空间
void print_arr(int b[10])//数组做形参,系统会自动转化为指针  int *b;
{
	for (int i = 0; i < sizeof(b) / sizeof(b[0]); i++)
	{
		cout << b[i] << "  ";
	}
	cout << endl;
	cout << sizeof(b) << endl;//打印结果为:4  说明数组做形参,就会退化为指针
	cout << sizeof(b[0]) << endl;//打印结果为:4  所以sizeof(b) / sizeof(b[0])==1,因此只会打印一个字节
}
void out_arr(int *b,int n)//n代表数组中的元素个数
{
	for (int i = 0; i < n; i++)
	{
		cout << *(b+i) << "  ";
	}
	cout << endl;
}

//1.数组名作为函数的参数
int main01()
{
	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };

	print_arr(a);//打印数组内容
	//没有输出整个数组的值,只打印了第一个元素的值
	out_arr(a, sizeof(a) / sizeof(a[0]));


	system("pause");
	return 0;
}

//2.指针作为函数的返回值
int* getnum()//函数的类型要与函数返回值的类型相同
{
	//函数{}中定义的变量是局部变量,局部变量在函数结束后的空间会被释放
	srand(time(NULL));
	num = rand();
	return #//返回值类型是指针(地址)类型
}


int main02()
{
	int* p = getnum();
	cout << *p << endl;

	system("pause");
	return 0;
}

四、指针与字符数组

#include
#include
#include
#include

using namespace std;
//1.指针与字符数组
int main05()
{
	char a[] = "helloworld";//定义了一个字符数组,字符数组内容为helloworld\0
	//定义一个指针用来保存数组首元素的地址
	char* p = a;
	printf("%s\n", p);//打印一个字符串,要的是首个字符的地址
	printf("%s\n", p + 2);
	printf("%c\n", *(p+3));
	printf("%d\n", sizeof(a));//11
	printf("%d\n", sizeof(p));//4
	printf("%d\n", strlen(a));//10
	printf("%d\n", strlen(p));//10
	p++;
	printf("%s\n", p);//输出elloworld;
	//指针指向那个元素,打印时就从那个元素开始打印
	system("pause");
	return 0;
}



int main06()
{
	char a[] = "helloworld";
	char* p = a;
	//p = "abcdef";//字符常量存文字常量区,p中存的是字符串首元素地址,“”在使用时,取的是字符串首元素的地址



	system("pause");
	return 0;
}




//字符指针作为形参
char * my_strcat(char* scr, char* dst)
{
	int n = strlen(scr);
	int i = 0;
	while (i = strlen(dst))
	{
		scr[n + i] = dst[i];
		i++;
	}
	scr[i + 1] = 0;


	return scr;
}


int main07()
{
	char str1[128] = "hello";
	char str2[128] = "123456";
	char* my_strcat(char*, char*);
	//将str2拷贝到str1后面
	//字符数组作为形参时,不用告知数组中元素的个数,因为字符数组中最后会有结束符'\0',判断什么时候出现结束符就可以了
	;
	cout << my_strcat(str1, str2) << endl;
	system("pause");
	return 0;
}



//字符指针数组
//是一个数组,每一个元素时字符指针
int main08()
{
	int* arr[10];
	/*char* p1 = "heihei";
	char* p2 = "haha";
	char* p3 = "xixi";
	char* num[3] = { p1,p2,p3 };*/
	//char* arr[3] = { "heihei","haha","xixi" };//把三个字符串常量的首地址存在数组里面
	for (int i = 0; i < 3; i++)
	{
		cout << arr[i] << endl;//输出了三个字符串常量
	}
	cout << *arr[0] << endl;//输出结果为h;
	cout << *(arr[1] + 1) << endl;//输出结果为a
	system("pause");
	return 0;
}



//字符指针数组作为main函数参数
//.exe
//在没有给文件命令参数时,argc中保存的是1    argv中保存的是。exe文件的路径
//点击项目名称,右击选择属性-->调试-->命令参数处可以为main函数传参,各个参数的首地址存放在argv数组中
//char* argv[] = {".*.exe","hello","123456"};

//argc是执行可执行程序的参数个数
//argv是一个字符指针数组,保存的是参数(字符串)的首元素地址
int main(int argc, char* argv[])
{
	cout << argc << endl;
	cout << argv[0] << endl;
	cout << argv[1] << endl;
	cout << argv[2] << endl;
	cout << argv[3] << endl;
	system("pause");
	return 0;
}

五、指针练习

#include
#include
#include
#include

using namespace std;
//1.找出数组中第二大的数,(使用*操作数组元素个数,不要使用[])
int main03()
{
	int a[] = { 100,100,100,234,123,500,32,68,41,99,13,71 };
	int* p = a;
	int* q = (int*)(&a + 1) - 1;
	int temp = 0;
	for (int i = 0; i < (q - p); i++)
	{
		for (int j = 0; j < (q - p) - i ; j++)
		{
			if (*(p + j) > *(p + j + 1))
			{
				temp = *(p + j);
				*(p + j) = *(p + j + 1);
				*(p + j + 1) = temp;
			}
		}
	}
	cout << *(q-1) << endl;
	cout << q-p << endl;
	system("pause");
	return 0;
}



//不使用库函数,实现字符串拷贝功能
//char src[100] = "hello";
//char dst[100];  //把src的内容拷贝给dst
//函数名:void my_strcpy(char dst[],char src[]);




int main04()
{
	char src[100] = "hello";
	char dst[100] = {0};
	char* p = src;
	char* q = dst;
	int i = 0;
	for (i = 0; *(p + i) != '\0'; i++)
	{
		*(q + i) = *(p + i);
		//dst[i] = src[i];
		//q[i] = p[i];
		//*(dst+i) = *(src+i);
		//四者等价

	}
	*(q + i + 1) = '\0';//补结束符
	cout << "src= " << src << endl;
	cout << "dst= " << dst << endl;
	
	system("pause");
	return 0;
}

 

 

你可能感兴趣的:(C语言,c语言,学习)