【问题标题】:Referencing char array pointers in C在 C 中引用 char 数组指针
【发布时间】:2013-10-22 20:40:54
【问题描述】:

我遇到了指针取消引用问题。

在 C 中,&a 表示 a 的地址。如果 a 是指针,则 &a 仅表示该指针的地址。

如果我们有:

char ptr [] = "abcd"

ptr 应该是指向第一个字符的指针,即'a'。因此,

&ptr

应该是ptr的地址,与'a'的地址不同。但是,当我尝试以下代码时,我真的很困惑:

int main()
{
    char a [] = "abcd";

    printf("0x%X 0x%X", a, &a);

}

Output: 0xBF7E62AB 0xBF7E62AB

有人可以解释为什么 a 和 &a 具有相同的值吗?根据我的理解,它们应该是不同的。提前谢谢

【问题讨论】:

  • ptr 不是指针。这是一个数组。你可以看出,因为你的代码中没有*,而是一个大胖子[]
  • 尝试打印a+1&a+1 的值,你会看到不同。 web.torek.net/torek/c/pa.html 很好地回答了你的问题,顺便说一句。
  • @KerrekSB 但是,嘿,一个数组,我只是一个指针而已???
  • @H2CO3:不要喷 - “iznt it” 是一个死的赠品。真正的专业人士从不质疑自己的假设,而是自以为是地把它们当作事实,然后愤怒地斥责现实不符合他的结论。
  • @KerrekSB 我希望那是讽刺。 :) “真正的专业人士从不质疑自己的观点”……这种行为我见过多少次了……

标签: c pointers


【解决方案1】:

所以如果我们有:char ptr [] = "abcd",ptr 应该是指向第一个字符的指针。

没有。一点也不。

ptr 是一个数组。并且数组不是指针。

确实,如果您将ptr 声明为真正的指针,那么您将获得预期的行为:

const char *ptr = "abcd";
printf("ptr = %p, &ptr = %p\n", (void *)ptr, (void *)&ptr);

至于为什么数组的地址与其第一个元素的地址相同:这很合逻辑。该数组表示一个连续的元素序列。数组的地址是数组在内存中的开始位置。它从第一个元素开始的地方开始。因此,第一个元素的地址(相当“可以”——标准不强制要求这种行为)与数组本身的地址相同。

+-----------+-----------+- - - -
| element 1 | element 2 |
+-----------+-----------+- - - -
^ start of array
^ start of first element

【讨论】:

  • 你需要在那里强制转换为 void 吗?
  • @detly 是的,绝对是,否则它是未定义的行为(%p 需要一个指向 void 的指针,此外,printf() 是可变参数,因此通常不会进行隐式转换。) (在实践中,这个“工作”没有演员,事实上,我是演员的强烈反对者,特别是在void *的情况下,但不幸的是,这是一个案例——我唯一的案例知道 - 这是强制性的。)
【解决方案2】:

有人可以解释为什么 a 和 &a 具有相同的值吗?根据我的理解,它们应该是不同的。

在声明中

  printf("0x%X 0x%X", a, &a);  

a&a 属于不同类型。 achar * 类型(衰减后),而 &achar (*)[5] 类型。
a 衰减到指向第一个元素的指针,因此 a 是第一个元素的地址字符串。而&a 是字符串"abcd" 的地址,它等于第一个元素的地址。

【讨论】:

  • &a 不是char ** 类型。它的类型为char (*)[5]
  • @H2CO3;那是错字。
  • @kotlomoy;现已编辑。
  • @hacks 我知道那种感觉 :)
【解决方案3】:

数组不是指针。当你说 &p 是指针的地址时是对的,如果 p 是这样定义的:

char *p;

一个数组是不同的,并且没有完全相同的行为。

使用数组:

char a[] = "abc";,&a[0]是你数组中第一个元素的地址,和a一样。

【讨论】:

    【解决方案4】:

    char a[] = "abcd" 没有声明指向 "abcd" 的指针 a 而是一个数组。即使数组可以衰减为指针,它也是不同的类型,&aa 产生相同的地址。

    基本上a 将地址生成到数组的第一个元素,因此它等价于&a(和&a[0])。

    【讨论】:

    • 我可以执行 printf(%x,*a),它将以十六进制打印“a”,这是该数组中的第一个元素,其行为与指针相同。所以如果给我一个类似a的东西,就没有办法判断它是数组还是指针,但是它们的返回值是不同的?这对我来说完全没有意义。
    • 这是因为当将数组名称传递给printf 时,它将衰减为指向第一个元素的指针。这就是为什么取消引用它会给你a。但这并不意味着数组就是指针。
    • 假设我声明了一个函数并且一些用户不小心传入了一个数组而不是一个指针。在那种情况下,有没有办法区分数组和指针?还是段错误是唯一的解决方案? :\
    • @turtlesoup 我看不出“段错误”是如何相关的。一旦将数组传递给函数,被调用的函数就无法判断您传递的是数组还是指针。差异仅在函数的外部中很明显。
    • @turtlesoup 如果将数组传递给函数,它会自动转换为指向数组第一个元素的指针。
    【解决方案5】:

    数组总是会引用它存储在内存中的位置,这就是为什么当你打印a时,它会给你它所在的地址,这等于让指针指向数组(&a)

    【讨论】:

      【解决方案6】:

      为了获得你寻求改变的行为

      char a [] = "abcd";
      

      char *a  = strdup("abcd");
      

      或只读字符串

      const char *a  = "abcd";
      

      然后,您将获得 a 和 &a 的不同地址。

      将数组传递给函数时,数组会转换为指针。 使用您的原始程序尝试

      printf("%d %d\n",sizeof(a),sizof(&a));
      

      第一个会随着字符串的大小而变化,第二个会基于你机器上的指针大小。

      【讨论】:

      • @H2CO3 在 C 中,字符串文字的类型是 char [],而不是 const char [],对吧?
      • @AlokSinghal 完全正确。但是,它们是不可修改的(尽管它们不是由const 元素组成的),并且从字符串文字到char * 的转换已被弃用(至少如果我们可以相信clanggcc) .因此,最好使用指向const 的指针来指向字符串文字。 (在 C++ 中,他们做对了,而且字符串文字的类型为 const char []。)
      猜你喜欢
      • 2021-01-26
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-26
      • 2023-03-17
      相关资源
      最近更新 更多