指针
变量是一块内存区域,而计算机通过“地址”来访问内存(变量),用来表示“地址”的变量叫做“指针”。*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)
网友评论