C语言入门课程学习笔记9
- [第41课 - 指针:一种特殊的变量](#第41课 - 指针:一种特殊的变量)
- [第42课 - 深入理解指针与地址](#第42课 - 深入理解指针与地址)
- [第43课 - 指针与数组(上)](#第43课 - 指针与数组(上))
- [第44课 - 指针与数组(下)](#第44课 - 指针与数组(下))
- [第45课 - 指针与函数](#第45课 - 指针与函数)
- [第46课 - 指针与堆空间](#第46课 - 指针与堆空间)
- [第47课 - 指针专题经典问题剖析](#第47课 - 指针专题经典问题剖析)
第41课 - 指针:一种特殊的变量
实验-指针的使用
cpp
#include <stdio.h>
int main()
{
int var = 0;
int another = 0;
int* pVar = NULL;
printf("1. var = %d\n", var);
printf("1. pVar = %p\n", pVar);
pVar = &var; // 使用指针保存变量的地址
*pVar = 100; // *pVar 等价于 var , var = 100;
printf("2. var = %d\n", var);
printf("2. pVar = %p\n", pVar);
pVar = &another; // 改变了 pVar 的指向,使得 pVar 保存 another 的地址
*pVar = 1000; // another = 1000;
printf("3. another = %d\n", another);
printf("3. pVar = %p\n", pVar);
printf("4. add ==> %d\n", var + another + *pVar); // 100 + 1000 + 1000 ==> 2100
return 0;
}
/*
1. var = 0
1. pVar = 0000000000000000
2. var = 100
2. pVar = 000000000061FE14
3. another = 1000
3. pVar = 000000000061FE10
4. add ==> 2100
*/
小结
第42课 - 深入理解指针与地址
实验-指针的类型
cpp
#include <stdio.h>
int main()
{
int i = 10;
float f = 10;
int* pi = &f; // WARNING int* 指向了float
float* pf = &f; // OK
printf("pi = %p, pf = %p\n", pi, pf);
printf("*pi = %d, *pf = %f\n", *pi, *pf);
pi = i; // WARNING
*pi = 110; // OOPS
printf("pi = %p, *pi = %d\n", pi, *pi);
return 0;
}
实验
cpp
#include <stdio.h>
int calculate(int n, long long* pa, long long* pm)
{
int ret = 1;
if( (1 <= n) && (n <= 20) )
{
int i = 0;
*pa = 0;
*pm = 1;
for(i=1; i<=n; i++)// 0+1+...+n
{ //1*1*...*n
*pa = *pa + i;
*pm = *pm * i;
}
}
else
{
ret = 0;
}
return ret;
}
int main()
{
long long ar = 0;
long long mr = 0;
if( calculate(5, &ar, &mr) )
printf("ar = %lld, mr = %lld\n", ar, mr);//15 1*2*3*4*5=120
return 0;
}
实验
cpp
#include <stdio.h>
void func(int* p)
{
*p = 100; // 修改内存中 4 字节的数据,即:修改一个整型变量的值
}
void swap(int* pa, int* pb)//通过指针交换变量
{
int t = 0;
t = *pa;
*pa = *pb;
*pb = t;
}
int main()
{
int var = 0;
int a = 1, b = 2;
printf("1. var = %d\n", var);
func( &var );
printf("2. var = %d\n", var);//100
printf("3. a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("4. a = %d, b = %d\n", a, b);
return 0;
}
小结
第43课 - 指针与数组(上)
实验
cpp
#include <stdio.h>
int main()
{
int a[] = {1, 2, 3, 4, 0};
int* p = a; // a 的类型为 int*, &a[0] ==> int*
int (*pa) [5] = &a;//指向数组的指针 注意指针类型
printf("%p, %p\n", p, a);
p++;//p+1==== p+1*sizeof(p)
*p = 100; // a[1] = 100;
printf("%d, %d\n", *p, a[1]);
printf("%p, %p\n", &a, a);//????值一样 但是意思不一样,数组的地址 数组首元素的地址
p = pa; // WARNING !!!! warning: assignment to 'int *' from incompatible pointer type 'int (*)[5]'
p = a;
while( *p )
{
printf("%d\n", *p);
p++;
}
return 0;
}
/*
000000000061FDF0, 000000000061FDF0
100, 100
000000000061FDF0, 000000000061FDF0
1
100
3
4
*/
小结
第44课 - 指针与数组(下)
实验
cpp
#include <stdio.h>
int main()
{
int a[] = {1, 2, 3, 4, 5};
int* p = a;
int i = 0;
// a[i] <==> *(a+i) <==> *(p+i) <==> p[i]
for(i=0; i<5; i++)
{
printf("%d, %d\n", a[i], *(a + i));
}
for(i=0; i<5; i++)
{
printf("%d, %d\n", a[i], p[i]);
}
for(i=0; i<5; i++)
{
printf("%d, %d\n", p[i], *(p + i));
}
printf("a = %p, p = %p\n", a, p);//值相同
printf("&a = %p, &p = %p\n", &a, &p);//值不同
return 0;
}
实验
cpp
#include <stdio.h>
int main()
{
int a[] = {1, 2, 3};
int* p = a;
int v = *p++;//int v=*p,p++;
char* s = NULL;
printf("%p\n", "D.T.Software");
printf("%p\n", "D.T.Software");
printf("v = %d, *p = %d\n", v, *p);
printf("First = %c\n", *"D.T.Software");
s = "D.T.Software";
while( *s ) printf("%c", *s++);
printf("\n");
return 0;
}
/*
0000000000404000
0000000000404000
v = 1, *p = 2
First = D
D.T.Software
*/
小结
第45课 - 指针与函数
实验
cpp
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int mul(int a, int b)
{
return a * b;
}
int calculate(int a[], int len, int(*cal)(int, int))
{
int ret = a[0];
int i = 0;
for(i=1; i<len; i++)
{
ret = cal(ret, a[i]);
}
return ret;
}
int main()
{
int a[] = {1, 2, 3, 4, 5};
int (*pFunc) (int, int) = NULL;
pFunc = add;
printf("%d\n", pFunc(1, 2));//3
printf("%d\n", (*pFunc)(3, 4));//7
pFunc = &mul;
printf("%d\n", pFunc(5, 6));//30
printf("%d\n", (*pFunc)(7, 8));//56
printf("1 + ... + 5 = %d\n", calculate(a, 5, add));//15
printf("1 * ... * 5 = %d\n", calculate(a, 5, mul));//120
return 0;
}
实验
cpp
#include <stdio.h>
int demo(int arr[], int len) // int demo(int* arr, int len)//数组求和
{
int ret = 0;
int i = 0;
printf("demo: sizeof(arr) = %d\n", sizeof(arr));// 8 退化为指针了
while( i < len )
{
ret += *arr++;
i++;
}
return ret;
}
int main()
{
int a[] = {1, 2, 3, 4, 5};
// int v = *a++;
printf("return value: %d\n", demo(a, 5));//
return 0;
}
小结
第46课 - 指针与堆空间
实验
cpp
#include <stdio.h>
int main()
{
char c = 0;
int i = 0;
float f = 2.0f;
double d = 3.0;
void* p = NULL;
double* pd = NULL;
int* pi = NULL;
/* void* 指针可以保存任意类型的地址 */
p = &c;
p = &i;
p = &f;
p = &d;
printf("%p\n", p);
// void* 类型的指针无法访问内存中的数据
// printf("%f\n", *p);
/* void* 类型的变量可以直接合法的赋值给其他具体数据类型的指针变量 */
pd = p;
pi = p;
// void* 是例外,其他指针类型的变量不能相互赋值
// pd = pi;
return 0;
}
实验
cpp
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = malloc(4); // 从堆空间申请 4 个字节当作 int 类型的变量使用
if( p != NULL ) // 如果申请失败 p 为 0 ,即:空值
{
*p = 100;
printf("%d\n", *p);//100
free(p);
}
p = malloc(4 * sizeof(int));
if( p != NULL )
{
int i = 0;
for(i=0; i<4; i++)
{
p[i] = i * 10;
}
for(i=0; i<4; i++)
{
printf("%d\n", p[i]);
}
free(p);
}
return 0;
}
/*
100
0
10
20
30
*/
小结
第47课 - 指针专题经典问题剖析
cpp
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0;
int b = 1;
int* p = &a; //p指向a
int** pp = &p;//pp指向p
**pp = 2; // a = 2;
*pp = &b; // p = &b;
*p = 3; // b = 3;
printf("a = %d, b = %d\n", a, b);
return 0;
}
cpp
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[] = {1, 2, 3, 4};
int* pa = a;
int b[2][2] = {{1, 2}, {3, 4}};
// int** pb = b; // b 的类型绝对不是 int** warning: initialization of 'int **' from incompatible pointer type 'int (*)[2]'
int (*pnb) [2] = b; // b 的类型是 int(*)[2]
printf("a = %p, pa = %p\n", a, pa);
// printf("b = %p, pb = %p\n", b, pb);
printf("b = %p, pnb = %p\n", b, pnb);
return 0;
}
/*
a = 000000000061FE00, pa = 000000000061FE00
b = 000000000061FDF0, pnb = 000000000061FDF0
*/
cpp
#include <stdio.h>
#include <stdlib.h>
int getDouble(double** pp, unsigned n)
{
int ret = 0;
double* pd = malloc(sizeof(double) * n);
if( pd != NULL )
{
printf("pd = %p\n", pd);
*pp = pd;
ret = 1;
}
return ret;
}
int main()
{
double* p = NULL;
if( getDouble(&p, 5) )
{
printf("p = %p\n", p);
free(p);
}
return 0;
}
/*
pd = 00000000006E5CB0
p = 00000000006E5CB0
*/
cpp
#include <stdio.h>
#include <stdlib.h>
int main()
{
int b[2][2] = {{1, 2}, {3, 4}};
int (*pnb) [2] = b; // b 的类型是 int(*)[2]
*pnb[0] = 10;//*(pnb[0])
*pnb[1] = 30;
printf("b[0][0] = %d\n", b[0][0]);
printf("b[0][1] = %d\n", b[0][1]);//30
printf("b[1][0] = %d\n", b[1][0]);
printf("b[1][1] = %d\n", b[1][1]);
return 0;
}
/*
b[0][0] = 10
b[0][1] = 2
b[1][0] = 30
b[1][1] = 4
*/
cpp
#include <stdio.h>
#include <stdlib.h>
int main()
{
int b[2][2] = {{1, 2}, {3, 4}};
int (*pnb) [2] = b; // b 的类型是 int(*)[2]
*pnb[0] = 10;
int * k=pnb[0] +1;//?? pnb[0] +sizeof(*pnb[0])对了
*k= 20;
// *pnb[1] = 30;
printf("sizeof(pnb) = %d\n", sizeof(pnb));
printf("sizeof(pnb[0]) = %d\n", sizeof(pnb[0]));
printf("sizeof(*pnb) = %d\n", sizeof(*pnb));
printf("sizeof(*pnb[0]) = %d\n", sizeof(*pnb[0]));
printf("pnb=%p\n",pnb);
printf("pnb[0]=%p\n",pnb[0]);
printf("pnb[0]+1=%p\n",pnb[0]+1);
printf("sizeof(b) = %d\n", sizeof(b));
printf("sizeof(int[2]) = %d\n", sizeof(int[2]));
printf("b[0][0] = %d\n", b[0][0]);
printf("b[0][1] = %d\n", b[0][1]);//30
printf("b[1][0] = %d\n", b[1][0]);
printf("b[1][1] = %d\n", b[1][1]);
return 0;
}
/*
sizeof(pnb) = 8
sizeof(pnb[0]) = 8
sizeof(*pnb) = 8
sizeof(*pnb[0]) = 4
pnb=000000000061FE00
pnb[0]=000000000061FE00
pnb[0]+1=000000000061FE04
sizeof(b) = 16
sizeof(int[2]) = 8
b[0][0] = 10
b[0][1] = 20
b[1][0] = 3
b[1][1] = 4
*/
cpp
#include <stdio.h>
#include <stdlib.h>
int* func()
{
int var = 100;
return &var;
}
int main()
{
int* p = func(); // OOPS!!!!
// p 指向了不合法的地址,这个地址处没有变量存在
// p 是一个野指针,保存不合法地址的指针都是野指针
printf("*p = %d\n", *p);
*p = 200; // 改变 func 函数中局部变量 var 的值,是不是非常奇怪???
printf("*p = %d\n", *p);
return 0;
}