博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
当罗密欧遇到朱丽叶... ...当指针遇到数组
阅读量:5156 次
发布时间:2019-06-13

本文共 3116 字,大约阅读时间需要 10 分钟。

题目是扯淡. 无视

他们说, 题目要长长长长....

当罗密欧遇到朱丽叶的时候, 看官们都非常happy... 古典唯美悲情爱情嘛~

然而捏. 数组遇到指针的时候, 我就差点panic了...

这里特别感谢 @Fantasy @凯旋冲锋 另一起关注问题讨论问题的Essential On Linux的道友们

事情的起因源于这里的一个hash表的实现,里面用到了二级指针(还有三次解引用...)

第一感觉不科学, 然后debug, 程序没有挂 ...他竟然没有挂...

-----------------------------

看官假设不知道hash表都没有关系, 我们这里只分析C语言的语法问题.

#include 
#define SIZE 1024static int (**hnew())[2] { return calloc(sizeof(int**), SIZE);}static void hdel(int (**e)[2]) { for (int i = 0; i < SIZE; i++) free(e[i]); free(e);}static int (**hget(int (**t)[2], int k))[2] { for (int h = k & (SIZE - 1); **t && ***t != k; h = ((h + 1) & (SIZE - 1)), t += h); return t;}static void hset(int (**t)[2], int k, int v) { for (int (**a)[2] = hget(t, k); !*a && (*a=malloc(sizeof(**t))); (**a)[0]=k,(**a)[1]=v);}// TEST DRIVER#include
int main() { int (**table)[2] = hnew(); hset(table, 10, 20); hset(table, 20, 30); hset(table, 30, 40); int (**a)[2] = hget(table, 10); int (**b)[2] = hget(table, 20); int (**c)[2] = hget(table, 30); printf("%d:%d\n", (**a)[0], (**a)[1]); printf("%d:%d\n", (**b)[0], (**b)[1]); printf("%d:%d\n", (**c)[0], (**c)[1]); hdel(table); return 0;}
不得不佩服这样的神人, 对于C语言的掌握差点儿到了出神入化的境地.

static int (**hnew())[2] {    return calloc(sizeof(int**), SIZE);}
首先这里构造了一个函数, 来申请内存空间, 并且函数的返回值是一个
二级指针

这个指针一个int数组, static是用来修饰函数的作用域的,把external改动为internal

作者巧妙的利用了堆上的数据默觉得0

把calloc申请来的指针所有初始化为0x0000

在函数内部假设这样写

static int (**pp_array)[2] = malloc(sizeof(int**) * 13);

这都是违法的!

作者则是把它直接作为函数返回值.

int (**table)[2] = hnew();

而后又赋值给了int类型的指针( 假设对于数组-指针,指针-数组有困惑的看官能够再翻翻<<C和指针>>这本书,里面有非常具体的辨析).

之前和数组有关的一些讨论基本上在以下两个link里面:

话唠继续,

static int (**hget(int (**t)[2], int k))[2] {    for (int h = k & (SIZE - 1); **t && ***t != k; h = ((h + 1) & (SIZE - 1)), t += h);    return t;}
这里对于t的解引用我一度非常不理解.

可是特殊就特殊在t是指向一个数组的指针.而不是什么别的变量.

int array[2] = {10, 20};

int (*p)[2] = array;

那么p == *p是为真的!!

看以下的demo:

#include 
int main(){ int temp[100] = {1000}; int array = {10, 20}; int (*p_array)[2] = array; printf("&array : 0x%x array:0x%x p_array:0x%x *p_array:0x%x\n", &array, array,p_array, *p_array); return 0;}

程序输出如图.

还有个有意思的现象.这里打印的时候,

&array : array : p_array : *p_array四个变量

后面三个变量在数值上,利用printf函数打印时是一样的

骚安勿躁,假设你认为有什么不科学的话,我也发现了,我们再看另外一个demo:

唯一的差别就是把p_array初始化的数据由array变成了&array.

#include 
int main(){ int array = {10, 20}; int (*p_array)[2] = &array; //int (*p_array)[2] = array; printf("&array : 0x%x array:0x%x p_array:0x%x *p_array:0x%x\n", &array, array,p_array, *p_array); return 0;}

&array p_array *p_array的值都是数组的地址,

而仅仅有array是第一个数据的值.

我printf打印数据的时候是会强制类型转换的.

所以我这里特意选择了%x,直接解释提供变量地址处的数据的16进制的值.

千万注意,这里指针表现出来的特性都是指向数组的指针表现出来的.不是常规的指向基础元素的指针.

以下是个常规指针的demo

#include 
int main(){ int array[10] = {100}; int *p_array = array; printf("%x %x\n", p_array, *p_array); return 0;}

打印的数据也都不用猜了.

这里我们讨论所遇到的问题,亦或说指针的特性都是指向数组的指针所遇到的(翻了几本书,这东西都讲得少).

假设有什么错漏, 或者新发现, 欢迎联系我, 博客随时更新.

最后,再次向一起讨论问题的道友致谢!

2015年3月16日, @凯旋冲锋 提出修正. 丢脸(要勇于承认嘛~),static 作用于函数,改动函数的作用域

转载于:https://www.cnblogs.com/wzjhoutai/p/7119702.html

你可能感兴趣的文章
List_统计输入数值的各种值
查看>>
学习笔记-KMP算法
查看>>
Timer-triggered memory-to-memory DMA transfer demonstrator
查看>>
跨域问题整理
查看>>
[Linux]文件浏览
查看>>
64位主机64位oracle下装32位客户端ODAC(NFPACS版)
查看>>
获取国内随机IP的函数
查看>>
今天第一次写博客
查看>>
江城子·己亥年戊辰月丁丑日话凄凉
查看>>
IP V4 和 IP V6 初识
查看>>
Spring Mvc模式下Jquery Ajax 与后台交互操作
查看>>
(转)matlab练习程序(HOG方向梯度直方图)
查看>>
『Raid 平面最近点对』
查看>>
【ADO.NET基础-数据加密】第一篇(加密解密篇)
查看>>
C语言基础小结(一)
查看>>
STL中的优先级队列priority_queue
查看>>
UE4 使用UGM制作血条
查看>>
浏览器对属性兼容性支持力度查询网址
查看>>
OO学习总结与体会
查看>>
虚拟机长时间不关造成的问题
查看>>