C语言基础-----(4)指针

学习内容
  • 什么是指针
  • 指针类型
  • 数组与指针
  • 指针与函数
  • 函数、指针、数组互用的注意事项
  • 字符数组与指针
  • 变量内存的分配
  • 动态分配内存
  • 指针demo之输入姓名
  • 指针demo之比较字符

1、什么是指针

指针是一个变量,这个变量只能存地址,指针变量占据8个字节空间
作用 :如果希望在函数之间传递数据a(>1)给调用者
(1)、声明时表明是一个指针变量
(2)、使用时表示是地址内中的一个值
&:取地址

2指针类型

去掉*和变量名就是指针的类型
常量指针:常量指针不可以改变指针指向的变量的值,可以改变指向的方向

int a=10;
 int const *p=&a;
 *p=20//错误,不可改变指针指向的变量的值 
 p=&b//正确,改变指针指向 

指针常量:可以改变指针指向的变量的值,但是不可以改变指向的方向

 int *const pb=&a;
 *p=20;//正确,改变变量的值
 p=&b;//错误,不可以改变指针指向的方向 
 指向常量的常量指针:既不可以改变指针指向的变量的值,也不可以指针指向的方向

int const * const pc=&a;
*pc=20;//错误,不可改变指针指向的变量的值
pc=&b;//错误,不可以改变指针指向的方向

3、数组与指针

1)不同点:
a、数组名本身没有分配内存空间
b、数组名代表数组首地址
c、数组是一片连续的内存空间
d、指针只是一个变量(存地址)
e、指针变量分配的有内存空间()
f、sizeof(指针)=8,而sizeof(int型数组名)=4
2)共同点:
a、数组成员也可以通过指针去访问
b、数组是一个指针常量,所以数组的指向不能改变==不能对数组名进行运算

4、指针与函数

通过指针间接访问某个内存
定义一个函数 什么情况下参数是指针
a、这个函数会不会改变传递过来的数据本身
b、需要改变外部的值就将变量定义为一个指针变量

  #include <stdio.h>
  void test1(int *pa,int *pb){
     (*pa)++;
     (*pb)++;
   }
   int main(){
     int a=10,b=20;
     test1(&a,&b);
     printf("a=%d,b=%d",a,b);
     return 0;
   }

5函数、指针、数组互用的注意事项

函数接收数组时,必须知道数组元素个数
函数里面是通过指针变量来接收数组的地址的
指针变量无法确定指向的内容的大小
访问数组的两种方式
1、num[3]
2、*(num+3)

  void test2(int *p,int count(数组长度)){
      for(int i=0;i<5;i++){
          p[i]++;//第1种,也可以写为p[i]+=1; 
          //*(p+i)++;第2种,也可以写为*(p+i)+=1; 
      }
  }
  int main(){
     int num[5]={1,2,3,4,5};
     test2(num,5);
     for(int i=0;i<5;i++){
          printf("%d",num[i]);
        }
      return 0;
  }

*#6字符数组与指针
用%s则当你在终端输入结束后在末尾默认加一个'\0',但如果用%c的话就需要在末尾手动添加一个'\0',来告诉编译器输入结束,且需要在数组中再添加一个'\0 '

注意:

(1)不能直接使用字符指针来接收字符串;
(2)字符指针只为这个变量分配8个字节的内存空间,这个空间只能用来存地址不能用来存具体的数据 。

例如:
#include<stdio.h>
void test3(char *p){
     for(int i=0;i<20;i++){
         scanf("%s",p[i]);   
     }   
}
int main(){
 char array[20]={};  
 //char *array;
 test3(array);
   for(int i=0;i<20;i++){
     printf("%s",array[i]);
   }
 return 0;
}

7变量内存的分配

常量字符串的内存空间有系统自动分配例如:"jack",在常量区里分配,当程序结束后才会被释放
常量区 - 常量 const int a=1;
静态区(生命周期很长)- static
栈 局部变量 inta=10 离开作用域就被自动收回
堆 自己申请的内存malloc calloc realloc,必须自己释放
注意:数组是变量,既可以作为局部变量也可以作为全局变量
静态变量只会被定义一次static

#include<stdio.h>
char* test(){
  char *name = "jack";
  return name;
} 
char *test1(){
  char name[10] = {'j','a','c','k'};
  return name;
} 
void test3(){
  static int count=0;
  count++;
  printf("%d\n",count);
}
int main()
{
  //char *p ;
  //p = test1();
  //printf("-%s\n", p);//运行错误,因为数组是局部变量,只在test1中有效,当test1执行完后
   test3();
   test3();                  //就会被释放,而这时候的p再去访问name的地址就属于不合法的访问 
 return 0;
}

8动态分配内存

动态分配内存 为什么需要动态分配内存
(1)、存储的数据需要延长生命周期
(2)、一个指针变量需要存储数据,变量本身只能存地址,不能存数据,需要分配内存空间来储存数据
(3)、如果要使用指针变量接收数据,必须先为这个指针变量分配一片指向的内存空间,有空间才能存数据,所以需要导入头文件<stdlib.h>、使用malloc申请内存空间,还可以使用realloc去动态改变已经分配的内存的大小(增加后减少)[需要告诉两个参数,一个是内存所在地,一个是加或减的大小]

