在C语言中给指针赋值字符串

6

我是C语言的新学习者,我的问题是关于指针的。据我所学和搜索到的信息,指针只能存储其他变量的地址,而不能存储实际的值(如整数或字符)。但在下面的代码中,char指针c实际上存储了一个字符串。它可以正常执行并输出“name”而没有错误。

#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 typeint’, but argument 2 has typeint *’ [-Wformat=]
printf("%d",c);
^

指针存储变量的地址,那么为什么整数指针与字符指针不同?
如果我对指针有所遗漏,请解释一下。

1
这只是类型的问题。“name”是一个指针(技术上是一个数组),因此可以存储在指针中。10是一个整数,因此不能存储在指针中。我认为你的困惑源于不太明显的事实,即字符串字面值实际上具有指针类型。 - ApproachingDarknessFish
4个回答

12
  1. char *c; c="name";

    观察上述代码,你并没有将字符串"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()的使用发出警告。当然,说它是糟糕的代码(会触发未定义行为)是完全正确的,但我不确定编译器是否能捕捉到它。 - unwind

5

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

char *c;
c="name";

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

1
是的,当你写下“name”时,这是一个快捷方式,告诉编译器要有一些内存来存储“name”这四个字母,后面跟着一个空终止符,并让你获取该字符串的指针。 - David Grayson
内存是在哪里创建的?如果我提供了一个过长的字符串,它不会干扰其他程序的内存吗? - Sudheer
@Sudheer 这取决于平台,但字符串字面量通常存储在某些只读位置。我不知道你为什么认为它会干扰其他程序。 - Yu Hao
谢谢您的回复。 - Sudheer

3
在物理机的层面上,它们是相同的。只是适当宽度(通常为32或64)的二进制字。但C语言创建了这两个抽象类型来帮助区分计算机字的两种不同用途:保存数字(或符号)值与保存另一个字的地址(本身可能是标量(数字)值或另一个指针)。
因此,指针指向各种东西,有可能是其他指针。在可读的C编程中,清晰地区分这些概念非常重要。
您也可以违反这些规则。但首先需要知道如何向其他程序员(在代码注释中)解释自己在做什么。
“name”的字节静态分配;即字节进入编译器生成的目标代码和可执行程序文件。在赋值"name"中,表达式中的"name"产生一个指向(第一个)单独字节的指针,并且变量 c (它作为自动变量动态分配,定义在函数内部)接收此指针作为它的“值”。
c = *
    |
    V
  _____ _____ _____ _____ ______
  |'n'| |'a'| |'m'| |'e'| |'\0'|

在整数示例中,你正在将指针设置为地址10。无论内存中第十个整数是什么。问题是,通常不会为程序映射内存的第一页。这允许程序在访问NULL指针时 安全地 崩溃。要将“值”赋给指针指向的位置是一个两步过程。首先,必须将指针设置为指向某些存储器以容纳该值。通常使用malloc
int *c = malloc(sizeof(int));

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

*c = 10;

使用C99复合字面量,您可以创建自动数组,这些数组在表达式中会衰变为指针。
这是一个指针:
(int[3]){4, 5, 6}

这是C语言中char-string字面量的整数字符串等价物(编译器语义略有不同:4、5和6可能不会放入字符串表中,而是放入单独的整数表中)。

2
char *c;
c="name";

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

它没有名称,具有静态存储期(意味着它存在于整个程序的生命周期);以及类型为指向字符的指针的变量,称为 c,它被初始化为该未命名的只读数组中第一个字符的位置。

如果将其声明为全局变量,则编译器会直接将其放置在程序的数据段中。如果将 c 声明为局部变量,则它将被放置在堆栈上。

现在来看

int *c;
c=10;

这里 c 的类型是 int *,它包含整数变量的地址。欲了解更多信息,请参见此处的解释


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接