C语言指针1

前言:指针是 C语言一个重要概念,也是C 语言的一个重要特色。使程序简洁、紧凑、高效。指针乃是C之精华。

数据在内存中的存储及读取:在程序中定义的变量,在对程序进行编译时,系统会给变量分配内存单元。编译系统根据程序定义的变量类型,分配一定长度的空间。内存区的每一个字节有一个编号,这就是“地址”,它相当于旅馆中的房间号。在地址所标志的内存单元中存放的数据则相当于旅馆房间中居住的旅客。

由于通过地址能找到需要的变量单元,因此,地址指向该变量单元。将地址形象地称为“指针”。通过指针能找到以它为地址的内存单元。

区分:存储单元的地址    和  存储单元的内容

eg:

int i ,j,k;

printf(”%d”,i)

在程序中,一般通过变量名引用变量的值、实际上,是通过变量名 i 找到存储单元的地址,从而对存储单元进行操作。

scanf(“%d”,&j)

程序运行时,把键盘输入的值送入到某一地址开始的整形存储单元中。if k = i + j;按变量名进行的运算存储的这种方式,直接按变量名进行的访问 ,称为 :直接访问

另外:将变量 i 的地址存放到另一变量中,然后通过该变量来找到变量i 的地址的方式是间接访问。

i_pointer = & i; (变量i 所占用单元的起始地址)

一个变量的地址称为该变量的 “指针”:变量 存放 另一个变量的地址 .->  变量称为:指针变量 地址变量 指针变量的值 是 地址(即地址  指针是一个地址  指针变量 是一个存放地址的变量)。

指针变量: 存放地址的变量是指针变量 ,用来指向 另一个 对象(变量、数组、函数等)通过访问指针变量 可以找到它所指向的变量,从而得到这些变量的值。

定义:

# include

int main( )

{

int a =100,b =10;

int *p1,*p2;

p1 = &a,p2 = &b;

printf(“a = %d,b = %d”,a,b);

printf(“ *p1 = %d,*p2 = %d”,*p1,*p2); //输出 a b 的值

}

其中的“*” ,表示 “指向”。*p1 表示 指针变量p1 指向的变量a.

定义时: *p1 和 *p2  表示定义两个指针变量。前面的“*” 表示该变量为指针变量。无定义时,表示的是 指针变量指向的 变量。

类型名 * 指针变量名;可定义时 初始化;

int * p1 = &a;

注:指针变量的“*”表示该变量的类型为指针型变量。

定义时,必须制定基类型。不同数据类型在内存中占据不同的存储单元。

一个变量的指针的含义:以存储单元编号表示的地址(如2000开始的字节),指向的存储单元的数据类型。float char .

指针变量只能存放地址。

2.引用指针变量

(1)、给指针变量赋值。

p = &a; //把 a的地址付给 指针变量 p;

指针变亮 p  的值 是 变量a 的地址。p  指向 a .p 是指向 整形数据的指针变量。

(2)、引用指针变量 指向的 变量。

如果执行了1  操作、即p 是指向 整形数据的指针变量。

则printf(“%d”,*p); 其作用是以整数形式输出 指针变量p  所指向的 变量的值。即变量 a 的值。

如果有赋值语句:

*p = 1; // 表示 将 整数 1 赋给 p当前 所指向的变量。 即 a = 1;

(3)、引用指针变量的值

printf(“ %o”,p); // 以八进制的形式输出指针变量的 p的值,即 a   的值。

注:1.& 取地址符 。* 指针运算符(或 间接访问  运算符)*p 代表指针变量 p   指向的对象。

eg :输入 a and b  两个整数,按大小顺序 输出 a 和 b;

# include

int main( )

{

int *p1,*p2,*p,a,b;

printf(“enter two number:”);

scanf(“%d,%d”,&a,&b);

p1 = &a;

p2 = &b;

if(a < b)

{

p = p1;p1 = p2;p2 = p; // p1 = &b;p2 = &a;不交换 整形变量的值 而是改变指针的值。

printf(“a = %d,b = %d”,a,b);

printf(“max = %d,min = %d”,*p1,*p2);

}

return 0;

}

3、指针变量 作为   函数  参数

函数的参数不仅可以使 整形 浮点型 字符~,指针类型。其作用是将一个    变量的地址   传送到 另一个函数中。

上列:定义一个函数 将指向  两个整形变量 的 指针变量 作为实参 传递给 函数的形参指针变量,在函数中 通过指针 实现交换两个变量的 值。

