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

推荐阅读更多精彩内容