注意:int pointer不是取值操作符,只是一个声明指针的操作符号
下边pointer才是取值操作符
指针变量是变量,指针是地址
*号表示从p的内存单元中所指的地址中读取内容
定义格式:类型标识符 *指针变量名
说明
1)号用于定义指针变量,但指针变量名不包括号
2)一个指针变量只能指向同一类型的变量
3)指针变量本身是整型的,指针变量本身也有自己的地址,占四个字节
取地址运算:用&变量名可以取得该变量的物理地址取内容运算:用*指针表达式取得指针变量内存单元存储中存的另一个内存地址里的值给指针变量赋值
1)指针变量使用前必须要有值
2)指针变量的数值必须是地址值,不能直接用一个整型赋值
3)定义格式:int a, *p =&a;或int a,*p; p=&a; 4)可以给指针赋空值,此时指针不指向任何变量:p=NULL;
*只是表示它是指针
这里需要和数组一起理解。 C中的数组实际上定义的是一个指针为首元素地址向后依次移动元素数据大小的字节,取得该元素的地址所以必须规定指针所指数据类型,从而保证对数据访问的完备性
#include <stdio.h>
void exchange(int *q1,int *q2,int *q3)//int *q1=p1
{
void swap(int *pt1,int *pt2);//如果a<b<c
//去调用函数 ,用于交换&……&%
if(*q1<*q2)
{
swap(q1,q2);
}
if(*q1<*q3)
{
swap(q1,q3);
}
if(*q2<*q3)
{
swap(q2,q3);
}
}
void swap(int *pt1,int *pt2)
{
int pt;
if(*pt1<*pt2){
pt=*pt1;
*pt1=*pt2;
*pt2=pt;//记得加*号只有在取地址和定义函数里边的时候不用加星号
}
}
int main()
{
void exchange(int *q1,int *q2,int *q3);//使得a>b>c
int a,b,c,*p1,*p2,*p3;
scanf("%d,%d,%d",&a,&b,&c);
p1=&a;
p2=&b;
p3=&c;
exchange(p1,p2,p3);
printf("%d>%d>%d",a,b,c);
return 0;
}
取p=&a【3】,即为取了第三个数组
我去试了下,p++是a的地址+4,不知道就动手 哈~
整型地址加了4,就相当于数组的下一个元素了
+i表示指向第i个元素
p=a等价于p=&a【0】
指针本质也是个变量,在自己的物理地址里存的是别人的物理地址 物理地址是个数字,所以可以对指针进行算数运算
/*a+10是指向a[10];的
p<(a+10)就是p的地址通过p+=1;依次往后加,但要小于a[10]的地址
实际上for(p=a ; p<(a+10) ; p+=1) 就相当于
for( i=0; i<10; i++ )
printf("%d ", a[i] );
现在相当于是将指针p指向a[0],然后p指向的地址依次变成a[1]……a[9];*/
//p=a等价于p=&a【0】 数组名存放的就是首元素的物理地址
//a+10是地址范围
//将*p指向数组的首地址 ,此处将p这个指针指向了a的首地址
//p++表示每次指向下一个单元的位置
int main()
{
int *p,i,a[10];
p=a;
for(i=0;i<10;i++)
{
scanf("%d",p++);
}
printf("\n");
p=a;
/*因为第一个for循环将p的值增加了十次,
即指针P不再指向原来的数组,
所以输出的不是你输入的10个数
也可以改成p =p-10;*/
for(i=0;i<10;i++,p++);
{
printf("%d\n",*p);
}
return 0;
}
//出问题了,我也不知道哪里出问题了,和rt的编程明明一模一样qaq
之前调用使用数组下标来做索引,现在改为用指针来做索引
#include <stdio.h>
int reverse(int *x,int n)//获取的是一个指针变量
{
int *p,temp,*i,*j,m;
m=(n-1)/2;
i=x; //i指向数组的第一个元素(地址)
j=x+n-1; //j指向数组的最后一个元素
//因为这个数组是从零开始索引的,所以需要减一
p=x+m; //m等于中间的值 ,指向中间配对
for(;i<=p;i++,j--)
{
temp=*i;
*i=*j;
*j=temp;
}
}
int main()
{
int i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The original array:\n");
for(i=0;i<10;i++)
{
printf("%d",a[i]);
}
printf("\n");
reverse(a,10);//作用使得数组重新倒叙排放
//传递的依旧是这个数组的数组名
printf("the array has been inverted:\n");
for(i=0;i<10;i++)
{
printf("%d",a[i]);
}
printf("\n");
return 0;
}
/*数组0,4,9三个地址,然后进行值交换.主函数数组首地址传过去相当于
数组首地址传过去程序自动识别为指针指向了数组的首地址
两种方法都是穿的地址过去的两个变量分别是数组首地址和数组个数
*/
数组名a相当于此数组的地址。。。
a[0]的地址传给指针变量*p,此时*p为定义,不是取值
#include <stdio.h>
void sort(int x[],int n)
{int i,j,k,t;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(x[j]>x[k])
{
t=x[j];
x[j]=x[k];
x[k]=t;
}
}
}
}
int main()
{
int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The original array:\n");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
p=a;
sort(p,10);
printf("the result is:\n");
for(p=a,i=0;i<10;i++)
{
printf("%d ",*p);
p++;
}
printf("\n");
}
{
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
printf("a=%d\n",a);//a的地址,a【0 】【0】的地址,也是此二维数组的地址
printf("*a=%d\n",*a);//表示的是这一个指针变量,与下边的a【0】相同
printf("a[0]=%d\n",a[0]);//不是0哦!!!!
printf("&a[0]=%d\n",&a[0]);
printf("&a[0][0]=%d\n",&a[0][0]);//前五个都指向同一个地址,只是表达不相同
printf("a+1=%d\n",a+1);//指第二行的第一个地址
printf("*(a+1)=%d\n",*(a+1));
printf("a[1]=%d\n",a[1]);
//只有在输出a【1】【0】的时候才会输出4,就是要把名称写全
printf("&a[1]=%d\n",&a[1]);
printf("&a[1][0]=%d\n",&a[1][0]);
printf("a+2=%d\n",a+2);//指向a【2】【0】的地址
printf("a[2]=%d\n",a[2]);//同上
printf("a[1]+1=%d\n",a[1]+1);//指向a【1】【1】的地址
printf("*(a+1)+1=%d\n",*(a+1)+1); //同上
printf("*(a[1]+1)=%d\n",*(a[1]+1));//取a【1】【1】的地址
printf("*(*(a+1)+1)=%d\n",*(*(a+1)+1));//取此值
return 0;
}
所以多维数组指的是在一维数组上边的扩展,并不是真正的多维数组
对二维数组,如果不出现降维符“【】”或“*”,指向二维数组出现一个降维符号指向一维数组,出现两个则指向元素即数值,而a【1】【2】则是元素值
小心别忘了\0这个元素
#include <stdio.h>
void copy_string(char *from,char *to)
{
while((*to=*from)!='\0')
{
to++;
from++;
}
*to='\0';
}
/*错因::while(*(from+i)!='\0')
{
*(to+i)=*(from+i);
i++;
}
*to='\0';
}*/
int main()
{
void copy_string(char *from,char *to);
char *a="im a student";
char b[]="you are a liar";//*b就不能运行
/*因为是b背写(被copy了) ,
如果使用指针变量来存放一段字符串,
他是直接将一段字符串的偏移地址存放,是整句整句的存放
而数组是一个字符一个字符的存放。
指针存放地址是一个常量区,我们不能去改变常量区的值*/
printf("string a == %s\nstring b=%s\n",a,b);
printf("copy string a to string b:\n");
copy_string(a,b);
printf("\nstring a=%s\nstring b=%s\n",a,b);
return 0;
}
字符串在内存中存储在常量里面。这样写相当于把常量的地址给数组,然而数组的地址是不可以修改的。而非单纯的乱码等价的问题
这个字符数组已经是定义好了的了,我们完全可以把输入的字存放到这个字符串里边去
正解: 错误原因是:未初始化就使用了局部指针变量a !
想要输出字符串后边的部分,直接+相应的数目即可,不用*,这样去的仅仅只是一个字符的地址。
#include <stdio.h>
int main()
{
int max(int,int);
int min(int,int);
int add(int,int);
void process(int x,int y,int(*fun)(int,int));
int a,b;
printf("endter a and b:");
scanf("%d%d",&a,&b);
printf("max=");
process(a,b,max);
printf("min=");
process(a,b,min);
printf("sum=");
process(a,b,add);
return 0;
}
int max(int x,int y)
{
int z;
if(x>y)
{
z=x;
}
else
{
z=y;
}
return z;
}
int min(int x,int y)
{
int w;
w=x<y?x:y;
return w;
}
int add(int w,int z)
{
int x;
x=w+z;
return x;
}
void process(int x,int y,int (*fun)(int,int))
{
int result;
result=(*fun)(x,y);
printf("%d\n", result);
}
process函数不需要用if判断指针指向的函数,int main主函数里面已经给指针赋予了一个新函数,直接用指针函数就行
#include <stdio.h>
int *search(int (*stu)[4]); //定义搜索函数
int main()
{
int stu[3][4], i, j, *p;
for (i=0; i<3; i++)
for (j=0, printf("Please enter No.%d student score: ", i+1);
j<4; scanf("%d", &stu[i][j++])); //输入全部学生成绩
for (i=0; i<3; i++){ //循环判断3个学生的成绩
p=search(stu+i); //调用搜索函数
if (p==*(stu+i)){
for(j=0, printf("No.%d student is fail!\nScore: ", i+1);
j<4; printf("%d ", *(p+j)), j++); //输出不及格成绩的学生成绩及学生号。
printf("\n");
}
}
return 0;
}
//搜索函数
int *search(int (*stu)[4])
{
int *fail, i;
for (i=0, fail=NULL; i<4; *(*stu+i)<60 ? fail=*stu, i++ : i++);
return fail;
}
法二:
#include <stdio.h>
int main(void)
{
float score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
float *search(float (*p1)[4]);
float *p;
int i,j;
for(i=0;i<3;i++)
{
p=search(score+i);//如果不及格就返回score[i][0]的地址,否则返回null
if(p==*(score+i))//如果没有小于60的就返回null
{
printf("%d\tscore:",i);
for(j=0;j<4;j++)
{
printf("%f\t",*(p+j));
}
printf("\n");
}
}
return 0;
}
float *search(float (*p1)[4])//判断成绩是否及格
{
int i=0;
float *pt;
pt=NULL;
for(;i<4;i++)
{
if(*(*p1+i)<60)
{
pt=*p1;
}
}
return pt;
}
重点通常在后边
#include <stdio.h>
#include <stdlib.h>
void main (int argc, char *argv[])
{
int i;
printf ("the number of string is : %d\n", argc-1);
for(i=1; i < argc; i++)
{
printf ("the string %d is : %s\n", i, argv[i]);
}
}
argc是int型的,它用来存放命令行参数的个数,argv是一个一维的一级指针数组,它是用来存放命令行中各个参数和命令字的字符串,这些都包含文件名
/* MEMCPY.C: Illustrate overlapping copy: memmove
* handles it correctly; memcpy does not.
*/
#include <memory.h>
#include <string.h>
#include <stdio.h>
char string1[60] = "The quick brown dog jumps over the lazy fox";
char string2[60] = "The quick brown fox jumps over the lazy dog";
/* 1 2 3 4 5
* 12345678901234567890123456789012345678901234567890
*/
void main( void )
{
printf( "Function:\tmemcpy without overlap\n" );
printf( "Source:\t\t%s\n", string1 + 40 );
printf( "Destination:\t%s\n", string1 + 16 );
memcpy( string1 + 16, string1 + 40, 3 );
printf( "Result:\t\t%s\n", string1 );
printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );
/* Restore string1 to original contents */
memcpy( string1 + 16, string2 + 40, 3 );
printf( "Function:\tmemmove with overlap\n" );
printf( "Source:\t\t%s\n", string2 + 4 );
printf( "Destination:\t%s\n", string2 + 10 );
memmove( string2 + 10, string2 + 4, 40 );
printf( "Result:\t\t%s\n", string2 );
printf( "Length:\t\t%d characters\n\n", strlen( string2 ) );
printf( "Function:\tmemcpy with overlap\n" );
printf( "Source:\t\t%s\n", string1 + 4 );
printf( "Destination:\t%s\n", string1 + 10 );
memcpy( string1 + 10, string1 + 4, 40 );
printf( "Result:\t\t%s\n", string1 );
printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );
}
#include <stdio.h>
void main(void)
{
const char *str= "Welcome to Fishc.com!\n\n";
// 这个语句的含义是:声明一个名为str的指针变量,
// 它指向一个字符型常量,初始化str为指向字符串
// "Welcome to Fishc.com!\n\n"
printf("\n\n%s", str);
#if (1)
str[0] = 'w'; //这条语句是错误的,但可以改变str指针的值
#endif
str = "I love Fishc.com!\n\n"; //合法!
printf("\n\n%s", str);
#include <stdio.h>
void main(void)
{
char * const str = "Welcome to Fishc.com!\n\n";
// 常量指针是一个固定的指针,不可以改变它的值,但它所指的数据可以改变。
str[0] = 'w'; //合法!
#if( 1 )
str = "I love Fishc.com!\n\n"; //非法!!
#endif
printf("\n\n%s", str);
}
可以定义const常量,具有不可变性。例如:const int Max=100; Max++会产生错误
const在*后表示地址为变量,该地址指向的值是可变的
#include <stdio.h>
void main(void)
{
const char * const str = "Welcome to Fishc.com!\n\n";
// 常量指针是一个固定的指针,不可以改变它的值,但它所指的数据可以改变。
str[0] = 'w'; //非法!
str = "I love Fishc.com!\n\n"; //非法!!
printf("\n\n%s", str);
}