当我被介绍到指针时,我被告知它们是有用的,因为它们使我们可以修改输入到通常无法修改的函数中的某些变量。例如:
void copy(int *p, int *s);
int main(){
int a = 4, b = 10, *p = &a, *s = &b;
copy(p, s);
}
void copy(int *p, int *s){
*s = *p;
*p = 0;
}
因此,即使“ a”和“ b”通常不可修改,“ b”也等于“ a”,“ a”等于0。
在谈论列表,特别是在列表中添加元素时,我可以使用如下函数:
struct list{
int n;
struct list *next;
}
struct list *first = NULL;
int main(){
int n = 3;
first = add_to_list(first, n);
}
struct list *add_to_list(struct list *first, int n){
struct list *new_node;
new_node = malloc(sizeof(struct list));
if(new_node == NULL) exit(EXIT_FAILURE);
new_node->value = n;
new_node->next = first;
return new_node;
}
我特别关心的是为什么函数不能简单地返回void类型,而不是编写“ return new_node” ,而不是简单地编写“ first = new_node” 。因为first是指针,所以如果我在程序中的任何地方修改它,原始指针也应该修改,就像我在第一个示例中发生的那样,对吗?
另外,还有一个无关的问题,但是如果我有这样的功能:
void first_to_n(int a[], int n){
a[0] = n;
}
可以说是在main中声明的原始向量a的第一个元素也被修改了,对吗?因为向量可以视为指针
答案 0 :(得分:1)
当我被介绍给指针时,我被告知它们是有用的,因为它们使我们可以修改输入到通常无法修改的函数中的某些变量。
除其他事项外,例如创建非平凡的数据结构并避免复制。
因为第一个是指针,所以如果我在程序中的任何地方修改它,那么原始指针也应该修改,就像我在第一个示例中发生的那样,对吗?
first
(参数)是first
(全局)的副本。因此,first = new_node
仅会修改您的指针,而不会修改全局指针。
这在您的第一个示例中更加清楚:
void copy(int *p, int *s){
*s = *p;
*p = 0;
}
例如,如果您正在做p = 0;
,则只修改指针,而不修改指向的值。
可以说是在main中声明的原始向量a的第一个元素也被修改了,对吗?因为向量可以视为指针
那不是一个“向量”(数组),即使它看起来像一个数组,它也是一个指针。这是C的一大难题。
但是,实际上,a[0] = 0;
正在修改参数所指向的第一个值(在main
中)。
答案 1 :(得分:1)
让我们说我们有类似下面的代码
void funcA(int x)
{
x = 0;
}
void funcB(int *y)
{
y = NULL;
}
int main(void)
{
int a = 10;
int *b = &a;
funcA(a);
funcB(b);
}
调用funcA
时发生的事情是将a
的 value 复制到函数内部的单独变量x
中。进行呼叫时,值10
的两个副本存储在不同的位置。当在函数内部完成分配x = 0
时,仅修改局部变量x
。
对于funcB
也会发生同样的情况。变量b
的 value 被复制到函数中单独的变量y
中。这意味着有两个单独且不同的变量指向同一位置。但是一旦分配y = NULL
完成,那就不再是事实。变量y
不再指向相同的位置,但是在main
函数中b
未被修改,因为仅将值的副本传递给了该函数。
如果我们现在举一个稍微不同的例子
void func(int *x, int **y)
{
*y = x;
}
int main(void)
{
int a = 10;
int b = 20;
int *c = &a; // Make c point to the variable a
func(&b, &c);
}
调用函数后,c
不再指向a
,而是指向b
。这是因为对于第二个参数,我们传递的值为&c
,它是指向变量c
的指针。然后,在函数内部,我们可以使用解引用运算符访问y
指向的内容(在c
函数中将成为变量main
)。
答案 2 :(得分:0)
我特别关心的是为什么函数不能简单地返回 类型无效,除了写“ return new_node”,我不能简单地 写“ first = new_node”。
正如其他答案所解释的,您不能因为first
是函数外部指针的“副本”。但是,如果要改为更改函数,以使您将“指针指向指针”传递给了指针,而不是仅传递了“指针”,则可以更改外部值,即“复制”函数中的内容。 / p>
答案 3 :(得分:0)
这使用指向文字字符串的指针。
指针将传递到modifypointer()
,在此处它被修改为指向另一个文字字符串。新的文字字符串将打印在函数中,但是main()
仍会打印原始字符串。
指针在modifypointertopointer()
中作为指向自身的指针传递,在该指针中,该指针被取消引用以指向另一个文字字符串。现在,该函数将打印新的文字字符串,而main()
也将打印新的文字字符串。
在您的最后一个示例中,可以使用first = new_node;
,但该函数声明了影子变量first
并且全局first
不在函数范围内。
#include <stdio.h>
void modifypointer( char *mod) {
mod = "modify pointer";
printf ( "%s\n", mod);
}
void modifypointertopointer( char **ptrmod) {
*ptrmod = "modify pointer to pointer";
printf ( "%s\n", *ptrmod);
}
int main( void) {
char *text = "original";
printf ( "%s\n", text);
modifypointer ( text);
printf ( "%s\n", text);
modifypointertopointer ( &text);
printf ( "%s\n", text);
return 0;
}