注意:程序运行完之后必须手动释放内存,不然会导致内存泄漏
demo演示
#include<stdio.h>
#include<stdlib.h>
int main()
{
  char *name;
  name=(char*)malloc(10*sizeof(char));    
  if(name==NULL){
      //申请内存失败 
       exit(EXIT_FAILURE);
   } 
   scanf("%s",name);
  printf("%s",name);
  name=(char*)realloc(name,20*sizeof(char));//由原来的的10个字节增加20个字节
  if(name==NULL){
      free(name);
      exit(EXIT_FAILURE);
  } 
  free(name); 
 return 0;
}

8指针demo之比较字符串

main.cpp
#include <stdio.h>
#include"myString.h"
//scanf不能输入带空格的字符串
//只能自己定义一个输入语句的方法 
int main(){
 //1、定义两个数组保存字符串 
 char sentence[100]={};
 char word[20]={};
   //char *sdes="请输入语句";
 //char *wdes="请输入查找单词";
 
 inPut(sentence,"请输入语句"); 
 inPut(word,"请输入查找单词");  
 int count=find(sentence,word);
 printf("%d",count); 
 return 0;
}
myString.h
#include "stdio.h"
//printf(num,"请输入名称:");
void inPut(char *p,char *des);
void myScanf(char *p);
int find(char *sentence,char *word);
int length
myString.cpp
#include "myString.h"
void myScanf(char *p){
 int i=0;
 while(1){
     char c=getchar();
     if(c=='\n'){
         p[i]='\0';
         break;
     }
     p[i]=c;
     i++;
 }
}
void inPut(char *p,char *des){
 printf("%s:",des);
 myScanf(p);
}
int length(char *p){
 int i=0;
 for(;p[i]!='\0';i++){
     continue;
 }
 return i;
}
int find(char *sentence,char *word){
 int sLength=length(sentence);
 int wLength=length(word);
 
 if(sLength<wLength){
     return 0;
 }

 int start=0;
 int count=0;
 for(int i=0;i<sLength;i++){
     //记录当前位置 
     start=i;
      //从当前位置取数据与查找的单词比较
      int j=0;
      for(;j<wLength;j++){
         if(sentence[start+j]!=word[j]){
             break;
          }
      }
      if(j==wLength){
         i=start+j-1;
         count++;
      } 
 }
 //printf("%d %d",sLength,wLength);
 return count;
}

指针demo之输入姓名

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//从终端接收字符串 返回这个字符串的首地址
char *inputName(){
   //1.定义一个指针变量 指向字符串的首地址
   char *pName = NULL;
   //2.接收输入
   int i = 0;
   //3.提示操作
   printf("请输入人名:");
   while (1) {
       //接收一个字符
       char c = getchar();
       //判断这个字符是不是\n
       if (c == '\n') {
           //输入结束
           break;
       }
       //判断是不是第一个字符
       if(i == 0){
           //使用malloc分配内存
           pName = (char *)malloc(1*sizeof(char));
           //判断是否分配成功
           if(pName == NULL){
               exit(EXIT_FAILURE);
           }
           pName[0] = c;
       }else{
           //使用realloc在之前的基础上加一个
           pName = realloc(pName, (i+1)*sizeof(char));
           //判断是否分配成功
           if(pName == NULL){
               exit(EXIT_FAILURE);
           }
           pName[i] = c;
       }
       
       i++;
  }
   //将当前的字符串首地址返回
   return pName;
}

//是否继续
bool isContinue(){
   printf("是否继续(y/n)?:");
   while (1) {
       char c = getchar();
       getchar();
       if (c == 'y'){
           return true;
       }else if(c == 'n'){
           return false;
       }else{
           printf("输入格式不对,请重新输入:");
       }
   }
}
//初始化整个数组
char **initNames(int *pNum){
   //1.定义指针变量指向每个名字的首地址的内存
   char **pHead = NULL;
   
   //2.记录元素个数
   int i = 0;
   while (1) {
       //判断是不是第一个
       //第一个使用malloc分配内存
       if (i == 0) {
           pHead = malloc(1*sizeof(char *));
           if (pHead == NULL) {
               exit(EXIT_FAILURE);
           }
           
           //输入人名 将地址放到pHead对应位置
           pHead[0] = inputName();
       }else{
           //使用realloc重新再增加一个元素
           pHead = realloc(pHead, (i+1)*sizeof(char *));
           if (pHead == NULL) {
               exit(EXIT_FAILURE);
           }
           //输入人名 将地址放到pHead对应位置
           pHead[i] = inputName();
       }
       
       i++;
       
       //是否继续
       bool result = isContinue();
       if (result == false) {
           break;
       }
   }
   
   *pNum = i;
   return pHead;
}

void show(char **pHead, int num){
   printf("输入%d个名字:\n",num);
   for (int i = 0; i < num; i++) {
       printf("%s\n",pHead[i]);
   }
   printf("\n");
}

int main(int argc, const char * argv[]) {
   char **pHead = NULL;
   int count = 0;
   pHead = initNames(&count);
   show(pHead, count);
   return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容