【问题标题】:Array of pointers to strings(base type of pointers)指向字符串的指针数组(指针的基本类型)
【发布时间】:2019-11-13 03:46:34
【问题描述】:
int main(){
int i;
char *names[]={"pankaj",
               "anshul",
               "dheeraj",
               "rahul"
               };
for(i=0;i<4;i++)
    printf("\n%u",names[i]);}

当我对此进行编码时,我发现所有字符串都以连续的方式排列。例如。如果names[0]=436,则names[1]=443,names[2]=450,names[3]=458,因此所有字符串都以连续方式分配内存,其中\0作为字符。 但是字符串可以在任何地方分配内存,并且它们的基地址存储在指向这些字符串的指针数组中。不应该是这样吗? 此外,声明的数组中这些指针的基本类型是什么?它们是 指向 char 的指针还是 指向字符串的指针。**就像这些 **char(*p)[6] 类型的指针数组或 数组char *p 类型的指针。 我们可以使用这个名称数组来处理整个字符串,例如:

int main()
{
char *names[]={"pankaj",
               "anshul",
               "dheeraj",
               "rahul"
               };
char *temp;
printf("Original:%s%s\n",names[2]names[3]);
temp=names[2];
names[2]=names[3];
names[3]=temp;
printf("New:%s%s",names[2],names[3]);
return 0;
}

在这种情况下,我可以通过交换指针数组字符串的基地址来反转 dheerajrahul (作为一个整体)字符串的位置。 通过它看起来指针是 pointer to string 类型,即指针指向整个字符串,而不是仅指向字符串的第一个字符。 因此,如果它们不是指向字符串的指针,而只是指向 char 的指针;指向它们各自字符串的第一个字符,我们如何通过仅交换指针数组中 dheerajrahul 的基地址来交换整个字符串。

【问题讨论】:

  • 你需要明白几件事: (1) C 并没有真正的“字符串”类型; C 使用 char 的数组模拟字符串。 (2) C 中的数组和指针之间存在非常密切的关系,因此每当我们使用数组时,我们经常使用指针来这样做。 (3) 没有“指向字符串的指针”这样的东西。 (4) 尽管字符串在内部表示为char的数组,但由于数组和指针之间的密切关系,我们经常使用指向charchar *的指针来引用字符串。
  • 那么问题是什么?

标签: c arrays string pointers


【解决方案1】:

文字字符串实际上是一个只读字符数组(包括空终止符)。与其他数组一样,它们衰减为指向其第一个元素的指针。您的数组names 是一个指针数组,每个指针都初始化为指向文字字符串的第一个元素(第一个字符)的指针。

当你交换names 的元素时,你只交换指针。

您可以通过使用"%p" 格式说明符打印来轻松检查指针本身:

printf("names[2] = %p, names[3] = %p\n", (void *) names[2], (void *) names[3]);

如果您在交换之前和之后执行此操作,您将看到指针已在您的数组中交换。文字字符串本身的内容仍然是相同的。

在指针交换之前数组看起来像这样:

+----------+ |姓名[0] | ----->“pankaj” +----------+ |姓名[1] | ----->“安舒尔” +----------+ |姓名[2] | ----->“dheeraj” +----------+ |姓名[3] | ----->“拉胡尔” +----------+

指针交换后的数组如下所示:

+----------+ |姓名[0] | ----->“pankaj” +----------+ |姓名[1] | ----->“安舒尔” +----------+ |姓名[2] | -\ /-> “dheeraj” +----------+ x |姓名[3] | -/ \->“拉胡尔” +----------+

字符串本身的位置仍然相同。只是数组 names 的内容发生了变化。


作为一个小旁注,由于 C 中的文字字符串是只读的,因此您应该真正将它们视为常量并使用 const char * 作为指向它们的指针。

【讨论】:

  • 这里名称[2] =450,名称[3]=458。在交换名称[2]=458 和名称[3]=450 之后。因此现在 d 被移动到地址 458(dheeraj 是名称)并且 r(rahul 的第一个字符)现在被移动到 450 地址。但是为什么 char 在 451应该是 h (dheeraj) 更改为 (rahul 的第二个字母)。如果指针仅指向字符串的第一个字符,则只有那些应该更改,字符串的其余字符即使在交换之后也应保持在其原始地址。
  • @VIbhor 不不不,您只交换数组本身中的 pointers。您不会在字符串中复制或移动字符。请参阅我的更新答案,希望它能让您看得更清楚。
  • 哦,是的..明白了!
  • 但是为什么字符串以连续的方式获得内存呢?他们本可以随机分配内存,并将其基地址收集在指针数组中。
  • @VIbhor 这是一个实现细节。未指定编译器存储文字字符串的方式和位置。
【解决方案2】:

C 没有 string 这样的数据类型 - 在 C 中,字符串只是一个包含零值终止符的字符值序列。字符串(包括字符串文字)存储为字符类型的数组(charwchar_t 用于“宽”字符串)。

除非它是sizeof 或一元&amp; 运算符的操作数,或者是用于在声明中初始化字符数组的字符串字面量,否则为“N”类型的表达式 T"的-element数组被转换("decays")为"pointer to T"类型的表达式,表达式的值是数组第一个元素的地址。

鉴于您的声明:

char *names[]={"pankaj",
               "anshul",
               "dheeraj",
               "rahul"
               };

每个字符串字面量("pankaj""anshul" 等)的类型为“N-element array of char”,其中N 是每个字符串的长度加 1(需要一个额外的元素考虑到 0 终止符)。每个文字都作为数组存储在内存中,以便在程序的整个生命周期内都可用。它们被连续分配并不奇怪,但这不是可以指望的。字符串文字 supposed 是不可变的,但是尝试修改字符串文字内容的行为是 undefined - 它可能有效,也可能无效,您可能会得到运行时错误,你可能没有,等等。

因为它们不是 sizeof 或一元 &amp; 运算符的操作数,并且由于它们不用于初始化 character 数组,所以每个文字表达式都被转换(“decays” ) 从类型“N-char”的元素数组到“指向char”的指针(char *),每个文字表达式的值是字符串中第一个字符的地址。这些指针值是实际存储在数组中的值。

如果你听到有人在 C 中引用指向字符串的指针,他们真正的意思是指向 char 的指针,它指向字符串的第一个字符。

所以,总结一下:

  • names 是指向 char 的指针数组
  • 除非它是sizeof 或一元&amp; 运算符的操作数,表达式 names 将衰减为指向char (char **) 的指针,并且表达式的值将是数组第一个元素的地址
  • 每个names[i] 都有char * 类型(指向char 的指针)
  • 每个names[i]都存储了初始化器中每个字符串的第一个字符的地址
  • 每个字符串文字的内容都存储在“某处”,以便它们在程序的整个生命周期内都可用
  • 尝试修改字符串文字的内容将调用未定义的行为 - 它可能会按预期工作,也可能不会,您可能会遇到运行时错误,也可能不会,等等。

您的第二个代码 sn-p 只交换指针,而不是字符串内容 - 字符串本身是未修改的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多