指向malloc和操纵的指针

时间:2011-06-17 09:35:52

标签: c pointers malloc

#include <stdio.h>
#include <stdlib.h>


int main(int argc, char * argv[])
{
    char *p[2];
    char **pp = calloc(2, 4);

    p[0] = "ab";
    p[1] = "cd";
//  p[2] = "ef";

    pp[0] = "ab";
    pp[1] = "cd";
    pp[2] = "ef";

    printf("pp: %s, %s, %s\n", pp[0], pp[1], pp[2]);
    printf("size_p: %d\nsize_pp: %d\n", sizeof p, sizeof pp);
}

如果定义'p [2]'并赋值 - 结果行为是段错误。如果分配'pp [2]' - 输出如下:“ab,cd,ef”。对于'p','sizeof'返回8(每个指针2x4个字节),'pp'只返回4个字节。为什么我能够分配'pp [2]',即使它只应拥有8个字节的已分配内存(应该只能存储2个指针地址)?另外,'sizeof'如何确定两种情况下的实际内存大小?

3 个答案:

答案 0 :(得分:4)

声明

p有两个元素,因此p[2]不存在 - 因此是段错误。由于p是一个本地数组(指针),sizeof(p)给出了元素类型的大小(元素类型为char *,其大小为4)乘以元素数(2)。另一方面,pp是指针(指针),而不是数组,因此sizeof(p)只是char **的大小,与大小相同对32位机器上的任何其他指针,即4.对pp[2]的赋值似乎成功是纯粹的机会 - 你在分配的内存之外写入(只包含两个char *元素的空间)。

顺便说一句,指向字符串文字的指针应为const char *

答案 1 :(得分:2)

使用char *p[2];,您可以在堆栈上分配2 char*。访问p[2]时,您有缓冲区溢出并可能访问属于当前方法的堆栈帧的任何其他fings(某些编译器在调试模式下检查它)。

使用calloc,您可以在堆中分配内存。访问pp[2]是(可能)可用内存,这里没有段错误。但是这个内存也可以被其他对象使用,所以这绝对不行!

对于大小计算:sizeof(char**)为4,与每个32位指针一样。 sizeof(char*[2])是8,因为它是2x4字节。

答案 2 :(得分:1)

正如Aasmund Eldhuset所说,p [2]不存在。 p [0]和p [1]是数组的两个元素。

p [2]而不是pp [2]的段错误的原因是,据我所知,因为p存储在堆栈中而pp存储在堆上。因此,虽然你没有在pp [2]中拥有记忆,但它并没有出错。相反,它只是覆盖了上帝知道什么,并可能导致你的程序以不可预测的方式行为不端。

一般情况下,如果超出边界,动态分配的内存(例如示例中的pp)将不会始终发生段错误,而静态分配的内存(例如.p)将会出现段错误。