C指针的爆炸难点.

指针重难点:

难点一:以下程序的执行结果是?

int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);  //&a 得到的是int(*)[5]型
                             //&a + 1 得到的是跳过a[5]这个数组的下一个元素
                             //(int *) 强制转换为int *,也就是a[5]数组后的下一个元素地址
printf("%d,%d", *(a + 1), *(ptr - 1));
                                //*(a + 1) ==> a[1]  ==> 2
                                //ptr 为int* 型,自然而然的ptr-1 为a[4]的地址
                                //* 解引用得到a[4] ===> 5

所以打印的结果是   2 , 5

难点二:以下程序的执行结果是?

struct Test{
    int Num;
    char *pcName;
    shortsDate;
    char cha[2];
    shortsBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//p + 0x1 = 0x___ ?
//(unsigned long)p + 0x1 = 0x___ ?
//(unsigned int*)p + 0x1 = 0x___ ?

上面代码中的结构体可以换种写法:

struct Test{
int Num;
char *pcName;
shortsDate;
char cha[2];
shortsBa[4];
};

struct Test *p = 0x100000;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
printf("%p\n", p + 0x1);
//p + 0x1 = 0x___ ?     //这个结构体占用20个字节, p指向的是struct Test类型的结构体,+1操作执行的是跳过整个结构体的下一个元素的首地址; 故: 0x100000 + 0x14(20的16进制表示) => 0x100014


 下面的强制类型转换, 导致 p 就变成了一个 unsigned long, 再去 + 1 , 就只是单纯的整数 + 1
printf("%p\n", (unsigned long)p + 0x1);//(unsigned long)p + 0x1 = 0x___ ?  0x100000 + 0x1 => 0x100001
//下面的强制类型转换中,导致 P 转换为unsigned int(*) 类型的指针, 再 + 1 ,得到的是跳过四个字节后的指针 0x100000 + 0x1 => 0x100004
printf("%p\n", (unsigned int*)p + 0x1);//(unsigned int*)p + 0x1 = 0x___ ?



在这种 + 1 操作中,首先要注意的就是 + 1 前它的类型,然后再去执行 + 1 操作

难点三:以下程序的执行结果是?

int main(){
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1); //&a得到的是int(*)[4]类型的指针, + 1 跳过整个数组,强制转换后得到的是 int(*)指针;
    int *ptr2 = (int *)((int)a + 1); //a是数组名,(int)强制转换后得到的是整型, + 1就是加一个字节,强制转换得到的是int(*)指针
    printf( "%x,%x", ptr1[-1], *ptr2); // 4 和 02000000
    return 0;
}

这里我们要借用画图板来假设内存中的分布:

 (int) a + 1得到的是0x101  ===> ptr2 ,因为 ptr2 是int * 型,所以对其解引用得到的是四个字节的int型,往后数四个字节即可.

难点四:

#include <stdio.h>
int main(int argc, char * argv[])
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };  //局部初始化,一定要注意这个地方使用的是逗号运算符,逗号运算符的作用就是:执行完代码后返回的是最后一个值;
int *p;
p = a[0];   //a[0]是int[2]型,
printf( "%d", p[0]);  //p[0] ==> a[0][0] ==> 1
}

难点五:

int main()
{
    int a[5][5];   //二维数组
    int(*p)[4];    //数组指针,长度为四个元素的数组指针
    p = a;    
    printf( "a_ptr=%#p,p_ptr=%#p\n" , &a[4][2], &p[4][2]);
    printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

同样借助画图板来表示一下内存分布:

一目了然,我们得到的是: 错位的读取:

&p[4][2] - &a[4][2] 指针相减得到的是 -4 的元素空间大小,  最后打印的也是 16进制下的 -4.和十进制下的-4;

难点六

int main()
{
    int aa[2][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10} };
    int *ptr1 = (int *)(&aa + 1);  //&aa 得到的是int(*)[2][5], 加 1 得到的是跳过整个数组元素的下一个地址

    int *ptr2 = (int *)(*(aa + 1)); // aa + 1得到是aa[1], 它是int (*)[5]型,强制转换为int* 得到的是aa[1][0]的地址
    printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));  //打印的是 10   5
    return 0;
} 

难点七

char *a[] = { "work","at","alibaba" };//定义字符串指针,需要注意的是字符串常量的存储位置在常量区,而非栈区
char**p = a;  // a是char*[3]型
p++;
printf("%s\n", *p);

借助画图板看一下内存分布:

 p + 1 ==> 0x10004

解引用得到的是: 0x200

%s打印找0x200为开始地址数,直到遇到下一个\0结束.

