C语言指针(四)
通过指针引用字符串
字符串的引用方式
- 用字符数组存放一个字符串,可以通过数组名和小标引用字符串中的一个字符,也可以通过数组名和格式声明“%s”输出该字符串
比如
char string[]="I Love China";
printf("%s\n",string)
其中字符串数组名string是指针变量,指向内存给字符串开辟地址的首地址。内存中,字符串的最后自动加了一个‘\0’。在输出项中给出字符指针名string,则系统会输出string所指向的字符串第一个字符,然后自动使指针变量string加1,使之指向下一个字符,直到遇见字符串结束标志‘\0’为止。但是对于数值型数组,只能一个个输出
- 用
字符指针变量
指向一个字符串常量,通过字符串指针变量引用字符串常量。
比如
char *string="I love China!";
//char *string;
//string="I love China";
print("%s\n",string);
数组没有名字,字符指针变量string指向不知名数组的首元素地址。C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组来存放字符串常量,但是这个字符数组是没有名字的。因此不能用数组名来引用,只能通过指针变量来引用。这时的string是指针变量,不能对string进行在赋值,一旦进行在复制,那他代表的地址就是新字符串的首地址了,如下:
int *string=“I love china”;
string="you are beautiful";
上边的例子指针变量string已经指向了新字符串
int a[2] = { 1,2 };
int* p;
p = a;
printf("%d", *p);
上面的代码就是把数组a的首地址赋给了指针变量p,以此类推string="I love China"就是把字符串数组首元素地址赋给了指针变量string。只不过表达形式不一样,人家没有名字,只能这样。就比如有一个班级40个人拍成一列,如果有班级名字我就说莫某班不错,但是如果没有班级的名字,我就只能说这一列学生不错。
对字符串中字符的存取
可以使用下标的方法,也可以使用指针的版办法。
实例1
字符串a复制为字符串b
#include<stdio.h>
int main()
{
char a[] = "I am a student.", b[20];
int i;
for (i = 0; *(a + i) != '\0'; i++)
{
*(b + i) = *(a + i);
}
*(b + i) = '\0';
printf("string a is:%s\n", a);
printf("string b is:");
for (i = 0; b[i] != '\0'; i++)
{
printf("%c", b[i]);
}
printf("\n");
return 0;
}
实例2
上边的例子
#include<stdio.h>
int main()
{
char a[] = "I am a student.", b[20];
char * p1, * p2;
p1 = a;
p2 = b;
for (; *p1 != '\0'; p1++, p2++);
{
*p2 = *p1;
}
*p2 = '\0';
printf("string a is:%s\n", a);
printf("string b is:%s\n", b);
return 0;
}
字符指针做函数参数
用字符数组名作为函数参数
int main()
{
void copy_string(char from[], char to[]);
char a[] = "I am a teacher";
char b[] = "you are a student";
copy_string(a, b);
printf("a:%s", a);
printf("b:%s", b);
}
void copy_string(char *from, char to[])
{
int i = 0;
while (from[i] != '\0')
{
*(to+i) = from[i]; i++;
}
to[i] = '\0';
}
用字符型指针变量做实参
int main()
{
void copy_string(char from[], char to[]);
char a[] = "I am a teacher";
char b[] = "you are a student";
char *from=a,*to=b;
copy_string(from, to);
printf("a:%s", a);
printf("b:%s", b);
}
void copy_string(char from[], char to[])
{
int i = 0;
while (from[i] != '\0')
{
*(to+i) = from[i]; i++;
}
to[i] = '\0';
}
用字符指针变量作形参和实参
int main()
{
void copy_string(char *from, char *to);
char *a = "I am a teacher";
char b[] = "you are a student";
char *p=b;
copy_string(a, p);
printf("a:%s", a);
printf("b:%s", b);
}
void copy_string(char *from, char *to)
{
int i = 0;
while (from[i] != '\0')
{
*(to+i) = from[i]; i++;
}
to[i] = '\0';
}
使用字符指针变量和字符数组的比较
int a[3] = { 1,2,3 };
int* p;
// p = a;
printf("please input a num:");
scanf_s("%d\n", p);
for (int i = 0; i < 3; i++)
{
printf("%d", *(a + i));
}
错误C4700 使用了未初始化的局部变量“p”
在编译的时候还给指针变量a分配了储存单元,变量a的地址是已经指定的,但是a并未被赋值,在a的储存单元中是一个不可预料的值,在执行scanf的时候,要求将一个数输入到a所指向的一段储存单元,但是因为我们根本不知道a现在指向那里,所以很危险。如果a现在指向一个空白的出储存单元的话还好,如果a指向了已经存放指令或者数据的有用内存段,就会破坏程序或者有用数据,甚至破坏系统。vs编译中为了避免出现这种破坏系统的危险行为,就在底层这样设置了,指针变量不初始化赋值就无法进行写数据。
- 编译的时候,字符数组分配若干的储存单元,以存放各元素的值。而对字符指针变量,只分配一个储存单元(用来储存数组某元素的地址)
- 指针变量的值是可以改变的,而字符数组名代表一个固定的值(数组首元素的地址),不能改变
char *a=”I love you“;
a=a+7
这是可行的,只是指针变量值发生变化,改变了指向
char a[]={"I love you"}
a=a+7
这种写法是错误的
- 字符数组各个元素是可以改变的,但是字符指针常量指向的字符串常量种的内容是不能改变的
-可以对字符指针变量进行赋值,不能对数组名进行赋值