我们什么时候向指针添加*?

时间:2017-08-29 02:54:09

标签: c pointers

在C中,指针永远是我的痛苦。

我的问题:当我们向指针添加*时?

我看到了这两个代码:

第一个:

int x;
int *ptr;
ptr = &x;

第二个:

int x;
int *ptr;
*ptr = 5;

为什么第一个指针在指针前面有*,但第二个指针没有?

更新: 为什么我们不*pr = &xptr = 5

7 个答案:

答案 0 :(得分:3)

变量保存一个值,该值存储在内存中的某个位置(在地址处)。指针是一个变量,它将值保存为地址。

*的一个用途是声明一个指针;在发布的代码中,int *ptr;声明指向int的指针。表达式&x的计算结果为x的地址,因此ptr = &x;将变量x的地址存储在(指针)变量ptr中。如果单独使用变量ptr,请执行以下操作:

printf("ptr = %p\n", (void *) ptr);

ptr将评估ptr中存储的值,即x的地址。请注意,打印指针值需要%p转换说明符,并且必须将其转换为(void *)以避免未定义的行为。

如果要使用存储在指针所指向的变量中的值,则使用*运算符取消引用指针。也就是说,如果您想使用ptr获取x中存储的值,请使用*ptr

printf("*ptr = x = %d\n", *ptr);

同样,如果要将值存储在指针指向的变量中,可以取消引用指针:

*ptr = 5;
printf("x is now %d\n", x);

现在请注意,在您的第一个代码段中,x未初始化(包含不确定的值),但x已定义,并且有一个地址,因此ptr确实存在确定价值。但在第二个代码段中,ptr未初始化,因此包含不确定值。使用不确定值是未定义的行为,因此在这种情况下行:

*ptr = 5; 

导致未定义的行为。

以下是发布代码的一个版本,可以避免未定义的行为:

#include <stdio.h>

int main(void)
{
    int x;
    int *ptr;

    ptr = &x;
    printf("ptr = %p\n", (void *) ptr);

    x = 1;
    printf("*ptr = x = %d\n", *ptr);

    *ptr = 5;
    printf("x is now %d\n", x);

    return 0;
}

答案 1 :(得分:1)

声明中的

*只是指定此变量是指针。 *使用变量时(即声明以外的任何地方)意味着你想要访问指针指向的任何东西,而不是指针本身。

当你想让指针指向与之前指向的不同的对象时,请将*保留(右边的任何内容应该是某个地址):

ptr = &thing_it_points_to;

当您希望指针保持指向同一个对象时使用*,但更改该对象的值: *ptr = 5; // 5 is not an address here, it's the value I'm assigning to the int that this points to

所以,你的第一个:

int x;
int *ptr; // * while declaring the variable tells us this is a pointer type
ptr = &x; // Get a pointer that points to 'x', and store it in 'ptr'

第二个:

int x;
int *ptr; // * while declaring the variable tells us this is a pointer type
*ptr = 5; // * while using the variable means to get the thing this pointer points to, and set it to 5
BTW,这两个都是无效的代码; x在第一个中初始化之前使用ptr,在第二个中初始化之前使用wData

答案 2 :(得分:1)

指针可能会让人感到困惑。

首先,指针是一个存储另一个变量地址的变量。

声明指针时,需要使用*声明它。 C是一种静态类型语言,您需要在分配变量之前定义变量的类型。

因此,int *ptr声明一个整数指针。 char *string是一个字符指针。

但是,在声明之后,当您再次使用*时,它会取消引用指针。你基本上可以&#34;阅读&#34;那是&#34;&#34;的价值指针指向的内存地址。

示例:

int *ptr;
int x;

x = 10;
/*
* store the address of x in ptr
* so ptr is now pointing to x
*/
ptr = &x

/*
* this is printing the pointer
* which is pointing to the address of x
* so this will print you a memory address
* Output will be something like: 0x7fff9575c05f
*/
printf("%p\n", ptr);

/*
* this prints the value of the memory address
* save which is the value of x
* so in this case, this will print 10
*/    
printf("%i\n", *ptr);

答案 3 :(得分:1)

如果*出现在声明中,例如:

声明指针变量pt 指针变量*pt。变量pt指向int类型,您可以使用它来存储地址。

int *ptr;
ptr = &x;

如果*出现在赋值语句中,它取消引用指针,*ptr实际上意味着 获取指针指向的内存中的数据/值< / EM>

*ptr = 5;

这意味着将整数5赋给指针变量`ptr。

的内容
  

为什么我们不做* pr =&amp; x和ptr = 5?

*pr = &xptr=5实际上(i)将x的地址分配给指针的值(ii)将整数赋给指针变量

导致错误/未定义的行为。

答案 4 :(得分:0)

所以基本上C中的指针将地址存储到特定的内存中。

任何变量(例如上例中的x)都存储在内存中的某个位置,因此可以使用指针来表示位置。

在C中,在内存中获取变量位置的操作是使用运算符&amp;,所以ptr =&amp; x表示获取指向存储x的内存的指针并将位置存储到指针ptr中

在指针位置获取变量是指针前面的运算符*,因此* ptr = 5表示设置指针ptr指向5的内存的4个字节。

但是,第一个代码中的x未初始化,导致未定义的行为,并且第二个代码中的ptr也未初始化,并且语句* ptr = 5肯定会导致运行时错误,因为内存ptr表示无法修改通过该计划。严格来说,你的两个代码都是无效的。

答案 5 :(得分:0)

在您的代码中

int *ptr;
ptr =&x;

此处ptr正在寻找存储int类型整数的地址。

例如:0x77C79AB2

*ptr = 5;

此处ptr查找整数,而不是地址。

例如:5 // (some number)

因为地址不被视为整数。 您需要将其强制转换为整数

在你的问题中

*ptr = &x and ptr =5

会抛出错误,因为它找不到第一个中的整数和第二个

中的地址

答案 6 :(得分:0)

正如其他人所指出的那样,'*'可以用来告诉编译器和其他程序员你声明一个包含地址的变量。 在第一种情况下,您正在存储变量x的地址(使用'&amp;')并存储在ptr中。在第二种情况下,您将获取地址ptr存储的值。 所以你有这样的事情:

--------------      --------------
|    ptr     |      |      x     |
|++++++++++++|      |++++++++++++|
|  xaddress  |----->|   xvalue   |       
|++++++++++++|      |++++++++++++|

你说ptr指向x,因为ptr持有x的地址。

现在真的,指针只是该语言的一个便利功能。你没有 使用指针来存储地址,尽管你应该这样做。以下内容完全有效:

int x;
int ptr;
ptr = &x;

但是你的可读性和便利指针运算都会失败。如果你做了ptr + 1,那么如果你已经将ptr声明为指针,那么你只会提前1个字节而不是4个字节。此外,最终你会想要在整数变量中访问地址存储的内容,所以你必须做一个丑陋的演员,如:* (int*)ptr你必须要特别小心,因为整数大小不是始终与整数指针大小相同。你的指针可能是8个字节,整数可能是4,所以你实际上必须声明long long ptr = &x;