【C基础】当指针作为函数的形参,实参可能是____?
当函数的形参为一级指针时,实参可以是:一级指针变量、变量的地址、常量的地址。
当函数的形参为二级指针时,实参可以是:一级指针的地址,二级指针变量、指针数组int* parr[10]。
总结: ??① 值传递:形参是实参的一份临时拷贝,形参与实参无任何关联,在函数中对形参进行修改不影响外部的实参。 ??② 址传递:形参实际就指向实参,在函数中对形参指向的空间中的内容修改,实际就是修改实参本身。 ??③二级指针传递:要对指针进行操作或者修改,传参时,实参应是该指针的地址,形参用二级指针来接收。
指针即为地址(地址是个数),而指针变量是存放地址的变量(包含两个方面,一是以存储单元编号表示是的纯地址,二是指向的存储单元的数据类型(int,char,floar等)) 指针几个字节跟语言无关,而是跟系统的寻址能力有关。 指针初始化随机指向一个未知存储单元,一定初始化指向NULL,不然随机向一片未知存储单元赋值十分危险 ??譬如32位系统,是4个字节,64位系统,是8个字节。
1)指针的含义 ??指针不同于一般变量,存的是变量的地址,在同一架构下地址长度都是相同的(cpu的最大寻址内存空间),所以不同类型的指针长度都一样比如说一个char 1字节,可以存在0x0,也可以位于0xFFFFFFFF,比如你的32位系统。 2)指针的范围 ??指针长度为4,在64位操作系统下那么就都是8了,而和char占用1字节还是100字节无关,指针的范围只和机器字和系统有关。 3)变化的范围 ??如果你输出的是666,说明指针长度为4字节可以记录的地址范围是0x00000000~0xFFFFFFFF,这个范围才是指针变量的值。 4)指针的介绍 ??指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型、指针所指向的类型、指针的值(或者叫指针所指向的内存区)、指针本身所占据的内存区。
举例说明一级指针作为形参
1.比如形参是char*,函数是void function(char* a)
实参可以是指针
char* p;
function(p);
也可以是地址
char c;
function(&c);
也可以是数组名
char m[10];
function(m);
也可以是字符串
function("Hello world!");
实际上
指针,是指针变量
地址,是指针常量
数组名,是指针常量
字符串,是数组,所以也是指针常量
补充:想引用一个字符串两种方式 1.char string[]="Hello World!";未指定长度,由于初始化了,因此长度确定,长度13,最后一个存储‘\0’。
2.char *string="Hello World!";未指定字符数组,只定义了一个char *型的指针变量,用字符串Hello World!
对它进行初始化,C语言中对字符常量是按字符数组处理的,在内存中开辟一个字符数组用来存放该字符串变量,
当这个字符数组没有名字,因此不能通过数组名引用,只能通过指针变量来引用
二者区别如下:
1.字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址)
,绝不是将字符串放到字符指针变量中
2.赋值方式,可以对字符指针变量赋值,但不能对数组名赋值
char *string; string="Hello World!"
char string[10]; string="hello"
3.初始化含义
char *a,str[10]; a=str; scanf("%s",a);
char *string="Hello World!" 等价char *string; string="Hello World!"
char *string="Hello World!" 不等价 char *string; *string="Hello World!"
如果再赋值string ="Hello china" ,指针不会再指向"Hello World!" 第一个字符.
4.存储单元的内容,编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元
(32位系统4个字节,64位8个字节)
5.字符数组中个元素是可以改变(可进行再赋值),但字符指针变量指向的字符串常量中的内容是不可再被取代(不可进行赋值)
char []="Hello world!";
char *b="Hello china";
a[2]='r';
b[2]='r';
2.比如形参是结构体指针
typedef struct student{
int id;
char name[10];
float score;
};
void chang_struct(struct student *s){
strcpy(s->name,"李六");
}
int main(){
struct student s={1,"张三",20};
chang_struct(&s);
printf("%d,%s,%f",s.id,s.name,s.score);
return 0;
}
静态建立链表,所有结点都是在程序中定义的,不是临时开辟的,也不能用完后就释放
#include <stdio.h>
#include<string.h>
typedef struct student{
int id;
char name[10];
float score;
struct student *next;
};
void print(struct student *p){
while(p!=NULL){
printf("p->id=%d,p->name=%s,p->score=%f\n",p->id,p->name,p->score);
p=p->next;
}
}
int main(){
struct student a,b,c,*head,*p;
a.id=1;strcpy(a.name,"张三");a.score=100;
b.id=2;strcpy(b.name,"李四");b.score=100;
c.id=3;strcpy(c.name,"王五");c.score=100;
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL;
p=head;
print(head);
return 0;
}
举例说明二级指针作为形参
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct student{
int id;
char name[10];
float score;
struct student *next;
};
struct student* creat(int N){
int i=0;
struct student *head,*p;
head=p=NULL;
head=(struct student *)malloc(sizeof(struct student));
head->next=NULL;
while(i<N){
p=(struct student *)malloc(sizeof(struct student ));
scanf("%d,%[^,],%f",&(p->id),p->name,&(p->score));
p->next=head->next;
head->next=p;
i++;
}
return head;
}
void print(struct student *p){
while(p!=NULL){
printf("p->id=%d,p->name=%s,p->score=%f\n",p->id,p->name,p->score);
p=p->next;
}
}
void Delete_chang(struct student **head){
(*head)->next=(*head)->next->next;
}
int main(){
struct student *stu=creat(3);
print(stu->next);
Delete_chang(&stu);
print(stu->next);
return 0;
}
|