C语言中的指针pointer,* 和 &

2019-10-09  本文已影响0人  莹子说她想吃烤冷面

指针

变量是一块内存区域,而计算机通过“地址”来访问内存(变量),用来表示“地址”的变量叫做“指针”。*x 用来获取地址为x的变量,&x 用来获取x的内存地址。

#include <stdio.h>
int main(int argc, const char * argv[]) {
    int a; //一个名叫a的整数变量(一块名叫a的内存区域)
    int b;
    int *pa; //一个名叫pa的指针,它指向一个整数
    pa = &a; //将a的内存地址存赋值给pa,即,pa指向a
    a = 10; //这块叫a的内存区域里存储着一个常数10
    b = *pa; //将地址pa指向的变量赋值给b,即b = 10
    *pa = 12; //地址pa指向的变量所存储的值变为12,即a = 12,此时b=10
    printf("%d\n",a); // 12
    printf("%d\n",b); // 10
    return 0;
}

指针与数组

声明数组的同时也代表声明了一个指向数组首位的指针。数组和指针的区别在于:数组是个常量指针,而普通指针是变量指针

int a[10]; // a等价于 &a[0],即a是数组首位的地址
           // a[i] 等价于 *(a+i),这就是指针运算:指针加上整数来遍历一段内存

将数组传入一个函数时,也是传入的一个指向数组首位的指针,而不是传入整个数组。

#include <stdio.h>
#include <stdlib.h>

int randarray(int *pa, int n)
{
    int i;
    for (i=0; i < n; i++)
    {
        *pa = rand()%n + 1;
        printf("%d\n",*pa);
        pa++;
    }
    // 循环体可简写为 for(i=0; i<n; i++) *(pa+i)=rand()%n+1;
    //           或 for(i=0; i<n; i++) pa[i]=rand()%n+1;
    return 0;
}

int main(int argc, const char * argv[]) {
    int a[10];
    randarray(a,10);
    return 0;
}

// a[10] = [8, 10, 4, 9, 1, 3, 5, 9, 4, 10]

字符串、数组和指针

字符串是字符组成的数组,以'\0'结尾。字符串的操作就是通过指针来进行的。

char cc='a';
char *str = "aaa";

字符串用“双引号”,字符用‘单引号’

#include <stdio.h>
#include <string.h>
int mod12(int note){
    while(note < 0) note += 12;
    while(note >= 12) note -=12;
    return note;
}
// 输入调号note和音程interval,输出转调后的调号
//比如输入"C"和10,输出"A#"
int main() {
    char note[3], **p1, **p2,
    *table[12] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
                 // 这里声明了一个数组,数组由12个字符串组成
                 // table[0] = “C”,table[0][0] = ‘C’
                 // *table = table[0],*(table+11) = table[11]
    int interval;
    printf("Enter base note (capitals, use # for sharps, eg. A#): ");
    scanf("%s", note);
    printf("Enter interval in semitones: ");
    scanf("%d", &interval);
    /* point p1 to the beginning of the array and p2 to its end */
    p1 = table;
    p2 = table+11;
    /* now find the base note position,
     incrementing the pointer until we find it */
    while(strcmp(*p1,note)){
        p1++;
        if(p1 > p2) { /* if we're past the end */
            printf("could not find %s\n", note);
            return 1;
        }
    }
    /* add the interval to the address of the base note */
    p1 += mod12(interval);
    /* if beyond the end of the table, wrap it around */
    if(p1 > p2) p1 -= 12;
    /* print result */
    printf("%s transposed by %d semitones is %s\n",
           note, interval, *p1);
    return 0;
}

指向函数的指针

指向函数的指针使得我们可以通过指针来操作函数,比如将函数传给另一个函数、将函数放入数组等。

# include <stdio.h>

void message_printer(int times, void (*callback)(char *msg),char *user_mess){
    int i;
    for(i=0; i < times; i++) callback(user_mess);
}
//这里指向函数的指针是 callback

void my_important_message(char* mess){
    printf("VERY IMPORTANT: %s \n,",mess);
}
void my_warning_message(char* mess){
    printf("WARNING: %s \n,",mess);
}

int main() {
    message_printer(10, my_important_message, "functions can be pointers");
    message_printer(1, my_warning_message, "but be careful");
    return 0;
}

指向结构体的指针

typedef struct _person
{
    char name[10];
    int age;
} person;

person *ptr;
(*ptr).age // 等价于 prt->age

指向“包含函数的结构体”的指针:

# include <stdio.h>

typedef struct comp {
    double real, imag;
    void (*incr)(struct comp *p);
} complex;

void incr1(complex *p){ p->real++; p->imag++; }

int main(){
    complex a = { 0, 0, incr1 };
    a.incr(&a); //这里a是结构体而不是指向结构体的指针,所以不能用 ->
    return 0;
}

C语言中包含函数的结构体其实就相当于C++的类(class)

上一篇下一篇

猜你喜欢

热点阅读