C:指针题

标签 c pointers

关于以下代码的两个问题:

  1. 有和没有malloc()语句的区别是什么:

    p = (char *) malloc (20 * sizeof(char) );
    

    仅仅是内存位置的不同吗?指针变量 'p' 在没有该语句的情况下处于 STACK 中,而在具有该语句的 HEAP 中?

  2. 为什么声明是

    printf("%s\n", p);
    

    不是

    printf("%s\n", *p);
    

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

int main () {

   char movie[] = "forrest gump";
   char *p;

   p = (char *) malloc (20 * sizeof(char) );
   p = movie;

   printf("%p\n", p);
   printf("%p\n", movie);
   printf("%s\n", p); // to print "forrest gump"

   free(p);

   return 0;
}

最佳答案

问题一

添加了行号注释的代码:

char movie[] = "forrest gump";                 // 1
char *p;                                       // 2

p = (char *) malloc (20 * sizeof(char) );      // 3
p = movie;                                     // 4

printf("%p\n", p);                             // 5
printf("%p\n", movie);                         // 6
printf("%s\n", p); // to print "forrest gump"  // 7

free(p);                                       // 8

我将忽略未检查 malloc() 的返回值,并且我不会被 malloc() 的返回值强制转换为 long如果您省略 malloc() 的声明,您的编译器会告诉您 — 但有很多人不同意这一点。 * sizeof(char) 不是必需的,最好写成 * sizeof(*p)

代码有内存泄漏,并且由于内存泄漏而表现出未定义的行为。

第 1 行没问题。第 2 行同样很好,尽管可以通过将它与第 3 行组合来初始化变量。

第 3 行在这种情况下是安全的,但分配的固定大小在其他情况下会成为问题。

第 4 行是一个主要问题。这是泄漏。您刚刚践踏了指向由 malloc() 返回的内存的唯一指针,因此内存不可挽回地丢失了。诚然,这个程序很快就会退出(如果它没有先崩溃的话),但总的来说,这很糟糕。你应该写:

strcpy(p, movie);

或者也许:

memmove(p, movie, sizeof(movie));

第 5 行将打印存储在 p 中的地址。正如所写的那样,这是 movie 的地址,因为第 4 行中的赋值。可以说,它应该用强制转换来编写,因为 %p 格式说明符采用 无效 *:

printf("%p\n", (void *)p);

在实践中,当 p 是一个 char * 时,您将无处不在。我学会了在一台机器上编程(在有 C 标准之前的日子里),其中 char * 地址的位表示与 anything_bigger * 地址不同相同的内存位置。在这样的机器上,如果代码正在处理 struct Something * 甚至是 int *,则必须转换为 void *

第 6 行产生与第 5 行相同的输出,并具有相同的注意事项。

第 7 行没问题,打印出 p 指向的数据,也是 movie 指向的数据。

第 8 行是调用未定义行为的地方。由于第 4 行中的分配,您试图释放未分配的空间,这是一场严重的灾难。它通常会导致崩溃;这绝不是一个好主意。

代码应该貌似是:

char movie[] = "forrest gump";
char *p = malloc(sizeof(movie)); // or: char *p = malloc(strlen(movie) + 1);
if (p != 0)
{
    strcpy(p, movie);
    printf("%p\n", p);
    printf("%p\n", movie);
    printf("%s\n", p);
    free(p);
}

问题2

您的问题 2 是关于:

printf("%s\n",  p);
printf("%s\n", *p);

第一个是正确的。 p 是一个 char *%s 转换规范需要一个 char *。第二个不正确,因为 *p 是一个 char,但 %s 需要一个 char *。相反,它获取一个小整数(如果您的代码集基于 ASCII,则为 102)并尝试将其视为地址。这是行不通的;它通常会导致崩溃,因为整个第一页内存(1 KiB 或 4 KiB)通常被映射为无效。

你可以使用:

printf("%c\n", *p);

这将打印 f

关于C:指针题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28007356/

相关文章:

C++ 相当于 C 中的 Union 吗?

c - 为什么这个编译没有错误?为什么它可以在 32 位机器上运行而不是 64 位机器?

objective-c - Objective-C 类实现中的 C 函数和变量?

c - 用指针访问结构体的变量时,Cache 会带什么?

c++ - 如何同时删除对象指针 vector 中的指针和对象本身?

c - C 中不兼容的指针类型。什么时候使用 * 或 &?对引用指针的概念有疑问

c - stat.h 文件访问文件描述符 open() 黑客利用的艺术

c - 使用makefile编译时如何设置GDB?

c - C 语言中 NULL 总是为零吗?

c - 使用预定义的字符串指针初始化指针数组?