C基础-变量和指针有问题
我在学习C时遇到了一些问题,我真的没有其他地方可以寻求建议。我来自一系列OOP语言,比如JavaScript,主要是Python,所以C是一个重大的变化,我在学习基础知识时遇到了不少困难。我最初是从Zed Shaw的“用艰苦的方式学习C”开始的,但他并没有在书中教授任何东西。是的,他让你写了很多代码,修改了很多东西,但我不知道为什么代码会工作,这只是导致了更多的混乱,因为这些例子越来越复杂 我遇到的主要问题是变量和指针之间的差异(我认为这是非常明显的,直到我在下面发布了一些示例,它们完全模糊了两者之间的界限) 例如,我知道声明和初始化名为C基础-变量和指针有问题,c,pointers,C,Pointers,我在学习C时遇到了一些问题,我真的没有其他地方可以寻求建议。我来自一系列OOP语言,比如JavaScript,主要是Python,所以C是一个重大的变化,我在学习基础知识时遇到了不少困难。我最初是从Zed Shaw的“用艰苦的方式学习C”开始的,但他并没有在书中教授任何东西。是的,他让你写了很多代码,修改了很多东西,但我不知道为什么代码会工作,这只是导致了更多的混乱,因为这些例子越来越复杂 我遇到的主要问题是变量和指针之间的差异(我认为这是非常明显的,直到我在下面发布了一些示例,它们完全模糊了两
a
的int
和指针p
如下所示:
int a;
int *p;
a = 12;
p = &a;
// NOTE: not actual scanf implementation
void scanf(char* format, int * input) {
*input = get_number(); // store value in variable
}
让我困惑的是,当您声明的变量看起来像指针,但实际上根本不是指针(或者是指针?)。例如:
char *string = "This is a string";
printf("%s\n", string);
char *string = “This is a string”;
printf(“%s\n”, string);
定义和初始化字符串时,它是什么?是指针吗?如果是,为什么不在printf
函数中打印时取消引用它呢?有很多这样的例子让我困惑
我遇到的另一个毫无意义的例子:
int i;
scanf("%d", &i);
当符号应该引用变量在内存中的位置而不是值时,该函数如何更新整数i
?数组和结构变得更加复杂,这就是我停下来决定需要寻求一些建议的地方
我真的觉得很尴尬发布这样一个noob问题,但每个人都从某个地方开始。我知道,在继续之前,我需要理解这些基本原理,但当我看到与我刚才所学内容相矛盾的代码示例时,我很难理解这些基本原理。我知道这是一个非常普遍的问题,但我希望你们中的一些人能够解释这些基本知识,或者为我指出一个我可以更好地学习/理解这一点的方向。我遇到的大多数视频教程都过于笼统,与在线文本教程相同,它们告诉你如何做某事,但没有解释,这会导致一些严重的问题 定义和初始化字符串时,字符串是什么?是指针吗?如果是,为什么不在printf函数中打印时取消引用它呢 这是一个指针。它直接指向字符串中的第一个字符。您不必取消引用它,因为
printf
将接受char
指针。。并打印所有内容,直到找到空终止符(自动为您添加)
当符号应该引用变量在内存中的位置而不是值时,该函数如何更新整数i的值
因为&i
使参数作为int*
传入。因此,函数将取消引用并添加。。有点像这样:
int a;
int *p;
a = 12;
p = &a;
// NOTE: not actual scanf implementation
void scanf(char* format, int * input) {
*input = get_number(); // store value in variable
}
读一些关于指针的基础知识怎么样 我将回答你的以下问题: 让我困惑的是,当您声明的变量看起来像指针,但实际上根本不是指针(或者是指针?)。例如:
char *string = "This is a string";
printf("%s\n", string);
char *string = “This is a string”;
printf(“%s\n”, string);
是的,他们是!它是一个字符指针
当符号应该引用变量在内存中的位置而不是值时,该函数如何更新整数i
这取决于函数签名。如果你看看
scanf
接受什么作为参数列表,你就会明白。我会回答你的具体问题,关于printf
为什么没有传递一个去引用指针,以及scanf
为什么传递一个地址,希望这能让一些事情更清楚
首先,按照惯例,C样式字符串是内存中的字符数组,由
\0
字符(称为NUL终止符)终止。跟踪C样式字符串的方法是保持指向字符串第一个字符的指针
当调用printf(“%s\n”,some_str)
时,其中some_str
类型为char*
,则printf
所做的是打印some_str
指向的字符,然后打印它后面的字符(在内存中,通过简单地增加指针some_str
定位),然后打印后面的字符,直到找到\0
,然后停止打印
其他C风格的字符串操作函数也使用相同的过程,如strcpy
,strlen
等
这样做的一个原因是字符串往往具有不同的长度,因此需要不同的内存量,但不方便使用大小可变的数据类型。因此,我们对内存中字符串的格式有一个约定(本质上是\0
终止符约定),我们只需用字符*
指向字符串
如果您取消引用一个字符*
,您将得到一个字符,而不是预期的字符串,因此请注意这一点
为什么
scanf(“%d”和&i)
将地址传递给int
,而不是int
本身
原因是在C语言中,函数参数是按值传递的,这意味着当你把某个东西传递给函数时,它的一个副本会被复制并传递给函数,而不管函数对副本做了什么,原始的都会保持原样。这意味着什么
首先,如果你有一个函数,比如:
void add_two(int i) {
i = i + 2;
}
void really_add_two(int *i) {
*i = *i + 2;
}
如果调用:inti=3;加二(i)
,则i
的值不会更改,因为添加两个int i;
scanf("%d", &i);
int i, j;
scanf("%d%d", &i, &j);
int a;
+-----+
| int |
+-----+
+-----+
&a -> | int |
+-----+
int *p;
+---------+
p -> | int |
+---------+
p = &a;
int i;
scanf( "%d", &i );
int foo(int n) { return 11; }
int j = 10;
int i = foo(j);
int foo(int *p) { *p = 12; return 11; }
int j = 10;
int i = foo(&j);
char *string = "This is a string";
printf("%s\n", string);
int i;
scanf("%d", &i);
void swap( int a, int b ) { int tmp = a; a = b; b = tmp; return; }
...
int x = 0, y = 1;
printf( "before swap: x = %d, y = %d\n", x, y );
swap( x, y );
printf( " after swap: x = %d, y = %d\n", x, y );
void swap( int *a, int *b ) { int tmp = *a; *a = *b; *b = tmp; return; }
...
int x = 0, y = 1;
printf( "before swap: x = %d, y = %d\n", x, y );
swap( &x, &y );
printf( " after swap: x = %d, y = %d\n", x, y );