我对C编程很新,我对指针如何工作感到困惑。如何使用ONLY指针复制值,例如...仅使用指针将x中的值复制到y中。
library(dplyr)
df %>%
group_by(site) %>%
mutate(avg.1 = mean(rf, na.rm=TRUE)) %>%
group_by(mon) %>%
mutate(avg.2 = mean(rf, na.rm=TRUE)) %>%
group_by(region, year) %>%
mutate(avg.3= mean(rf, na.rm=TRUE))
答案 0 :(得分:2)
这很简单。 &
返回变量的地址。所以当你这样做时:
ptr1 = &x;
ptr1
指向x
,或保留变量x
的地址。
现在假设您要复制ptr1
指向的变量中的值。您需要使用*
。当你写
y = ptr1;
ptr1
的值在y
中,而不是ptr1
指向的值。要设置ptr1
所指向的变量的值,请使用*
:
y = *ptr1;
这会将变量ptr1
的值指向y
,或者简单地说,将x
的值放在y
中。这是因为ptr1
指向x
。
要在下次解决此类简单问题时,请在编译期间启用编译器的所有警告和错误。
如果您使用的是gcc
,请使用-Wall
和-Wextra
。 -Wall
将启用所有警告,-Wextra
会将所有警告变为错误,并确认您不会忽略警告。
答案 1 :(得分:1)
什么是指针?
指针是C中的特殊基本类型。除了int
类型存储的小数,指针存储了内存地址。
如何创建指针
对于所有类型和用户类型(即结构,联合),您必须执行以下操作:
Type * pointer_name;
int * pointer_to_int;
MyStruct * pointer_to_myStruct;
如何指定指针
正如我所说,我指针存储了内存地址,因此&
运算符返回变量的内存地址。
int a = 26;
int *pointer1 = &a, *pointer2, *pointer3; // pointer1 points to a
pointer2 = &a; // pointer2 points to a
pointer3 = pointer2; // pointer3 points to the memory address that pointer2 too points, so pointer3 points to a :)
如何使用指针值
如果要访问指针的值,必须使用*
运算符:
int y = *pointer1; // Ok, y = a. So y = 25 ;)
int y = pointer1; // Error, y can't store memory address.
通过指针编辑变量的值
要通过指针更改变量的值,首先,您必须访问该值然后更改它。
*pointer1++; // Ok, a = 27;
*pointer1 = 12; // Ok, a = 12;
pointer1 = 12; // Noo, pointer1 points to the memory address 12. It's a problem and maybe it does crush your program.
pointer1++; // Only when you use pointer and arrays ;).
答案 2 :(得分:1)
在向已经知道如何编程的人解释什么指针时,我发现使用数组术语引入它们非常容易。
在所有抽象之下,你的计算机内存实际上只是一个大数组,我们称之为mem
。 mem[0]
是内存中的第一个字节,mem[1]
是第二个字节,依此类推。
程序运行时,几乎所有变量都存储在内存中。在代码中看到变量的方式非常简单。您的CPU知道一个数字,该数字是mem
(我称之为base
)中您的程序数据所在的索引,实际代码只是使用{{base
来引用变量1}}和偏移。
对于一段假设的代码,让我们看一下:
byte foo(byte a, byte b){
byte c = a + b;
return c;
}
一个天真但很好的例子,它实际上看起来像编译之后看起来像是:
base
为三个新字节腾出空间mem[base+0]
(变量a)设置为a
mem[base+1]
(变量b)设置为b
mem[base+2]
(变量c)设为总和mem[base+0] + mem[base+1]
mem[base+2]
base
移回原位
具体发生的具体细节是平台和约定,但通常看起来没有任何优化。
正如示例所示,a
b
和c
作为特殊实体的概念出现了。编译器在生成相关代码时计算为变量提供的偏移量,但最终结果仅处理base
和硬编码偏移量。
指针只是引用mem
数组中索引的一种奇特方式。实际上,指针实际上只是一个数字。这就是全部; C只是给你一些语法,使它更加明显,它应该是mem
数组中的索引而不是某个任意数字。
当你引用一个变量(比如&var
)时,编译器会检索它为变量计算的偏移量,然后发出一些大致意味着"返回base
之和的代码。变量的偏移"
这是另一段代码:
void foo(byte a){
byte bar = a;
byte *ptr = &bar;
}
(是的,它没有做任何事情,但它是为了说明基本概念)
这大致转换为:
base
为两个字节和一个指针mem[base+0]
(变量a)设置为a
mem[base+1]
(变量条)设置为mem[base+0]
mem[base+2]
(变量ptr)设置为base+1
的值(因为1是用于条形的偏移量)base
移回原先的位置在这个例子中,您可以看到,当您引用变量时,编译器只使用内存索引作为值,而不是在该索引的mem
中找到的值。
现在,当您取消引用指针(如*ptr
)时,编译器会将指针中存储的值用作mem
中的索引。例如:
void foo(byte* a){
byte value = *a;
}
说明:
base
为指针和字节腾出空间mem[base+0]
(变量a)设置为a
mem[base+1]
(变量值)设为mem[mem[base+0]]
base
移回原来的位置在此示例中,编译器使用内存中的值,其中该值的索引由内存中的另一个值指定。这可以达到你想要的深度,但通常只有一到两个深度。
由于引用的变量实际上只是数字,因此您无法引用引用或为引用赋值,因为base+offset
是我们从第一个引用获得的值,它不存储在内存中,因此我们无法获得存储在内存中的位置。 (&var = value;
和&&var
是非法声明)。但是,您可以取消引用引用,但这只会让您回到起始位置(*&var
是合法的)。
另一方面,由于解除引用的变量 是内存中的值,因此您可以引用解除引用的值,取消引用解除引用的值,并将数据分配给解除引用的变量。 (*var = value;
,&*var
和**var
都是合法陈述。)
此外,并非所有类型都是一个字节大,但我简化了示例,使其更容易掌握。实际上,在大多数机器上,指针会占用内存中的几个字节,但我将其保留在一个字节以避免混淆问题。一般原则是一样的。
mem
。varlocation
的位置,该位置由编译器为每个变量指定。mem[varlocation]
。 varlocation
的数值。 mem[mem[varlocation]]
的值。//Your variables x and y and ptr
int x, y;
int *ptr;
//Store the location of x (x_location) in the ptr variable
ptr = &x; //Roughly: mem[ptr_location] = x_location;
//Initialize your x value with scanf
//Notice scanf takes the location of (a.k.a. pointer to) x to know where
//to put the value in memory
scanf("%d", &x);
y = *ptr; //Roughly: mem[y_location] = mem[mem[ptr_location]]
//Since 'mem[ptr_location]' was set to the value 'x_location',
//then that line turns into 'mem[y_location] = mem[x_location]'
//which is the same thing as 'y = x;'
总的来说,正如其他人已经指出的那样,你只是错过了取消引用该变量的明星。
答案 3 :(得分:0)
只需将y = ptr1;
更改为y = *ptr1;
。
这是因为ptr1
是指向x
的指针,要获得x
的值,您必须取消引用 ptr1
添加前导*
。