6

一直让我感到困惑的一件事是字符指针。在漫长的四年之后,我再次徘徊在 c 中。

以上述案例为例。为什么char指针会以这种方式表现?当指针指向任何内容时,我们如何直接寻址指针的内容,或者它就像 char 指针存储地址以外的东西!

#include <stdio.h>
#include <stdlib.h>

int main()
{ 
char* charPtr="I cant understand why";
int* intPtr=60;


printf("%d\n", intPtr); //displays 60
printf("%p\n", intPtr); // displays the hex value of 60

printf("%s\n", charPtr); // displays the wh0le string
printf("%p\n", charPtr); // displays the start address of the string
return 0;

}

接下来是int指针,它如何接受值 60 以及它存储在哪里?

撇开 char 指针和 malloc 不谈,我认为指针的基本思想是获取指向的地址!

为什么这些情况

 *intptr = 60 ; // should be setting the pointee's value to 60
  intptr = 60 ;  // sets the address

抛出编译错误同时

  int* intPtr=60;

在没有得到指针的情况下偷偷溜进来(或者是60作为地址,如果是这样,为什么在前一种情况下这是不可接受的)!

我想我在这里遗漏了一些东西,但是嘿!你猜怎么了 ?他们告诉我在 SO 中搜索!

编辑:将 char 指针指向的地址提供给 int 指针也不会引发错误!

int8_t* intPtr= (int8_t*)0x80485c8 ; // works without casting too ! I guess addresses are acceptable.

取消引用它会给出一个I与字符串的第一个相等的值。这是一个好的做法还是存在任何其他解释这忽略了它们的字节位大小分配,例如 int 可以容纳一个 char 等等..?

正如 hmjd 指出的那样,“初始化语法”是问题所在!我编写自己的代码没有问题,但是在修改某人的代码时会出现问题!

4

4 回答 4

6

当指针指向任何内容时,我们如何直接寻址指针的内容,或者它就像 char 指针存储地址以外的东西!

认为混淆是初始化语法。这:

char* charPtr="I cant understand why";

不取消引用charPtr。它相当于:

char* charPtr;
charPtr = "I cant understand why";

两个代码片段都将字符串文字的地址存储"I cant understand why"charPtr. 没有指向什么都没有发生的指针的解引用。任何类型的指针变量只能存储地址。

这:

int* intPtr=60;

存储60in的地址intPtr:没有int发生分配或延迟。此时不int存在变量。编译器应该在这一行发出警告。任何顺从的尝试intPtr很可能会导致崩溃。

于 2012-08-29T09:38:10.207 回答
4

在 C 中,像“我不明白为什么”这样的字符串文字char被存储为这样的数组,这样内存在程序的整个生命周期内都是可用的(所有地址都是凭空提取的,并不意味着代表任何特定的平台或架构):

Item        Address        0x00  0x01  0x02  0x03
-----       -------        ----  ----  ----  ----
"I..."      0x00080000      'I'   ' '   'c'   'a'
            0x00008004      'n'   '''   't'   ' '
            0x00008008      'u'   'n'   'd'   'e'
            0x0000800C      'r'   's'   't'   'a' 
            0x00008010      'n'   'd'   ' '   'w' 
            0x00008014      'h'   'y'  0x00  0x??

字符串字面量也是一个数组表达式,在大多数情况下,“N-element array of T”类型的表达式将被转换为“pointer to T”类型,其值将是数组第一个元素的地址(例外情况是数组表达式是sizeof或一元运算符的操作数&,或者是用于在声明中初始化数组的字符串文字)。

所以当你写

char* charPtr = "I can't understand why";

您将字符串文字的地址charPtr复制到:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
charPtr     0xffbe4000     0x00  0x08  0x00  0x00

请注意,如果声明是

char str[] = "I can't understand why";

str将被分配为一个char足够长的数组来保存字符串,并且字符串的内容将被复制到它:

Item        Address        0x00  0x01  0x02  0x03
-----       -------        ----  ----  ----  ----
str         0xffbe4000      'I'   ' '   'c'   'a'
            0xffbe4004      'n'   '''   't'   ' '
            0xffbe4008      'u'   'n'   'd'   'e'
            0xffbe400C      'r'   's'   't'   'a' 
            0xffbe4010      'n'   'd'   ' '   'w' 
            0xffbe4014      'h'   'y'  0x00  0x??

当你写

int* intPtr = 60;

您正在使用 60 初始化指针值,而不是将其设置为指向值为 60 的匿名整数:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
intPtr      0xffbe4004     0x00  0x00  0x00  0x3C

地址 60 很可能不是有效地址,因此尝试取消引用intPtr很可能会导致未定义的行为。

你有没有写过类似的东西

int x = 60;
int *intPtr = &x;

那么你会有这样的情况:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
x           0xffbe4004     0x00  0x00  0x00  0x3C
intPtr      0xffbe4008     0xff  0xbe  0x40  0x04

在这种情况下, 的值intPtr是 的地址x

最后,注意初始化赋值不是一回事。

T *x = value;

不取消引用x并分配value给结果;它value直接分配给x. 的类型value被视为T *。请注意,您应该收到警告

int *intPtr = 60;

沿着“从整数制作指针而不进行强制转换”的思路。

于 2012-08-29T11:34:02.690 回答
3

当你写:

 char* charPtr = "I can't understand why";

这意味着字符串“我不明白为什么”的基地址被分配给

charPtr 因为字符串文字也是指向该字符串的指针。

它可以被视为:

存储在 char 数组中的字符串的概念

这意味着,在 charPtr 中存储了整个字符串的基地址。现在这就是您在代码中所做的。

 char *charPtr="i cant understand why";

除此之外,如果您打印以下语句:

printf("%c","i cant understand why"[0]);//prints i
printf("%c","i cant understand why"[2]);//prints c

这两个 printf 证明了我的概念,即字符串“我不明白为什么”本身就是一个指向存储字符串的 char 数组的指针。

于 2012-08-29T12:51:15.693 回答
1

intPtr被初始化为指向绝对内存地址60。这里没有后备商店。

由于您没有取消引用指针本身,因此您永远不会尝试读取60可能会使您的程序崩溃的地址,具体取决于环境。

相反,您将指针值传递给该指针值,该指针值printf几乎可以作为参数,并按照您在格式字符串中指定的值解释这些值。在您的情况下,它将解释指针的地址而不是指针值。地址是60这样显示的。如果你使用*intPtr它可能会崩溃。

于 2012-08-29T09:38:45.127 回答