# include

int main (  )

{

void swap(int *p1,int * p2);

{

int a,b;

int *pointer_1,*pointer_2;

printf(“enter a and b:”);

scanf(“%d,%d”,&a,&b);

pointer_1 = &a;

pointer_2 = &b;

if(a < b) swap(pointer_1,pointer_2);

printf(“max = %d,min = %d”,a,b);

}

return 0;

}

void swap(int *p1,int *p2)

{

int  temp;

temp = *p1;

*p1 =  *p2;

*p2 = temp;( 指针前面有赋值符号 表示值  无,表示 指向的对象)

}

注:在函数传递时,将实际参数的值传递给形式参数变量,采取的是“值传递”的方式。传递后 p1 的值 为 &a.这时 ,p1 and pointer_1都指向 变量 a。调用结束后,形参 p1 p2 释放。  这改变了变量的值 、行参的值的改变不能改变实际参的值。而应该用指针变量作为函数参数,在函数执行过程中使指针变量 所指向的变量发生变化,函数调用结束后,变量值的变化 保留;

注:不能通过改变指针形参的值而使指针实参 的值 改变。

不能通过执行调用函数来改变实参指针变量的值,但是可以通过改变实参指针变量所指向的值;

eg:

# include

int main(  )

{

void exchange(int *q1,int *q2,int *q3);

int a,b,c,*p1,*p2,*p3;

printf(“enter three number:”);

scanf(“%d,%d,%d”,&a,&b,&c);

p1 = &a;p2 = &b;p3 = &c;

exchange(p1,p2,p3);

printf(“the order is:%d,%d,%d\n”,a,b,c);

}

void exchange(int *q1,int *q2,int *q3 )

{

void  swap(int *p1,int *p2);

if(*q1 < *q2 ) swap(q1,q2);

if(*q1 < *q3) swap(q1,q3);

if(*q2 < *q3) swap(q2.q3);

}

void swap(int *p1,int *p2)

{

int temp;

temp = *p1;

*p1 =  *p2;

*p2 = temp;     // 实现   交换  两个变量  的值的 函数

}

(4).通过指针引用数组

一个变量有地址,一个数组由若干个元素,每个数组元素在内存中 占用 存储单元,有相应的地址。可指变量,也可指数组(把某一元素的地址放到 一个指针变量中)。数组元素的指针 就是 数组 元素的 地址。

int a[3] = {1,2,3};

int *p;

p = &a[0];p = a//p 是数组a首元素的地址。将数组元素的首地址赋给指针变量 P。

5、引用数组元素时 指针的运算

1、在引用数组元素时,可以对指针进行如下的运算:

加一个整数,P+1;

自加运算,++P,P++;

自减运算,--P,P--;

两个指针相减,P1- P2;

(1),如果指针变量指向一个元素,P+1 指向同一数组中的下一个元素(同P-1)。+ 的是字节数哦         (~v~)

(2) P+ i 和 a +i 代表同一个地址a[ i ].  P 指向 &a[0]

(3)指针加法无意义哦

6、通过指针引用数组元素

1>下标法 如 a[i]形式。

2>指针法 如*(a+i) 或者 *(p+i).

有一个整形数组a,有十个元素,输出数组中的全部元素。

int main( )

