`

关于数组指针和指针数组

阅读更多

在C/C++的编程中,对指针的使用和了解,再熟悉都不为过。

C/C++毫无疑问的十分强大,但离开了指针和数组,它们就什么都干不了了,可见其重要。

 

使用数组和指针来描述数据,是C/C++编程中最常见的工作。

本文通过一个描述二维数据的问题,来回顾下数组和指针的使用。

 

假设我们要表示的是一个5行3列的数据,则共有如下五种常用方式。

每种方式各有优缺点以及适用场景。

 

 

方法1,二维数组:

 

 

int data[5][3];
该方法的优点是完全不用关注内存什么时候创建和销毁的问题,直接使用即可。

 

但需要在程序运行之前就知道数据的行列数。

该方式的内存空间由编译器在栈空间创建。

空间示例如下图:

 

方法2,数组指针:

 

int (*data)[3];
data = (int(*)[3])malloc(sizeof(int[3]) * 5);

/// some code here

free(data);
 该方式的不便之处是需要在运行时通过malloc创建堆内存来存放二维数据,而且使用完之后需要free掉。

 

 同时该方法可以适用于在程序运行前行数不确定的情况,即在运行时动态确定数据行数。

 该方法所需创建的空间大小与方法1相同,不同在于空间是堆空间,其创建是由malloc在运行时完成的。

空间示例图如下:

 

方法3,指针数组:

 

int * data[5];

for (int i = 0; i< 5; i++){
    data[i] = (int*) malloc(sizeof(int)*3);
}

/// some code here

for (int i = 0; i< 5; i++){
    free(data[i]);
}

 

 

该方式与方法2的做法从逻辑上正好相反,同样适用于只知道二维数据中一维维数的情况。

但该方法与方式2相比却要多次调用malloc 和free进行内存的创建和释放,而且总使用的内存空间也更大。

其中data变量不需要free,因为其空间并不是在运行时通过malloc创建的。data自己的内存区会在程序运行出data所在的代码块之后自动销毁(栈空间)。当然data不能是static。

空间示例图如下:

 

 

方法4,指针的指针:

 

 

int ** data;
data = (int **)malloc(sizeof(int*) * 5);
for (int i = 0;i < 5; i++){
    data[i] = (int*)malloc(sizeof(int) * 3);
}

/// some code here


for (int i = 0;i < 5; i++){
    free(data[i]);
}
free(data);

 

该方式适用于在程序运行前行列都不知道的情况下,在运行时动态创建用来存储二维数据的内存空间。

该方式最灵活。data变量自己指向的空间也是在运行时由malloc创建,需要free掉,因此与方法3相比,要多一次malloc和free操作。

但与方法3在总内存空间占用量上是一致的。

空间示例图如下:

 

 

方法5,一维数组模拟:

实际上方法1,2本质上也是一个“一维数组”,只是你需要告诉编译器row维加一的时候,步长是多少而已。

而本法发,不需要编译器计算步长,而是我们自己计算。代码如下:

 

int * data = NULL;
data = (int *) malloc(sizeof(int)*5 *3);

for (int i = 0;i < 5; i++){
    for (int j = 0; j < 3j ++){
        ///do something with element: data[i * 3 + j] ,这里的3就是row维加一的步长
    }
}

free(data)
data = NULL;
 该方法和方法2更像,因为方法1的内存空间在栈空间,方法2和该方法都在堆空间,示例图如下:
该方法的缺点是我们要根据行列动态地计算元素在数组中的偏移量,则需要一定的开销。
但可以同时 兼有方法1,2占用内存较少,以及方法3,4不需要实现知道行列数 的优点。
 

 

 

总结:

  • 以上四种方式分别针对行列数已知、行数未知列数已知、行数已知列数未知、行列数都未知的情况使用。其中方式1,2使用的内存空间大小相同,方式3,4使用的内存空间大小相同。
  • 方式3,4比方式1,2 多用r个指针空间,r为行数。
  • 方式2比方式3在只知道一维维数的情况下要更优,只需要做数据转置存储即可。
  • 当行列数都需要在运行时才能知道的情况只能使用方式4.
  • 方式5需要动态计算元素的偏移量,但艰巨了方法1,2和方法3,4 的优点。

 

 

 

 

 
  • 大小: 20.9 KB
  • 大小: 22.4 KB
  • 大小: 29 KB
  • 大小: 29.5 KB
  • 大小: 24 KB
分享到:
评论
2 楼 liuzhiqiangruc 2015-12-10  
zhoumengkang 写道
  说得好!正好在 hashtable 那边存 bucket 用到了

1 楼 zhoumengkang 2015-06-25  
  说得好!正好在 hashtable 那边存 bucket 用到了

相关推荐

Global site tag (gtag.js) - Google Analytics