有关字符串问题
str系列_操作函数
- strcpy 函数(copy)
- strlen 函数 (length)
- strcmp 函数 (compare)
- strcat 函数 (concatenate)
#include<stdio.h>
#include<string.h>
int main(){
char a[6]="hello";
char b[7]=" world";
char c[6];
printf("strcpy函数:%s\n",strcpy(c,a));
printf("strlen函数:%d\n",strlen(a));
printf("strcmp函数:%d\n",strcmp(a,b));
printf("strcat函数:%s\n",strcat(a,b));
}
字符串_翻转问题
害,就是想说明一下(就是我把这茬给忘了而已) 别忘了翻转之后,给新的字符串的最后加一个’\0’,因为这个时候和初始化字符串(字符数组)时不太一样,因为不会被自动添加上’\0’,挺有毛病的。
指针有关操作符
- 与号 &:取地址(引用)
- 星号 *: 取值(解引用)
- 所以,&*p == &a == p;
- 而int* p就表示p是一个整型指针变量;
#include<stdio.h>
int main(){
int i=5;
int* p=&i;
printf("%d\n\n",&*p==&i);
printf("%d",&*p==p);
}
指针变量的本质
是一个变量,存的是地址
#include<stdio.h>
int main(){
int i=5;
int* p=&i;
printf("整型变量i的地址:%d\n\n",&i);
printf("整型指针变量p存储的值:%d\n\n",p);
printf("*p的值:%d\n\n",*p);
}
指针的使用场景
值的传递
#include<stdio.h>
void change(int* p)
{
*p=*p+1;
}
int main(){
int i=6;
printf("change之前的i:%d\n\n",i);
change(&i);
printf("change之后的i:%d",i);
}
地址偏移
- “ * 和 ++ ”两者的优先级相同,需要按从右到左的顺序执行
- 所以,* p++可看成*(p++),即先执行p++,后执行* p;但因为是后++,所以先执行*p,然后等赋值完成以后,p再++。
也就是说就算是加了括号, * (p++)也是先执行*p,然后等赋值完成以后,p再++。
#include<stdio.h>
int main(){
int a[3]={1,10,100};
int b[3]={2,20,200};
int c[3]={3,30,300};
int* i=a;
int* j=b;
int* k=c;
printf("*i 是 %d\n",*i);
printf("*++i 是 %d\n",*++i);
printf("*i++ 是 %d\n",*i++);
printf("*i 是 %d\n",*i);
printf("此时a[0] 是 %d\n\n",a[0]);
printf("*j 是 %d\n",*j);
printf("*(++j) 是 %d\n",*(++j));
printf("*(j++) 是 %d\n",*(j++));
printf("*j 是 %d\n",*j);
printf("此时b[0] 是 %d\n\n",b[0]);
printf("*k 是 %d\n",*k);
printf("++(*k) 是 %d\n",++(*k));
printf("(*k)++ 是 %d\n",(*k)++);
printf("*k 是 %d\n",*k);
printf("此时c[0] 是 %d\n\n",c[0]);
}
这里面让我难以接受的就是*(p++),我的阅读理解是:先让指针p++,然后再取这个新地址上的值,害,但是发现并不是。
指针与一维数组关系
- 数组名是一个不变的量,它存了一个值,是该数组的起始地址,所以可以对它进行取值操作。
#include<stdio.h>
int main(){
int a[4]={1,6,9,10};
printf("%d\n",sizeof(a));
printf("%d\n",*(a));
printf("%d\n",*(a+0));
printf("%d\n",*(a+1));
printf("%d\n",*(a+2));
}
#include<stdio.h>
void change(int b[])
{
b[0]=66;
}
int main(){
int a[3]={1,10,20};
change(a);
printf("a[0]为:%d\n",a[0]);
}
又可以写做:
#include<stdio.h>
void change(int *b)
{
b[0]=66;
}
int main(){
int a[3]={1,10,20};
change(a);
printf("a[0]为:%d\n",a[0]);
}
指针与动态内存申请
- 需要头文件 #include<stdlib.h> 以及函数 malloc()、函数 free()
- 其中,malloc() 函数动态申请的空间为堆空间,以字节为单位,不是栈空间(数组)
- malloc() 函数返回值为void *(无类型指针),然后可以根据存储数据类型的需要,进行强制转换
- 执行free()释放内存 时必须使用 malloc() 申请时返回的指针值,不能进行任何的偏移,否则会报错
- 执行完free() 函数之后如果不进行赋值NULL,那么就会生成野指针(指针指向了一个地址是不确定的变量)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int i;
char* p;
scanf("%d",&i);
p=(char*)malloc(i);
strcpy(p,"hello world!");
puts(p);
free(p);
p=NULL;
}
栈空间与堆空间对比
- 定义数组的时候系统给分配了内存,是栈空间,随函数的完成,系统自动释放
- 利用 malloc() 函数动态申请的内存,是堆空间,必须用free() 函数,手动释放
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* print_stack(char* b)
{
char p[15];
strcpy(p,b);
puts(p);
return p;
}
char* print_malloc(char* b)
{
char* q=(char*)malloc(15);
strcpy(q,b);
puts(q);
return q;
}
int main(){
char a[]="hello world";
char* p;
p=print_stack(a);
puts(p);
printf("\n\n");
char* q;
q=print_malloc(a);
puts(q);
}
WHAT?按理说 main() 函数里的 puts( p) 不应该有输出的呀,栈空间应该是随着函数的执行结束而释放了的哇,怎么会这样,麻了。
经过查阅资料,我发现:
- 函数执行的时候有自己的临时栈。栈区存储每一个函数在执行的时候都会向操作系统索要资源,栈区就是函数运行时的内存,栈区中的变量由编译器负责分配和释放,内存随着函数的运行分配,随着函数的结束而释放,由系统自动完成。
- 但是!!如果p指针指向的内存刚好没有被其他代码破坏时,就可以正常输出出来。
所以说,我这里是刚好没有被破坏,所以才能正常输出。
字符指针与字符数组
#include<stdio.h>
#include<string.h>
int main(){
char q[6]="hello";
q[0]='H';
q="world";
printf("q[0]是:%c\n",q[0]);
char* p="hello";
p[0]='H';
p="world";
printf("p[0]是:%c\n",p[0]);
}
|