如何使用指针传递大小信息?

时间:2013-12-11 01:23:24

标签: c pointers memory-management

我正在学习C并使用free()函数引导我来解决这个问题。说我有一个指针:

char *p = "String";

现在已经分配了7个字节的内存供p指向。但是,sizeof(* p)返回1,这使得它看起来像指针只知道它所拥有的地址的1字节。

如果是这种情况,那么free(p)如何释放所有7个字节。所以我能想到的唯一的事情是:

  1. 幕后发生了一些事情

  2. 只需要指定的第一个字节需要解除分配

  3. 这是其中之一吗?如果是1.什么是隐藏的过程/它是如何工作的?如果它是2.那么机器如何跟踪不应该为其他指针和变量分配的其他6个字节?

    感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

sizeof(*p)为1,因为p指向一个字符(一个字节)。

“它怎么知道”分配的内存有多大 - 它是“平台相关的”。很多时候你会发现有关malloc的两件事:

  • 它会分配比你要求的更大的块 - 因为它更多 有效地使用,例如,一次64字节(对齐问题等)
  • 通常,在指针下方有一小段代码,其中包含有关块大小的一些信息,以及指向“下一个和前一个块”的指针 - 如链接列表。这样,如果清除一个块,内存管理就可以跟踪哪些是空闲的,哪些不是。
  • 也可以单独维护分配表,描述哪些块是空闲/使用,它们有多大等等。

注意 - 我上面描述的内容与使用malloc的内存分配有关 - 这是C可以free()的唯一类型。字符串常量以不同的方式分配,其大小和位置是固定的 - 这就是您通常编写

的原因
const char *p = "hello";

对于这样的字符串,您可以通过查找nul终止符来了解大小。但是如果你真的决定用'\0'覆盖字符串中较早的字符,它就不会改变分配的内存量:

char p[] = "hi there world";
p[2] = '\0';
printf("%s***\n", p);

输出:

hi***

但是内存没有被释放。

答案 1 :(得分:1)

char *p = "String";

这是合法的,但它确实应该是:

const char *p = "String";

所以你不小心尝试修改数组。

你问什么阵?任何字符串文字对应于大小为LEN+1的静态分配数组,其中LEN是文字的长度。所以在这种情况下,在整个程序执行期间存在一个类型为char[7]匿名数组,其中包含值

`{ 'S', 't', 'r', 'i', 'n', 'g', '\0' }`.

p的初始值设定项使其指向该数组的第一个元素,其中包含'S'。由于未通过调用malloc()(或calloc()realloc())分配数组,因此不得尝试free()

给定p,您无法直接确定数组的大小(因为p指向其第一个元素,而不是指向整个数组)。您可以计算strlen(p) + 1可能与分配的大小相同 - 但如果字符串文字是"foo\0bar",那么它将是8个字节长,但是{{ 1}}将停在第一个空字符并返回strlen。因此,如果您需要能够确定数组的大小,请不要通过将其地址分配给指针来丢弃该信息。

现在,如果你写了:

3

初始化程序将字符串文字的内容复制到数组char arr[] = "String"; 中,并且arr的大小将由编译器根据初始化程序的大小确定。同样,您不得尝试在此数组上调用arr(或者更确切地说,在指向其第一个元素的指针上),因为它未使用free()分配。但您可以通过malloc()轻松确定其大小,这将产生sizeof arr。 (7会给你一个指针的大小,而不是它指向的数组。)

最后,如果您使用sizeof p分配数组:

malloc()

你仍然不能使用#define message "String" char *p = malloc(sizeof message + 1); if (p == NULL) { fprintf(stderr, "malloc failed\n"); exit(EXIT_FAILURE); } strcpy(p, message); (它只是一个指向单个字符的指针)来确定分配数组的大小 - 但是p能够解决它。怎么样?语言没有说,但任何实现都会在幕后留下额外的簿记信息,让free()做正确的事。

请注意,实现不一定记住您请求的大小。对free()的调用实际上可能会分配16个字节,唯一需要的信息{基础地址和实际分配的大小。

但是,既然您已经调用了malloc(7),那么如果您需要记住分配的大小,只需将其保存在某处:

free

如果您有声明的数组对象,则可以使用malloc来确定其大小。数组通常使用指针进行操作,指针不保留数组的大小;你必须自己跟踪。 // ... const size_t allocated_bytes = sizeof message + 1; char *p = malloc(allocated_bytes); // ... 和朋友在幕后保留一些大小信息,但仅限于让sizeof正常工作;你(可能)自己无法访问这些信息。如果需要跟踪已分配数组的大小,则必须自己完成。