第一章. 指针基础知识

1. 内存地址和内存空间

学习指针的相关知识,首先需要了解下内存。我们通常所说的内存,往往指的是内存空间。其实内存是由内存地址和内存空间共同组成的,且内存地址和内存空间是一一对应的。

内存地址是一个编号,代表一个内存空间的位置。
内存空间是存储数据的空间,真正保存数据的地方。
在计算机中存储器的容量是以字节为基本单位的。也就是说一个内存地址代表一个字节(8bit)的存储空间。

内存地址对应内存空间.png

有个非常形象的比喻:
内存就像小区房子一样,内存地址代表房子的门牌号,内存空间是房子内居住的空间。
已经被出售了的,代表空间被申请占用了;
已经办理入住的,代表空间被数据写入;
正在出售的,代表此空间空闲;

2. 指针相关表示方法

  • 2.1 指针,指向某空间的标记,比如:

    char *charPointer —> charPointer是指向 char 类型的指针。char 内存中占用一个字节内存空间,charPointer指向了这个字节的内存地址

    int *intPointer —> intPointer是指向 int 类型的指针。int 内存中占用四个字节内存空间,ntPointer指向了这个四个字节中首字节的内存地址。

  • 2.2 取地址
    符号 &,可以帮助我们获取相关内存中的地址。
    指针就是先申请内存空间,然后把指向这个数据内存的首地址存入申请的内存空间。
    所以指针必须初始化才有意义。

 int a = 1;

 int *d ; //申请一个可以保存 int 类型内存地址的指针
 d = &a;// 把 a 的地址赋值给指针

 printf("%d \n", a); // log结果:1
 printf("%p \n", &a); //log结果:0x7ffeefbff59c 
 printf("%lu \n", sizeof(a)); //log结果:4

 printf("%p \n", d); //log结果:0x7ffeefbff59c
 printf("%lu \n", sizeof(d)); //log结果:8
  • 2.3 解引用
    我们已经知道指针的内存空间中保存了相关的数据,那么怎么来使用这个数据呢?这里需要的就是解引用,也就是间接访问。
    需要注意的是:
    NULL 指针 :什么都没有指向的指针(默认 NULL = 0)
 int a = 1;
 int *d ; 
 d = &a;

printf("%d \n", a); // log结果:1

*d = 5;  //这里就是解引用(间接访问) :* 这个 * 是解引用指针
printf("%d \n", a); // log结果:5

3. 指针的相关运算

通过取地址,指针,解引用……相关的表示,我们衍射出很多相关的运算

  • 3.1 通过指针操作相关的变量
 int a = 12;
 int *d = &a;// 创建指针 指向a的地址
        
*d = 10 - *d;//  这里其实就修改了a变量

 printf("%d \n",a); // log 结果:-2
//先取地址 然后解引用
 *&a = 25;// 这行等价于 a = 25;
 printf("%d \n",a);// log 结果:25
 printf("%p \n",&a);// 取a 的地址::0x7ffeefbff59c
 //对这个地址数值进行操作
 *(int *)0x7ffeefbff59c = 20; // (int *)0x7ffeefbff59c ->代表指针常量,这个是把内存地址强转成一个指针

 printf("%d \n",a);//打印结果 :a = 20;
  • 3.2 多级指针
    多级指针是指,把一个变量的地址赋值给一个指针,然后把这个指针的地址又赋值给新的指针……

    多级指针的解引用,也是一层层通过相关的地址找到最终变量,然后才能对变量进行相关操作

 int a = 12;
 int *b ;
 b = &a;

 int **c;//指向指针的指针 :指向指针的地址
 c = &b;
        
/* 解引用: **
第一个* 指向b 的内存地址,得到指针b
第二个* 指向a 的内存地址,得到变量a
*/
  **c = 25;

  printf("%d \n",a);//打印结果 :a = 25;
  • 3.3 练习指针的++,--
char c1,c2,c3;
char *cp;
//定义初始化函数
void setup() {
     c1 = 'a';
     c2 = 'f';
     c3 = 'c';
  
   cp = &c1;
}

int main(int argc, const char * argv[]) {

 setup();
 printf("%c : %c : %c \n",c1,c2,c3);//a : f : c 
 printf("%p : %p : %p \n",&c1,&c2,&c3);//0x100001030 : 0x100001031 : 0x100001032 
 printf("%p : %p \n",&c1,cp);//获取 c1 cp 地址:0x100001030 : 0x100001030
 printf("%p \n",&cp);//指针的地址:0x100001038
 printf("%c \n",*cp);//指针指向的地址:a
 printf("%c \n",*cp + 1);//指针指向的地址:b ;原因:a的asc值97 ,97+1 = 98 (b的asc值)
 printf("%p : %p \n",cp + 1,&c2);//指针指向的地址:0x100001031 : 0x100001031 
 printf("%c \n",*(cp + 1));//指针指向的地址:f : 原因:指针指向的内存地址 + 1,指向了下一个byte的内存
 printf("%p : %p \n",++cp,&c2);//0x100001031 : 0x100001031

// 练习 // 结果:
  setup();
  printf("%c \n",*cp);//a
  printf("%c \n",++*cp);//b 
        
  setup();
  printf("%c \n",*cp++);//a
        
  setup();
  printf("%c \n",*(cp + 1));//f

  setup();
  printf("%c \n",++*cp++);//b

  setup();
  printf("%c \n",++*++cp);//g

}

