#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void pointer_access()
{
///a: 指针访问
char a[20]= {'s','d','f','g','h','j','k'};
printf("char_adr_a= %p\n",a);//数组名是首地址.6
int *ptr=(int *)a; //强制类型转换并不会改变a 的类型.
printf("int_adr_a= %p\n",a);//转换后, a的地址没发生变化.
printf("a= %c\n",*a);
ptr++;
//a++; //错误操作.
printf("ptr_adr= %p\n",ptr);
printf("ptr= %c\n",*ptr);//四个字节作为一个单位.
printf("a= %c\n",*a);//不会随着ptr 的改变而改变.
printf("\n\n");
}
void pointer_array_foreach()
{
///s: (指针+循环)遍历数组.
int array[10]= {0,1,2,3,4,5,6,7,8,9};
int *ptr1=array; //等价于: int *ptr1; ptr1=array;//定义一个指针变量,并且指针指向数组a
int i;
for(i=0; i<10; i++)
{
(*ptr1)++;
ptr1++;
}
for(i=0; i<10; i++)
printf("array[%d]= %d\n",i,*(ptr1));//用指针取数值 *(array+i)
printf("\n\n");
}
void pointer_access_overflow()
{
///d: 指针访问越界
int i;
char string[20]="You_are_a_girl";
int *ptr2=(int *)string;//前后兼容(compatible)
ptr2+=5;//移动了20 个字节
for(i=0; i<20; i++)
printf("%c",*(ptr2+i));//*(string)————只输出20个Y. 不能用*(ptr2+i),因为 ptr2是int.
printf("\n\n");
puts(string);
printf("\n\n");
/*
将指针ptr2 的值加上5 乘sizeof(int),在32 位程序中就是加上了5 乘4=20,
由于地址的单位是字节,故向高地址方向移动了20 个字节。
加5 后,ptr2 已经指向了数组a 的合法范围之外了。虽然这种情况在应用上会出问题,
但在语法上却是可以的。*/
}
void pointer_add()
{
///f: 指针+整数, 指针+指针
char aa[20]=" You_are_a_girl";
char *p=aa;
char **ptr3=&p;
printf("p= %d\n",p);
printf("ptr3= %d\n",ptr3);
printf("*ptr3= %d\n",*ptr3);
ptr3++;
printf("ptr3= %d\n",ptr3);
printf("*ptr3= %d\n",*ptr3);
//printf("**ptr3= %c\n",**ptr3);
printf("\n\n");
/*
1.一个指针ptrold 加(减)一个整数n 后,结果是一个新的指针ptrnew,
ptrnew 的类型和ptrold 的类型相同,ptrnew 所指向的类型和ptrold所指向的类型也相同。
ptrnew 的值将比ptrold 的值增加(减少)了n 乘sizeof(ptrold 所指向的类型)个字节。
就是说,ptrnew 所指向的内存区将比ptrold 所指向的内存区向高(低)地址方向移动了n 乘sizeof(ptrold 所指向的类型)个字节。
2.指针和指针进行加减:两个指针不能进行加法运算,这是非法操作,因为进行加法后,得到的结果指向一个不知所向的地方,
而且毫无意义.两个指针可以进行减法操作,但必须类型相同,一般用在数组方面,不多说了。*/
}
void pointer_expression()
{
///h: 指针表达式
int a2,b2;
int array1[10];
int *pa;
pa=&a2; //&a2 是一个指针表达式。
int **ptr5=&pa; //&pa 也是一个指针表达式。
*ptr5=&b2; //*ptr5 和&b2 都是指针表达式。
pa=array1;
pa++; //这也是指针表达式。
char *arr[20];
char **parr=arr; //如果把arr 看作指针的话,arr 也是指针表达式
char *str;
str=*parr; //*parr 是指针表达式
str=*(parr+1); //*(parr+1)是指针表达式
str=*(parr+2); //*(parr+2)是指针表达式
}
void pointer_operator()
{
///g: 运算符&和*.
int a1=12;
int b1=36;
int *p1; //p1 是一个指针,指针所指向的内容的类型为int 型. 指针的类型是int*,
//所以p1是一个返回整型数据的指针.
p1=&a1; //&a1 的结果是一个指针,类型是int*,指向的类型是
//int,指向的地址是a1 的地址。
*p1=24; //*p1 的结果,在这里它的类型是int,它所占用的地址是
//p1 所指向的地址 ,显然,*p1 就是变量a。
printf("*p1= %d\n",*p1);
printf("p1_adr= %p",&(*p1));
printf("\n\n");
int **ptr4;
ptr4=&p1; //&p1 的结果是个指针,该指针的类型是p1 的类型加个*,
//在这里是int **。该指针所指向的类型是p1 的类型,这
//里是int*。该指针所指向的地址就是指针p1 自己的地址。
*ptr4=&b1; //*ptr4 是个指针,&b1 的结果也是个指针,且这两个指针
//的类型和所指向的类型是一样的,所以用&b1 来给*ptr4 赋
//值就是毫无问题的了。
printf("**ptr4= %d\n",**ptr4);
printf("**ptr4_adr= %p",&(**ptr4));
printf("\n\n");
**ptr4=48; //*ptr4 的结果是ptr4 所指向的东西,在这里是一个指针,
//对这个指针再做一次*运算,结果是一个int 类型的变量。
printf("**ptr4= %d\n",**ptr4);
printf("**ptr4_adr= %p",&(**ptr4));
printf("\n\n");
}
void pointer_array()
{
char *str[3]= {"Hello,thisisasample!","Hi,goodmorning.","Helloworld"};
char s1[80],s2[80];
//strcpy(s,str[0]); //也可写成strcpy(s,*str);
strcpy(s1,str[1]); //也可写成strcpy(s,*(str+1));
strcpy(s2,*(str+1));
puts(s1);
puts(s2);
printf("\n\n");
/*str 是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。
(1)把指针数组名str 当作一个指针的话,它指向数组的第0 号单元,它的类型是char **,它指向的类型是char *。
(2)*str 也是一个指针,它的类型是char *,它所指向的类型是char,
它指向的地址是字符串"Hello,thisisasample!"的第一个字符的地址,即'H'的地址。
注意:
1.字符串相当于是一个数组,在内存中以数组的形式储存,只不过字符串是一个数组常量,
内容不可改变,且只能是右值.如果看成指针的话,它即是常量指针,也是指针常量.
2.str+1 也是一个指针,它指向数组的第1 号单元,它的类型是char**,它指向的类型是char*。
*(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向"Hi,goodmorning."的第一个字符'H'*/
int array[10]= {0,1,2,3,4,5,6,7,8,9};
int (*ptr)[10];
int *ptr1=&array;
ptr=&array;
int i;
for(i=0; i<10; i++)
printf("%d ",array[i]);
printf("\n");
for(i=0; i<10; i++)
printf("%d ",*(ptr+i));//显示的地址.
printf("\n");
for(i=0; i<10; i++)
printf("%d ",*(ptr1+i));
printf("\n\n");
}
void pointer_array_and_array_pointer()
{
///指针数组的传参;相当于普通的一维数组。
void print_fun011(char **str, int n)
{
int i;
for ( i = 0; i < n; i++)
printf("%s, ", *(str + i));
printf("\n");
}
void sort_fun011(char **str, int n)
{
//冒泡排序..指针数组的排序非常有趣,因为这个数组中存放的是指针,
//通过比较指针指向的空间的大小,排序这些空间的地址
int j,i;
char *tmp;
for ( i = 0; i < n - 1; i++)
{
for ( j = 0; j < n - 1 - i; j++)
{
if (strcmp(*(str + j), *(str + j + 1)))
{
tmp = *(str + j + 1);
*(str + j + 1) = *(str + j);
*(str + j) = tmp;
}
}
}
}
///数组指针:一个特殊的指针(步长特殊),指向一个数组。
void print_fun012(char(*p)[10])
{
int i;
for ( i = 0; i < 3; i++)
printf("%s, ", *(p + i));
printf("\n");
}
void sort_fun012(char(*p)[10], int n)
{
int j,i;
char tmp[10];
//选择排序
for (i = 0; i < n ; i++)
{
for (j = i + 1; j < n; j++)
{
if (strcmp(*(p + i), *(p + j))> 0)
{
strcpy(tmp, *(p + i));
strcpy(*(p + i), *(p + j));
strcpy(*(p + j), tmp);
}
}
}
}
///普通一维数组;数据类型是char [10]:(表示数组有10个元素,每个元素都是char型)
char a[10];
char *e ; //e是一个一级指针,用来接收普通的一维数组
e = a; //e每次"+1",跳过一个(char 类型),即一个字节
printf("e: %d, e+1: %d \n", e, e + 1);
///指针数组相当于普通的一维数组,不过数据类型是 char *[5]:(表示数组有5个元素,每个元素都是char 型的指针);
char *str[5] = { "sdada", "saadq", "wqeqwe", "12sda", "wq32r" };
char **w ; //w是一个二级指针,接收指针数组。 char **w = NULL;
w = str; //w 每次 "+1" 跳过1个(char *类型),即四个字节(32bit平台)。
printf("w: %d, w+1: %d \n", w, w + 1);
printf("排序前");
print_fun011(str, 5);
printf("排序后");
sort_fun011(str, 5); //数组内容重新排序(两个有本质区别,这个只是地址交换)
print_fun011(str, 5);
///数组指针:一个指向数组的指针,(这个指针带有特殊的步长)。
char str1[3][10] = { "asdqw", "123124", "xvzxc" };
char buf2[][10] = { "111111", "3333333", "222222" };
char(*q)[10]; //q是一个指针,每次 "+1" 跳10个字节(即10个char 元素)的指针。
q= str1;
// printf("q: %d, q+1: %d \n", q, q + 1);
//printf("排序前");
// print_fun012(buf2);
//printf("排序后");
sort_fun012(buf2, 3); //数组内容重新排序(这个是二维数组,行地址不能直接交换,因为它的拥有内存,
// 是一个一维数组,单纯的地址交换,将使一维数组的首地址丢失。
//print_fun012(buf2);
printf("\n");
system("pause");
/*注:
1.什么是指针数组和数组指针?
指针数组:即”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,
即这个数组的所有元素都是指针类型,在32位系统中,指针占4个字节。
数组指针:即”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,
即这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。
二者根本就是种 类型的变量。
2.指针数组传参时的使用:
传递数组的首地址,用一个指针接收这个地址。因此,指针数组对应着二级指针
void fun(char **pp);//子函数中的形参
fun(char *p[]);//主函数中的实参
3.数组指针传参时的使用:
数组指针既然是一个指针,那么就是用来接收地址,在传参时就接收数组的地址,所以数组指针对应的是二维数组。
void fun(int (*P)[4]);//子函数中的形参,指针数组
a[3][4] = {0};//主函数中定义的二维数组
fun(a);//主函数调用子函数的实参,是二维数组的首元素首地址
*/
}
void pointer_address()
{
int a[4] = {1,2,3,4};
int * p = a;
printf("*p = %d\n",*p);
printf("*(p+1)= %d\n",*(p+1));
printf("*(p+2)= %d\n",*(p+2));
printf("*(p+3)= %d\n",*(p+3));
///整型变量
int aa = 10;
int * pp;
pp = &aa; //pp 为a 的第一个字节的地址.aa= 6356748 pp= 6356744;
printf("aa= %d pp= %d\n",aa,*pp);
pp = aa; //pp 为a 的第一个字节的地址.aa= 6356748 pp= 6356744;
printf("aa= %d pp= %d\n",aa,pp);//aa= 10 pp= 10
///整型数组变量
int bb[10]={1,2,3,4,5};//bp= 6356708 bp+1= 6356716;
int *bp;
bp = &bb;
printf("bb= %d bp= %d\n",&bb,&(*(bp)));//bb= 6356708 bp= 6356708
printf("bb= %d bp= %d\n",&bb,&bp); //bb= 6356712 bp= 6356708
/*
bp[0]= 6356708 bp+0= 6356708
bp[1]= 6356712 bp+1= 6356712
bp[2]= 6356716 bp+2= 6356716
bp[3]= 6356720 bp+3= 6356720
bp[4]= 6356724 bp+4= 6356724
bb[0]= 6356708 bp+0= 6356708
bb[1]= 6356712 bp+1= 6356712
bb[2]= 6356716 bp+2= 6356716
bb[3]= 6356720 bp+3= 6356720
bb[4]= 6356724 bp+4= 6356724*/
printf("int= %d\n",sizeof(int));
}
int main()
{
//pointer_access();
//pointer_array_foreach();
//pointer_access_overflow();
//pointer_add();
//pointer_expression();
//pointer_operator();
//pointer_array();
//pointer_array_and_array_pointer();
//pointer_address();
return 0;
}