{

int a[10];

int i;

printf(“enter ten integer number:")

for(i = 0;i < 10;i++)scanf(“%d”,&a[i]);

for(i = 0;I < 10;i++) printf(“%d”,a[i]);

printf(“\n”);

return 0;

}

// =========================================

int main( )

{

int a[10];

int i;

printf(“enter ten integer number:")

for(i = 0;i < 10;i++)scanf(“%d”,&a[i]);

for(i = 0;I < 10;i++) printf(“%d”,*(a+i);

printf(“\n”);

return 0;

}

用指针变量指向数组元素

int a[10];

int *p,i;

printf(“enter ten integer number:”);

for(i = 0;i < 10;i++) scanf(“%d”,&a[i]); // for(p = a;p < (a+10);p++) scanf(“%d”,p); 用指针变量表示 当前元素的地址

for(p = a ; p < (a +10);p++)  printf(“%d”,*p);

int main( )

{

int a[10];

int i;

printf(“enter ten integer number:")

for(i = 0;i < 10;i++)scanf(“%d”,&a[i]);

for(i = 0;I < 10;i++) printf(“%d”,*(a+i);

printf(“\n”);

return 0;

}

for 循环中 P 的值要重新赋值 。

# include

int main(  )

{

int i,a[10],*p = a;

printf(“enter ten integer numbers:”);

for(i = 0; i < 10 ;i++) scanf(“%d”,p++);

p = a;

for(“i = 0;i < 10;i++,p++”) printf(“%d”,*p);

printf(“\n”);

return 0;

}

在编译时,对下标的处理是转化为地址的: 对P[i]  处理成 *(p+i),  如果P 是指向一个数组元素 a[0], 则 p[i] 代表 a[i];

//==================

*p++ :++ 和* 同优先级  结合方向自右向左,等价于*(p++),先引用 P的值,实现*P 运算 ,然后 再使P 自加 1.

用数组名做函数参数

1、当用数组名做参数时,如果形参数组中 各元素 的值 发生改变,实参数组元素 的值 随之发生变化。cause:

void  swap (int x,int y); swap (a[1],a[2]);

当调用函数改变两个值的交换时,a[1] a[2] 的值 并不改变。实参和形参的值传递。

fun(int arr[],int n);fun(int *p,int n);只有指针变量存放地址。

、通过这种方法改变实参数组 中的值。

用函数将数组中的元素调换顺序。

行参数组名可以用数组名,也可用指针变量名。

# include

int main()

{

void inv (int x[ ],int n);

int i,a[10] = {3,1,22,88,8,0,10,20,77,89};

printf(“the original array is:”);

for (i = 0 ;i < 10; i++) printf(“%d”,a[i]);

printf(“\n”);

inv(a,10);

printf(“the array has been inverted:\n”);

for(i = 0;i < 10;i++)   printf(“%d”,a[i]);

printf(“\0”);

return 0;

}

void inv(int x[ ],int n)

{

int temp,i,j,m = (n -1)/2;

for(i = 0;i <= m;i++)

{

j = n - 1 -i;

temp = x[i];x[i] = x[j];x[j] = temp;

}

return 0;

}

//====================

# include

int main( )

{

void sort(int x[ ],int n);

int i,*p,a[10];

p = a;

printf(“enter ten integer numbers:”);

for(i = 0;i < 10;i++) scanf(“%d”,p++);

p = a;  / 重新指向a[0];

sort(p,10);

for(p = a,i = 0;i < 10;i++)

{

printf(“%d”,*p);

p++;

}

printf(“\n”);

}

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

{

if(x[ j ] > x[ k ])   k = j;

if(k != i)

{

t = x[ i ];x[ i ] = x[k]; x[k] = t;

}

}

}

}

/*

void sort(int *x,int n)

{

int j,i,k,t;

for(i = 0;i < n -1;i++ )

{

k = i;

for(j = i+1,j < n;j++)

if(*(x+j) > *(x+k)) k = j;

if(k != i))

{

t = *(x+i);*(x+i) = *x(x+k);*(x+k) = t;

}

}

}

*/

2.通过指针引用多维数组

int a[3][4] = {{1,2,3,4},{2,3,5,6}};

表示形式                 含义                                                          地址

a              |二维数组名   指向一维数组a[0], 即0行首地址|  200 0

a[0]   *(a+0) *a       0行0列 元素地址                                          2000

a[1] +2  *(a+1) +2  &[1][2]    1 行2列的地址                             2024

a[1]   *(a +1)      1行0 列的地址                                                  2016

a + 1  代表一行中全部元素占用字节数。16

a[0] + 1 中的 1 代表一个a 元素占用的字节数。4

、输出二维数组中任一行,任一列元素的值

# include

int main ( )

{

int a[3][4] = {1,3,5,7,9,11,13,15,17,19,21,23};

int (*p)[4] ,i,j;

p = a;

printf(“enter row andcolum:”);

scanf(“%d,%d”,&i,&j);

printf(“a[%d][%d] = %d\n”,i,j,*(*(p +i)+ j));

}

//========================================

# include

int main ( )

{

void search (float (*p)[4],int n);

float score[3][4] = {{65,57,70,60},{58,87,90,81},{90,99,100,98}};

search(score,3);

return 0;

}

// 定义一个函数

void search (float (*p)[4],int n)

{

int i,j,flag;

for(j = 0;j < n;j++)

{

flag = 0;

for(i = 0;i < 4;i++)if(*(*(p +j) + i ) < 60) flag = 1;

if(flag == 1)

{

printf(“No.%d fails,his score are:\n”,j+1);

for(i = 0;i < 4;i++)printf(“%5.1f”,*(*(p + j) + i);

printf(“\n”);

}

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容