4. 指针与字符串

字符串指针->指向的是字符串第一个字符的内存地址;
字符串都是以"\0"结尾;

计算字符串长度的demo:

// 计算字符串长度
int my_strlen(char *string){
    int length = 0; 
    while (*string++ != '\0') {
        length++;
    }
    return length;
}

int main(int argc, const char * argv[]) {

        char *name = "bill gates";  //指向字符串:指向的是第一个字符;
        printf("%s \n",name);//bill gates 

        unsigned long length = strlen(name);  // 字符长度 c系统自带函数
        printf("%lu \n",length);//10
     
        //自定义函数
        int myLength = my_strlen(name);
        printf("%d \n",myLength);//10
}

查找字符串中的某个字符demo

//查找字符串
int find_char(char **strings,char word,int count){ 
    char *string ;
    char character;
    int  num = 0;
    while ((string = *strings++) && num++ < count) {
        while ((character = *string++ ) != '\0') {
            if ( character == word ){
                return 1;
            }else{
                printf("继续查找……%c \n",character);
            }
        }
    }
    return 0;
}
int main(int argc, const char * argv[]) {

        char *s0 = "zero", s1 = "first", s2 = "second",s3 = "third",*s4 = " ";
     
        int total = 5;
        char *strs[total];
        strs[0] = s0;
        strs[1] = s1;
        strs[2] = s2;
        strs[3] = s3;
        strs[4] = s4;
    
        char word = 'a';    //查找词
        
        if ( find_char(strs, word,total) ){
            printf("find_char :%c \n",word);
        }else{
            printf("unfind_char :%c \n",word);
        }
}

5. 指针的运算常在数组中使用

算数运算:指针 +(-) 整数 ,指针 - 指针(只限于指向同一数组的指针)
单独的两个指针进行 加减乘除 是没有意义的

关系运算(只限于指向同一数组的指针): >, >=, <, <=, !=, ==

// 遍历数组
void logArray(char arr[],int count){
    for(int i = 0 ;i < count ; i++){
        printf("%d : %c \n",i,arr[i]);
    }
}
int main(int argc, const char * argv[]) {
   char *cp;
   int total = 5;
   char characters[total];
 /*cp < &characters[total];
  指针的逻辑比较
*/ 
    for (cp = & characters[0]; cp < &characters[total]; cp++) {
       *cp = 'a';
    }
        
    logArray(characters, total);
        
     char * cBegin = &characters[0];
     char * cEnd = &characters[total];
        
      for (cp = cEnd; cp >= cBegin; cp--) {
            *cp = 'b';
      }
        
     logArray(characters, total);

 /*long count = cEnd -cBegin;
 指针的加减,判断数组中元素间隔的距离
*/ 
      long count = cEnd -cBegin;
      printf("array count : %ld \n",count);
}

6. 指针和函数

  • 6.1 函数的返回值可以是指针
int* find_intValue(int arr[] ,int arr_count ,int value ){
    
    for (int i = 0 ; i
  • 6.2 函数的参数也可以是指针
// 数据交换
void swap_0(int a ,int b){
    int temp = a;
    a = b;
    b = temp;
}
void swap_1(int *a ,int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
int main(int argc, const char * argv[]) {
   //交换
        int m = 10;
        int n = 20;
        
// 传值 操作,并不能完成数据的交换 
//参数把数值拷贝一份,函数内部进行了交换,不会影响到外部;
        printf("swap_0交换前 m= %d : n= %d \n",m,n);
        swap_0(m, n);
        printf("swap_0交换后 m= %d : n= %d \n",m,n);
// 传址 操作,才能完成数据的交换
//参数把地址拷贝一份,函数内部根据地址获取变量进行了交换,所以在内存中数据发生了交换
        printf("swap_1交换前 m= %d : n= %d \n",m,n);
        swap_1(&m, &n);
        printf("swap_1交换后 m= %d : n= %d \n",m,n); 

/*log结果:传值操作和传址操作是明显不同的
swap_0交换前 m= 10 : n= 20 
swap_0交换后 m= 10 : n= 20 
swap_1交换前 m= 10 : n= 20 
swap_1交换后 m= 20 : n= 10 
*/
}

你可能感兴趣的:(第一章. 指针基础知识)