【问题标题】:Pointers to strings指向字符串的指针
【发布时间】:2013-04-26 08:58:52
【问题描述】:

我是 C 编程的新手。我对指针的混乱行为感到困惑。特别是涉及到字符串和数组时。

我知道我写不出来,

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

因为显然它会尝试写入内存的第 5 个位置。这会使程序崩溃。我必须初始化“数字”。

但是当涉及到字符串时,我可以这样写,

#include <stdio.h>
int main()
{
 char *name="xxxxx";
 printf(name);
} 

而且它也有效。所以这意味着它隐式初始化“name”指针。我也知道 name=&name[0] 但我也发现了 name=&name。怎么会这样? 因为,对我来说,它看起来是两个同名的变量。谁能告诉我字符串是如何在内存中创建的?(一直以来我都假设它创建了 name[0].....name[n-1] 和另一个名为“name”的变量(一个指针),在里面我们把 name[0] 的位置。好像是我错了。)

PS:-我的英语可能不太好,如果有人能给我一个关于上述问题的链接,将不胜感激。

【问题讨论】:

  • C 中指针的行为并不混乱。它定义明确。
  • name 绝对不同于 &amp;name 如果 namechar* 类型。只有当namechar[] 并且只有值相同但类型不同时,它才是正确的。对于 char name[],名称属于 char[] 类型,但 &name 属于 char(*)[]
  • 另外,请一次只问一个问题,而不是把所有让你困惑的问题都放在同一个问题中。
  • 很抱歉将几个问题放在一起。当某些事情不确定时,它会引发更多问题?但无论如何谢谢。

标签: c arrays string pointers memory-management


【解决方案1】:

那是因为你这些字符串实际上是字符数组。你对char *name = "xxxxx"; 行做了什么:你构造了一个包含 6 个字符值的数组(其中 5 个是 'x',最后一个是 '\0')。 name 是指向该数组的指针。

这就是 C 中通常处理字符串的方式,您有某种字符序列,以 '\0' 字符结尾,以告诉像 printf 这样的函数在哪里停止处理字符串。

【讨论】:

  • 您还可以补充说printf(name) 是不好的做法
【解决方案2】:

让我们考虑这段代码:

 char *name="xxxxx";

这里发生的情况是字符串xxxxx被分配了内存并且一个指向该内存位置的指针,或者该字符串的address被传递给pointer变量name .或者换句话说,您使用该地址初始化name

printf() 是一个可变参数函数(接受一个固定参数,后跟随机数量的参数)。printf() 的第一个参数是 const char* 类型。传递时字符串标识符 name作为参数表示该字符串的基地址。因此您可以使用

printf(name);

它只会输出xxxxx

name=&amp;name too. How can it be?--这是一个有道理的问题。

让我先用一个现实世界的比喻来解释一下。假设您在住房协会的一排房屋中拥有第一所房屋。假设它的地块编号0。其他房屋位于地块1,2,3......现在假设有一个指针到你家,还有另一个指向整个房协行的指针。两个指针不会有相同的地址,即plot 0吗?这是因为指针表示单个内存位置。这里重要的是指针的type

将这个类比为字符串(字符数组),name 标识符仅表示字符串的基地址,即其第一个字符的地址(如第一所房子的地址)。在数字上与整个字符串的地址,即(&amp;name),在我的类比中是房屋的ROW。但它们的类型不同,一个是char*类型,另一个是char**类型。

【讨论】:

  • 投反对票的人,停止你的“报复”投反对票。如果你觉得我错了,请告诉我我错在哪里。
  • 我根本没有对你的答案投票。在你更正之后,我删除了我的 cmets,因为你有一个小错误。所以如果碰巧你指的是我的“复仇”:我没有我不喜欢那个。
【解决方案3】:

与许多编程语言一样,C 支持“文字”的概念 - 遇到这种特殊语法时,会导致编译器以特殊方式创建值。

例如,

-2 是一个整数文字。遇到时,编译器会将其视为 int 类型的值,内容为 -2。 "..." 是一个 字符串文字 - 遇到时,编译器会在一个特殊的内存区域中分配新空间,用与您在文字中使用的字符相对应的数据填充它,最后添加一个 0最后使用指向该区域的指针,类型为char*,作为文字表达式的结果。所以char* s = "hello" 是从char* 类型的东西到char* 类型的变量的赋值——完全合法。

你在这里偷偷问了另一个问题——为什么a == &amp;a[0]。最好一次问一个问题,但要点是a[n]*((a)+(n)) 相同,因此:

&a[0] == &*(a+0) == a+0 == a

【讨论】:

  • "-2" 看起来像字符串文字:-)。也许你可以使用 ``.
  • @user2247911 我不知道&amp;[a]是什么...无论如何,最好单独问一个新问题。
  • 对上述声明感到抱歉。应该是a=&a。我的错。不过不用担心,因为后来我意识到你已经给了我我期望的答案。
  • "最后使用指向该区域的指针,类型为 char*,作为文字表达式的结果" 从技术上讲,表达式具有数组类型,它被隐式转换为指向其第一个元素的指针因为它在需要指针类型的上下文中使用。
【解决方案4】:
 char *name="xxxxx";

这会在内存中创建一个char array(const),并将其第一个元素的地址分配给name。 char* 数组名称就像指针。 &amp;name[0] 表示第一个元素的地址,name(在 c,cpp 中,只有 char * 数组名称也会为您提供第一个元素的地址(bcos 这就是分配给 name 在第一个位置本身的地址) )) 也给出了相同的结果。

符号name[i] 被翻译为*(name+i),因此您实际上有一个基地址name,您可以在其中添加下标。 (计算按指针算术)。 printf("%s", name) 旨在从起始地址打印到 \0(附加到使用 char* 又名字符串文字创建的字符串的末尾)

也检查this

【讨论】:

    【解决方案5】:

    当 C 编译器看到表达式时,基本上会发生什么

    char *name = "xxxxx";
    

    是的,它会说。嘿"xxxxx",这是一个常量字符串(它是一个以0 字节结尾的字节数组),并将其放入生成的程序二进制文件中。然后它将用字符串替换内存位置,有点像:

    char *name = _some_secret_name_the_compiler_only_know;

    其中_some_secret_name_the_compiler_only_know 是一个指针,指向程序执行后字符串所在的内存位置。并开始解析文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2014-11-29
      相关资源
      最近更新 更多