【问题标题】:Pointer initialization doubt指针初始化疑问
【发布时间】:2011-01-06 04:29:46
【问题描述】:

我们可以像这样在 C 中初始化一个字符指针。

char *c="test";

其中 c 指向第一个字符 (t)。

但是当我给出如下代码时。它给出了分段错误。

#include<stdio.h>
#include<stdlib.h>
main()
{

    int *i=0;
    printf("%d",*i);
}

当我给的时候

#include<stdio.h>
#include<stdlib.h>
main()
{
    int *i;
    i=(int *)malloc(2);
    *i=0;
    printf("%d",*i);
}

成功了(输出为 0)。

当我给malloc(0) 时,它起作用了(输出为 0)。

请说出发生了什么

【问题讨论】:

  • 至少停止投射 malloc。

标签: linux pointers gcc malloc


【解决方案1】:

您的第一个示例是段错误,因为您试图取消引用您使用以下行创建的空指针:

int *i=0;

你不能取消引用一个不指向任何东西的指针并期望好事情发生。 =)

第二个代码段有效,因为您实际上已经使用 malloc 为指针分配了内存,您可以取消引用。我认为根据与您使用 malloc 分配的地址相邻的内存,您可能会获得除零以外的值。我这样说是因为通常一个 int 是 4 个字节,而您只分配了 2 个。当取消引用 int 指针时,它应该根据指向的 4 个字节将值作为 int 返回。在您的情况下,前 2 个字节是您从 malloc 收到的内容,而相邻的 2 个字节是可能存在的任何内容,无论它是什么,都将被视为 int。您可能会遇到这样的奇怪行为,您应该分配您尝试使用/指向的类型所需的内存大小。
(即int *i = (int *) malloc(sizeof(int));

一旦你的指针指向正确大小的内存,你就可以这样设置值:

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

int main (int argc, char *argv[])
{
    int *i = (int *)malloc(sizeof(int));
    *i = 25;
    printf("i = %d\n",*i);

    *i = 12;
    printf("i = %d\n",*i);
    return 0;
}

根据评论编辑:

指针指向内存,而不是值。初始化char *ptr="test"; 时,您没有分配“test”的值,而是分配了编译器放置“test”的内存地址,该地址位于您的进程数据段中并且是只读的。如果您尝试修改字符串“test”,您的程序可能会出现段错误。关于 char * 您需要了解的是它指向字符串中的单个(即第一个)字符。当您取消引用 char * 时,您将看到 1 个字符和一个字符。 C 使用以 null 结尾的字符串,并注意在调用 printf 时您没有取消引用 ptr,而是将指针本身传递给它,并且该指针仅指向第一个字符。这如何显示取决于传递给 printf 的格式。当 printf 传递 '%c' 格式时,它将打印 ptr 指向的单个字符,如果传递格式 '%p' 它将打印 ptr 指向的地址。要获取整个字符串,请传递 '%s' 作为格式。这使得 printf 所做的是从您传入的指针开始并读取每个连续的字节,直到达到空值。下面是一些演示这些的代码。

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

int main (int argc, char *argv[])
{
    // Initialize to data segement/read only string
    char *ptr = "test";
    printf("ptr points at     = %p\n", ptr);   // Prints the address ptr points to
    printf("ptr dereferenced  = %c\n", *ptr);  // Prints the value at address ptr
    printf("ptr value         = %s\n", ptr);   // Prints the string of chars pointed to by ptr

    // Uncomment this to see bad behavior!
    // ptr[1] = 'E'; // SEG FAULT -> Attempting to modify read-only memory

    printf("--------------------\n");

    // Use memory you have allocated explicitly and can modify
    ptr = malloc(10);
    strncpy(ptr, "foo", 10);
    printf("ptr now points at = %p\n", ptr);   // Prints the address ptr points to
    printf("ptr dereferenced  = %c\n", *ptr);  // Prints the value at address ptr
    printf("ptr value         = %s\n", ptr);   // Prints the string of chars pointed to by ptr

    ptr[1] = 'F';  // Change the second char in string to F
    printf("ptr value (mod)   = %s\n", ptr);
    return 0;
}

【讨论】:

  • 字符指针的初始化不同于整数指针?因为我们可以像 char *ptr="test" 一样初始化它
  • 感谢您的详细说明。我还有一个问题。那么为什么同样的概念不适用于int *i=12;。这会导致打印值出现分段错误
  • 它不起作用,因为您将 value (即 12)分配给没有与之关联的内存以存储所述值的指针。 C 编译器将文字 char 字符串(即“test”)作为语言的一部分放入过程数据存储区,并为 char x 分配该位置的地址。因此,您将一个指针分配给指向“test”的指针 *pointing,而不是指向“test”的 value 的指针。一清二楚对吧? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-09
  • 2011-04-10
  • 2012-11-10
相关资源
最近更新 更多