难点八:难点中的难点

char *c[] = { "ENTER","NEW","POINT","FIRST" };
char**cp[] = { c + 3,c + 2,c + 1,c };
char***cpp = cp;

printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp + 3);

// cpp[-2] => *(cpp-2) 这个操作没有修改 cpp 的内容. 而上面的 ++ 操作修改 cpp 
printf("%s\n", *cpp[-2] + 3);
//printf("%s\n", cpp[-1][-1] + 1);

同样先从画图板中的假设内存分布说起:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "C语言指针详解.pdf" 是一份详细介绍C语言指针概念和使用的PDF文档。C语言中,指针是一种特殊的变量类型,用于存储其他变量的内存地址。 该PDF文档首先详细介绍了指针的定义和声明。指针的声明需要指定指针变量的类型和名称,并使用星号(*)来表示该变量是一个指针指针变量名的前面加上一个星号,可以获取所指向的变量的值,这被称为"解引用"。 文档还介绍了指针的运算。指针可以进行自增和自减运算,指针之间可以进行相减操作,返回的结果表示它们之间的距离或者偏移量。此外,还可以将指针赋值给另一个指针,或者将指针赋值给一个变量,反之亦然。 除了基本的指针概念,文档还详细介绍了指针的常见应用场景。这包括指针作为函数参数,用于在函数内部对传入的变量进行修改。还有通过指针来实现动态内存分配和释放,以及使用指针实现数据结构(如链表和树)等。 此外,该文档还包含一些常见的指针错误和问题的解决方案。这些错误包括空指针引用、野指针引用以及内存泄漏等。文档指出了这些错误的影响以及如何避免它们。 总的来说,"C语言指针详解.pdf" 是一份详细介绍C语言指针概念、使用和常见问题解决方案的文档,对于学习和理解C语言指针的人们是一份宝贵的资料。 ### 回答2: 《C语言指针详解.pdf》是一本关于C语言指针的详细解析的电子书。在这本书中,作者详细介绍了C语言中指针的概念、用途和基本语法。 首先,指针是C语言中非常重要的概念,它是一种数据类型,用于存储和操作内存地址。指针可以指向各种数据类型,如整数、字符、数组和结构体等。 在《C语言指针详解.pdf》中,作者详细讲解了指针的声明和初始化,以及如何通过指针来访问和修改变量的值。作者还介绍了指针与数组的关系,以及指针和函数之间的关联。 此外,书中还涵盖了指针的高级应用,如指针的算术运算、指向指针指针指针数组等。作者通过丰富的例子和代码来帮助读者理解这些概念和技巧。 《C语言指针详解.pdf》不仅适合C语言初学者,也适合有一定编程基础的读者。通过阅读此书,读者将能够更深入地理解C语言中指针的功能和用法,掌握指针在编程中的灵活运用。 总之,《C语言指针详解.pdf》是一本内容详尽且易于理解的C语言指针教程。读者通过阅读此书,可以提高自己在C语言编程中的指针应用能力,从而更好地实现程序的设计和开发。 ### 回答3: 《C语言指针详解.pdf》是一本介绍C语言指针概念和使用方法的详细手册。C语言中的指针是一种非常重要和特殊的数据类型,它提供了直接访问内存地址的能力,使得C语言具有了更高的灵活性和效率。 这本手册首先会介绍指针的基本概念,包括指针变量的定义和声明、指针的初始化和赋值。它会详细讲解指针和变量之间的关系,以及指针的运算规则和使用方法。读者可以学习到如何通过指针操作变量的值和地址,以及如何利用指针实现函数的参数传递和返回值。 接下来,手册会介绍指针和数组之间的关系。C语言中,数组名本质上是一个指向数组首元素的常量指针,因此可以通过指针来操作数组。手册将详细讲解指针和数组的指针算术运算,以及指针和多维数组的关系。 此外,手册还会介绍指针和字符串之间的关系。C语言中,字符串本质上是以空字符结尾的字符数组,可以通过指针来操作字符串。手册将详细讲解指针和字符串的操作,包括字符串的输入输出、字符串的比较和拷贝。 最后,手册还会介绍指针和结构体之间的关系。C语言中,结构体是用户自定义的复合数据类型,可以通过指针来操作结构体。手册将详细讲解指针和结构体的操作,包括结构体指针的定义和使用,以及结构体指针作为函数参数的传递方式。 总之,《C语言指针详解.pdf》是一本深入浅出的指针教程,对于想更深入理解C语言指针的读者来说,是一本非常实用的参考书。无论是初学者还是有一定基础的读者,都可以从中获得很多宝贵的知识和技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值