【问题标题】:Assigning strings to pointer in C Language在 C 语言中将字符串分配给指针
【发布时间】:2014-07-11 05:11:56
【问题描述】:

我是 C 语言的新手,我的问题是关于指针的。据我所知和搜索的指针只能存储其他变量的地址,但不能存储实际值(如整数或字符)。但是在下面的代码中 char 指针 c 实际上存储了一个字符串。它执行没有错误,并将输出作为“名称”。

#include <stdio.h>
main()
{
    char *c;
    c="name";
    puts(c);
}

任何人都可以解释指针如何在没有任何内存的情况下存储字符串,或者是否在创建内存的位置创建内存以及可以创建多少大小。

我尝试将它与整数类型指针一起使用

#include <stdio.h>
main()
{
    int *c;
    c=10;
    printf("%d",c);
}

但是报错了

cc     test.c   -o test
test.c: In function ‘main’:
test.c:5:3: warning: assignment makes pointer from integer without a cast   [enabled by default]
c=10;
^
test.c:6:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%d",c);
^

指针存放的是变量的地址,为什么整数指针和字符指针不一样。

如果我对指针有什么遗漏,请解释一下。

【问题讨论】:

  • 这只是类型的问题。 "name" 是一个指针(技术上是一个数组),因此可以存储在一个指针中。 10 是一个整数,因此不能存储在指针中。我认为您的困惑源于字符串文字实际上具有指针类型这一不太明显的事实。

标签: c string pointers


【解决方案1】:
  1. char *c; c="name";

    如果您在此处观察,您并没有将字符串“名称”分配给变量 c,而是将内存的基地址分配给变量 name 存储在变量 c 中。

  2. 字符串name存储在编译器创建的字符串表中,这种形式的所有字符串都存储在字符串表中,这个字符串表是const类型,意味着你不能再写到这个位置.例如,您可以尝试这两行 char *p = "Hello" ; strcpy(p,"Hi");。编译时会在第二行出现错误。

  3. int *c; c = 10;

    在上面的代码中,您正在创建一个整数指针并为其分配 10,此处的编译器理解您将 10 作为地址分配。您需要了解的另一件事是所有指针变量仅存储无符号整数常量。因此,即使在这两种情况下都是char *cint *c,变量c 也只存储一个无符号整数。

【讨论】:

  • 我认为大多数编译器不会警告 strcpy() 的使用。说它是糟糕的代码(触发未定义的行为)当然是绝对正确的,但我不确定编译器会抓住它。
【解决方案2】:

C 中的字符串不是原生类型。它们是空终止的char 数组。在你的例子中,

char *c;
c="name";

指针c 不包含字符串本身的内容,而是字符串文字"name" 的地址(更准确地说,是它的第一个元素的地址)。

【讨论】:

  • 是的,当你写“name”时,这是一个快捷方式,它告诉编译器有一些内存,“name”的 4 个字母后跟一个空终止符,并让你得到一个指向它的指针字符串。
  • 如果我给一个太长的字符串,它在哪里创建的内存不会干扰其他程序的内存
  • @Sudheer 这取决于平台,但字符串文字通常以只读方式存储在某个地方。我不知道你为什么认为它会干扰其他程序。
  • 感谢您的回复
【解决方案3】:

在物理机级别,它们是相同的。只是适当宽度的二进制字(通常是 32 或 64)。但是 C 创建了这两种抽象类型来帮助区分机器字的两种不同用途:保存数字(或符号)值与保存另一个字的地址(本身可能是标量(数字)值或另一个指针)。

所以指针指向事物,可能是其他指针。对于可读的 C 编程来说,在头脑中牢牢区分这些概念是很重要的。

您也可以违反这些规则。但首先你需要知道你在做什么。 :) 如何向其他程序员解释你在做什么(在你的代码 cmets 中)。

"name" 的字节是静态分配的;也就是说,字节进入编译器生成的目标代码和可执行程序文件。在赋值c="name" 中,表达式中的"name" 产生一个指向(第一个)各个字节的指针,以及变量c(它动态分配的,因为它是一个自动变量,已定义inside 一个函数)接收这个指针作为它的“值”。

c = *
    |
    V
  _____ _____ _____ _____ ______
  |'n'| |'a'| |'m'| |'e'| |'\0'|

在整数示例中,您将指针设置为地址 10。无论内存中的第十个整数是什么。问题是内存的第一页通常没有为您的程序映射。这允许程序在访问NULL 指针时安全地 崩溃。为指针指向的“值”赋值是一个两步过程。首先必须将指针设置为指向某个存储以保存该值。通常使用malloc

int *c = malloc(sizeof(int));

然后您可以取消引用指针并设置和检索其关联值。

*c = 10;

使用 C99 复合文字,您可以创建自动数组,这些数组会衰减为表达式中的指针。

这是一个指针:

(int[3]){4, 5, 6}

这是 integer-string 等效于 C 中的 char-string 文字(编译器语义略有不同:4、5 和 6 可能不在 字符串表,但放入单独的整数表)。

【讨论】:

    【解决方案4】:
    char *c;
    c="name";
    

    这创建了一个指针并将其指向一个常量字符串。编译器将其放入标记为只读的内存部分中。

    它没有名称并且具有静态存储持续时间(意味着它在程序的整个生命周期中都存在);和一个指向字符类型的变量,称为c,它使用该未命名的只读数组中的第一个字符的位置进行初始化。

    如果你把它声明为c 是全局变量,那么编译器直接把它放在程序的数据部分。如果您将c 声明为局部变量,则将其放入堆栈,

    现在

    int *c;
    c=10;
    

    这里c的类型是int *,其中包含整数变量的地址。更多信息请看这里explanation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多