黑马程序员——C语言基础07—指针

时间:2022-06-05 11:29:54

一、指针
1.变量单元的地址称为“指针”,通过指针能找到以他为地址的内存单元。


int main()
{
int *p; //“*”的第一种含义: 定义

int a = 20;

p = &a;
// 此时我们称指针变量p指向了变量a
*p = 10; //“*”的第二种含义: 访问

a = 20;

printf("%d\n", *p); //‘*’的第三种含义: 取值

//printf("%d\n", a);

return 0;
}

2.指针变量的定义

类型名 *指针变量名
例如 char *ch;int *p;
说明:指针变量名为ch 和p,而不是*ch和*p。
在定义指针变量时必须制定基类型。因为不同类型的数据在内存中所占的字节和存放的方式是不一样的。例如:

int i=2;
char c=1;
int *p
p=&c; //此刻指针变量p是指向整形int的。
printf("c=%d\n",*p);
那么此刻c的值是多少呢?

答案不是1,而是513.
因为如下图所示,在内存为变量c和i分配空间时遵循寻址由大到小的原理
,i占据了下面黄色的四个字节,c分配了蓝色的一个字节,由于p指向的应该是4个字节空间的变量,所以当p指向c的首地址时,直接输出了
0000 0000 0000 0000 0000 0010 0000 0001
结果是513.

黑马程序员——C语言基础07—指针

3.引用指针变量

   p=&a;
printf("%d",*p);
printf("%p",p); //这个是输出变量p的地址,而不是&a

4.指针变量作为函数参数

指针变量作为函数传递时是指址传递。

二、指针与数组

1、


int a[5] = {3,4,5,5,6};
int *p ;
p = =&a[0]==a;

(或者 int *p = a;) //p指向了数组a;
注意:数组名只代表数组首元素的地址,不代表整个数组。

2、指针的运算与引用数组元素
如上例所诉,那么p+1 代表什么?

p+1指向同一组中的下一个元素。

p+1== a+1==&a[1];
p+1+1 == a+1+1 ==&a[2];
....
p+i == a+i
*(p+i)==a[i]==*(a+i)
// 这个以后经常用到

引用数组元素:
1)下标法 : a[i];
2) 指针法 :*(a+i)或者*(p+i)

3. 指针引用多维数组

 a[i][j]==*(a[i] +j)==*(*(a+i)+j);

4.指针引用字符串

定义字符串的两种方式:

1)利用数组:char name[] = “itcast”;

特点:字符串里面的字符可以修改的;

使用场景:字符串中的内容需要经常修改;


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

char string[]="I Love China";

printf("%p\n",string+1);

printf("%p",&string[1]);

return 0;
}

2)利用指针:char *name = “itcast”;

特点:字符其实是常量(在内存中存在常量区),字符串中的字符不可修改;

使用场景:字符串中的内容不需要修改,而且这个字符串经常使用 ;


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

char *string="I Love China";

printf("%p\n",string+1);

printf("%p",&string[1]);

printf("%s",string);//此时string是字符指针变量,指向字符串的第一个字符
return 0;
}

注意:string不是字符串变量,在C语言中没有字符串变量,只有字符变量。
在这不是把“I Love China”这些字符放在string中(指针变量只存地址),也不是把字符串赋给*string。

int a[10]={2,3,4,5,...};
printf("%d",a);//这是不对的,不能一一输出数组a的元素。
通过字符数组名或字符指针变量可以输出一个字符串,而对于一个数值型数组,是不能企图用数组名输出他的全部内容的。

5. 字符指针作函数参数

如果想把一个字符串在函数间进行传递,可以用地址传递,即用字符数组名或者字符指针变量作为参数。
两者都可以实现字符串的存储和运算,但是两者之间也存在区别:

1)字符数组有若干个元素构成,每个元素存放一个字符,而字符指针变量存放的只是地址(字符串第一个字符的地址),绝不是将字符串放到指针变量中;
2)可以对字符指针变量赋值,但不能对数组名赋值。
3)指针变量的值是可以改变的,而数组名代表一个固定的值,不能改变。

char *a;
a=“I Love China!”;//合法等价于char *a=“I Love China”;

而对于数组的初始化

char str[14]=“I Love China!”;
不等价于
char str14];
str14]=“I Love China!”
数组可依在定义时对个元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值。

4)字符数组中的各元素的值是可以改变的(可以赋值),但字符指针变量指向的字符串常量中的内容是不能再被取代的。

char *b="House";
b[2]='r'; //非法的,字符串常量不能改变

6.指向函数的指针
1)函数的指针就是函数的地址(存储空间的起始地址)

类型名 (* 指针变量名)(函数参数列表)
如 int (*p)(int ,int );

p可以指向有相同类型参数的(类型和参数都要对的起来),且有相同返回值类型的函数。

用指针调用函数时,先要指向这个函数,例如:p=max;
如果直接写成 p=max(3,4);那就错了。
可以(*p)(3,4)。

用函数指针变量调用函数比用函数名调用函数灵活。