【问题标题】:C: Behaviour of arrays when assigned to pointersC:分配给指针时数组的行为
【发布时间】:2013-01-05 01:27:50
【问题描述】:
#include <stdio.h>

main()
{
  char * ptr;

  ptr = "hello";


  printf("%p %s" ,"hello",ptr );

  getchar();

}

您好,我想清楚地了解如何将数组分配给指针。我注意到,当您将字符数组分配给字符指针ptr="hello"; 时,数组衰减到指针,但在这种情况下,我分配的数组字符不在变量内部,也不包含它们的变量“,确实这种分配方式专门为"Hello"(显然正在发生的事情)获取一个内存地址,并且是否可以修改“Hello”中每个元素的值,这些元素包含在存储该数组的内存地址中。作为比较,我可以用一个数组分配一个指针,例如 ints 像 thisint_ptr = 5,3,4,3; 这样模糊的东西,值 5,3,4,3 位于内存地址中“你好”做到了。如果不是,为什么只能使用字符串?在此先感谢。

【问题讨论】:

标签: c arrays string pointers


【解决方案1】:

"hello" 是一个字符串文字。它是char [6] 类型的无名不可修改对象。它是一个数组,它的行为方式与任何其他数组的行为方式相同。它是无名的事实并没有真正改变任何东西。您可以将它与 [] 运算符一起使用,例如 "hello"[3] 等。就像任何其他数组一样,它可以并且将在大多数情况下衰减为指针。

您不能修改字符串文字的内容,因为它在定义上是不可修改的。它可以物理存储在只读存储器中。如果它们包含常见的字符子序列,它可以与其他字符串文字重叠。

通过复合文字语法对其他数组类型也存在类似的功能

int *p = (int []) { 1, 2, 3, 4, 5 };

在这种情况下,右侧是int [5] 类型的无名对象,它衰减为int * 指针。不过,复合文字是可修改的,这意味着您可以使用 p[3] = 8 并因此将 4 替换为 8

您还可以对 char 数组使用复合文字语法并执行

char *p = (char []) { "hello" };

在这种情况下,右侧是char [6] 类型的可修改无名对象。

【讨论】:

  • @newacct:是的,但我相信我们已经过了需要明确提及的地步。
【解决方案2】:

您应该做的第一件事是阅读comp.lang.c FAQ 的第 6 部分。

字符串文字"hello"char[6] 类型的表达式(“hello” 5 个字符加上终止'\0' 1 个字符)。它指的是一个具有静态存储时长的匿名数组对象,在程序启动时初始化为包含这 6 个字符值。

在大多数情况下,数组类型的表达式被隐式转换为指向数组第一个元素的指针;例外情况是:

  • 当它是 sizeof 的参数时(sizeof "hello" 产生 6,而不是指针的大小);
  • 当它是_Alignof 的参数时(C11 中的一个新特性);
  • 当它是一元 &amp; 的参数时(&amp;arr 产生整个数组的地址,而不是它的第一个元素的地址;相同的内存位置,不同的类型);和
  • 当它是用于初始化数组对象的初始化程序中的字符串文字时(char s[6] = "hello"; 复制整个数组,而不仅仅是一个指针)。

这些例外都不适用于您的代码:

char *ptr;
ptr = "hello";

所以表达式"hello" 被转换为(“衰减”为)指向我上面提到的那个匿名数组对象的第一个元素('h')的指针。

所以*ptr == 'h',您可以通过内存推进ptr 以访问其他字符:'e''l''l''o''\0'。这就是 printf() 在你给它一个 "%s" 格式时所做的事情。

与字符串文字关联的匿名数组对象是只读的,但不是const。这意味着任何修改该数组或其任何元素的尝试都具有未定义的行为(因为标准明确说明了这一点)——但编译器不一定会警告您。 (C++ 生成字符串文字const;在C 中做同样的事情会破坏在const 添加到语言之前编写的现有代码。)所以不,你不能修改"hello" 的元素——或者至少你不应该尝试。为了让编译器在你尝试时发出警告,你应该将指针声明为const:

const char *ptr; /* pointer to const char, not const pointer to char */
ptr = "hello";

(gcc 有一个选项,-Wwrite-strings,它可以将字符串文字视为const。这将导致它警告一些就标准而言是合法的 C 代码,但这样的代码可能应该修改为使用const。)

【讨论】:

    【解决方案3】:
    #include <stdio.h>
    
    main()
    {
       char * ptr;
    
       ptr = "hello"; 
    
      //instead of above tow lines you can write char *ptr = "hello" 
    
       printf("%p %s" ,"hello",ptr );
    
       getchar();
    
    }
    

    在这里,您已将字符串文字"hello" 分配给ptr,这意味着字符串文字存储在只读内存中,因此您无法修改它。如果声明char ptr[] = "hello";,则可以修改数组。

    【讨论】:

      【解决方案4】:

      说什么?

      您的代码分配 6 个字节的内存并使用值“h”、“e”、“l”、“l”、“o”和“\0”对其进行初始化。

      然后它分配一个指针(指针的字节数取决于实现)并将指针的值设置为前面提到的 5 个字节的开头。

      您可以使用ptr[1] = 'a' 等语法修改数组的值。

      从句法上讲,字符串是一种特殊情况。由于 C 没有特定的字符串类型可言,它确实提供了一些快捷方式来声明它们等。但是您可以轻松地创建与使用 int 为字符串所做的相同类型的结构,即使语法必须有所不同。

      【讨论】:

      • ptr[1] = 'a'; 可能会或可能不会执行和/或可能会或可能不会将字符串中的“e”值修改为“a”。大多数现代系统(Linux、MacOS X、Windows NT、2K、XP 等 - 在 Win98 上不确定等)会在您这样做时出错,因为它是“只读内存”。
      • 这就是为什么我用更通用的术语“修改数组的值”来表达,以避免关于访问的问题,这完全是一个不同的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      • 1970-01-01
      • 2017-02-12
      • 1970-01-01
      • 2018-10-06
      • 2015-07-05
      相关资源
      最近更新 更多