在C中初始化字符串指针有什么意义

时间:2015-01-29 07:44:49

标签: c string pointers initialization

这是我的问题。在C中,我看到了这样的代码:

char *s = "this is a string";

但是,s实际上并没有指向实际的内存吗? 如果您尝试使用s来修改字符串,则结果是未定义的。

我的问题是,为指针分配字符串有什么意义 然后?

感谢。

8 个答案:

答案 0 :(得分:3)

char *s = "this is a string";

这是一个字符串文字。因此字符串存储在只读位置,并且该内存地址返回s。因此,当您尝试写入只读位置时,您会看到未定义的行为,并且可能会看到崩溃。

  

Q1:s实际上并没有指向实际的内存吗?

你错了s持有存储该字符串的内存地址。

  

Q2:那么将字符串赋值给指针的重点是什么?

http://en.wikipedia.org/wiki/String_literal

答案 1 :(得分:1)

  

s实际上并没有指向实际的内存吗?

从技术上讲,它指向只读内存。但只要遵循 as-if 规则,编译器就可以做任何想做的事情。例如,如果您从未使用s,则可以将其从代码中完全删除。

由于它是只读的,因此任何修改它的尝试都是未定义的行为。您可以而且应该使用const来指示指针的目标是不可变的:

const char* s = "Hello const";
  

我的问题是,那么将字符串赋值给指针的重点是什么?

就像将常量存储到任何其他类型一样。您并不总是需要修改字符串。但是您可能希望将指向字符串的指针传递给不关心它们是指向文字还是指向您拥有的数组的函数:

void foo(const char* str) { 
  // I won't modify the target of str. I don't care who owns it.
  printf("foo: %s", str);
}

void bar(const char* str) {}

char* a = "Hello, this is a literal";
char b[] = "Hello, this is a char array and I own it";

foo(a);
bar(a);
foo(b);

答案 2 :(得分:1)

执行char *s = "this is a string";时,会自动分配内存并使用此字符串填充内存,并将指向该内存的指针返回给调用者(您)。因此,您不需要将字符串显式地放入某个内存中。

  

s实际上并没有指向实际的内存吗?

错误,它确实指向一个实际内存,其分配实现对您隐藏。此内存位于内存的只读扇区中,因此无法更改/修改。因此,关键字const因为这些文字被称为常量文字。

  

如果您尝试使用s来修改字符串,则结果是未定义的。

因为,您正在尝试修改标记为Read-Only的内存。

  

然后将字符串赋给指针的重点是什么?

实现同样目的的另一种方法是,

char temp[260] = {0} ;
char *s ;
strcpy (temp, "this is a string");
s = temp ;

此处内存temp由您管理。

char *s = "this is a string" ;

此处内存由操作系统管理。

答案 3 :(得分:1)

通过使用const char *而不是char [],字符串将存储在read only内存空间中。这允许编译器消除字符串重复。

尝试运行此程序:

#include <stdio.h>

int main()
{
    const char *s1 = "This is a string";
    const char *s2 = "This is a string";
    if (s1 == s2) {
        puts("s1 == s2");
    } else {
        puts("s1 != s2");
    }
}

对我而言,它输出s1 == s2,这意味着字符串指针指向相同的内存位置。

现在尝试将const char *替换为char []

int main()
{
    const char s1[] = "This is a string";
    const char s2[] = "This is a string";
    if (s1 == s2) {
        puts("s1 == s2");
    } else {
        puts("s1 != s2");
    }
}

这会输出s1 != s2,这意味着编译器必须复制字符串内存。

通过使用char *而不是char [],编译器可以执行这些优化,从而减少可执行文件的大小。

另请注意,您应使用char *s = "string"。您应该使用const char *s = "string"代替。 char *s已弃用且不安全。通过使用const char *,您可以避免将字符串传递给尝试修改字符串的函数的错误。

答案 4 :(得分:0)

看看这段代码:

char *s = "this is a string";
printf("%s",s);

正如您所看到的,我使用“为string分配pointer”。这是否清楚? 并且知道s指向实际的内存,但它是只读的。

答案 5 :(得分:0)

如果你这样分配,

char *s = "this is a string";

它将存储在只读存储器中。所以这就是未定义行为的原因。在这个s中将指向只读区域中的一些内存。 如果您打印这样的地址,您可以获得一些内存地址。

 printf("%p",s);

所以在这种情况下,如果你分配一个内存并将值复制到该指针,你可以像数组一样访问该指针。

答案 6 :(得分:0)

如果您尝试修改字符串,其他所有人都告诉您有关只读内存和未定义行为的可能性,因此我将跳过该部分并回答问题,“将字符串分配给a的重点是什么?然后指针?“。

有两个原因

1)为了简洁起见。将字符串分配给指针后,您可以将字符串称为s,而不是重复键入“this is a string”。这当然假定您打算在多个函数调用中使用该字符串。

2)因为您可能想要更改指针引用的字符串。例如,在以下代码中,s初始化,假设代码将成功,并且如果失败则随后更改。最后,打印s指向的字符串。

const char *s = "Yay, it worked!!!";

if ( openTheFile() == FAILED )
    s = "Dang, couldn't open the file";

else if ( readTheFile() == FAILED )
    s = "Oops, there's nothing in the file";

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

请注意,const char *表示s指向的字符串无法更改。这并不意味着s本身无法改变。

答案 7 :(得分:0)

在你的情况下,指针s只是指向携带字符串第一个字符的位置。因此,如果我们想要更改字符串,则会在指针s指向前一个位置时产生混淆。如果你想用指针改变字符串,你应该处理前一个字符串的结尾(即NULL)。