猿问
下载APP

C中的指针:何时使用&符号和星号?

C中的指针:何时使用&符号和星号?

我刚开始用指针,我有点困惑。我知道&一个变量的地址,它*可以在指针变量前面使用,以获取指针指向的对象的值。但是当您使用数组,字符串或使用变量的指针副本调用函数时,情况会有所不同。在所有这些内部很难看到逻辑模式。

什么时候应该使用&*


慕丝7291255
浏览 54回答 3
3回答

湖上湖

你有指针和价值观:int* p; // variable p is pointer to integer typeint i; // integer value您将指针转换为值*:int i2 = *p; // integer i2 is assigned with integer value that pointer p is pointing to您将值转换为指针&:int* p2 = &i; // pointer p2 will point to the address of integer i编辑:在数组的情况下,它们被视为非常类似于指针。如果您将它们视为指针,您将使用它*来获取它们内部的值,如上所述,但是使用[]运算符还有另一种更常见的方法:int a[2];  // array of integersint i = *a; // the value of the first element of aint i2 = a[0]; // another way to get the first element要获得第二个元素:int a[2]; // arrayint i = *(a + 1); // the value of the second elementint i2 = a[1]; // the value of the second element所以[]索引操作符是运算符的一种特殊形式*,它的工作原理如下:a[i] == *(a + i);  // these two statements are the same thing

拉莫斯之舞

处理数组和函数时有一种模式;&nbsp;起初有点难以看到。在处理数组时,记住以下内容是有用的:当数组表达式出现在大多数上下文中时,表达式的类型被隐式地从“N元素数组T”转换为“指向T”,并且其值被设置指向数组中的第一个元素。此规则的例外情况是,数组表达式显示为&或sizeof运算符的操作数,或者它是在声明中用作初始值设定项的字符串文字。因此,当您使用数组表达式作为参数调用函数时,该函数将接收指针,而不是数组:int&nbsp;arr[10];...foo(arr);...void&nbsp;foo(int&nbsp;*arr)&nbsp;{&nbsp;...&nbsp;}这就是为什么你不使用&运算符作为对应于“%s”的参数scanf():char&nbsp;str[STRING_LENGTH];...scanf("%s",&nbsp;str);由于隐式转换,scanf()接收char *指向str数组开头的值。这适用于使用数组表达式作为参数调用的任何函数(几乎任何str*函数*scanf和*printf函数等)。在实践中,您可能永远不会使用&运算符调用带有数组表达式的函数,如:int&nbsp;arr[N];...foo(&arr);void&nbsp;foo(int&nbsp;(*p)[N])&nbsp;{...}这样的代码并不常见;&nbsp;您必须知道函数声明中数组的大小,并且该函数仅适用于指向特定大小的数组的指针(指向T的10元素数组的指针与指向11元素数组的指针的类型不同T)。当数组表达式作为操作&符的操作数出现时,结果表达式的类型是“指向T的N元素数组的指针”,或者T (*)[N],它与指针数组(T *[N])和指向基类型的指针不同(T *)。在处理函数和指针时,要记住的规则是:如果要更改参数的值并将其反映在调用代码中,则必须将指针传递给要修改的事物。同样,数组会投入一些动作,但我们会首先处理正常情况。请记住,C&nbsp;按值传递所有函数参数;&nbsp;形式参数接收实际参数中值的副本,并且形式参数的任何更改都不会反映在实际参数中。常见的例子是交换功能:void&nbsp;swap(int&nbsp;x,&nbsp;int&nbsp;y)&nbsp;{&nbsp;int&nbsp;tmp&nbsp;=&nbsp;x;&nbsp;x&nbsp;=&nbsp;y;&nbsp;y&nbsp;=&nbsp;tmp;&nbsp;}...int&nbsp;a&nbsp;=&nbsp;1,&nbsp;b&nbsp;=&nbsp;2;printf("before&nbsp;swap:&nbsp;a&nbsp;=&nbsp;%d,&nbsp;b&nbsp;=&nbsp;%d\n",&nbsp;a,&nbsp;b);swap(a,&nbsp;b);printf("after&nbsp;swap:&nbsp;a&nbsp;=&nbsp;%d,&nbsp;b&nbsp;=&nbsp;%d\n",&nbsp;a,&nbsp;b);您将获得以下输出:在交换之前:a&nbsp;=&nbsp;1,b&nbsp;=&nbsp;2交换后:a&nbsp;=&nbsp;1,b&nbsp;=&nbsp;2形式参数x和y从不同的对象a和b,所以要改变x和y未在反射a和b。因为我们要修改的值a和b,我们必须通过指针,以他们的交换功能:void&nbsp;swap(int&nbsp;*x,&nbsp;int&nbsp;*y)&nbsp;{int&nbsp;tmp&nbsp;=&nbsp;*x;&nbsp;*x&nbsp;=&nbsp;*y;&nbsp;*y&nbsp;=&nbsp;tmp;&nbsp;}...int&nbsp;a&nbsp;=&nbsp;1,&nbsp;b&nbsp;=&nbsp;2;printf("before&nbsp;swap:&nbsp;a&nbsp;=&nbsp;%d,&nbsp;b&nbsp;=&nbsp;%d\n",&nbsp;a,&nbsp;b);swap(&a,&nbsp;&b);printf("after&nbsp;swap:&nbsp;a&nbsp;=&nbsp;%d,&nbsp;b&nbsp;=&nbsp;%d\n",&nbsp;a,&nbsp;b);现在您的输出将是在交换之前:a&nbsp;=&nbsp;1,b&nbsp;=&nbsp;2交换后:a&nbsp;=&nbsp;2,b&nbsp;=&nbsp;1请注意,在交换函数中,我们不会更改xand&nbsp;y的值,而是更改what&nbsp;x和y&nbsp;指向的值。写作*x不同于写作x;&nbsp;我们没有更新价值x本身,我们从该位置获取位置x并更新该位置的值。如果我们想要修改指针值,这同样适用;&nbsp;如果我们写int&nbsp;myFopen(FILE&nbsp;*stream)&nbsp;{stream&nbsp;=&nbsp;fopen("myfile.dat",&nbsp;"r");&nbsp;}...FILE&nbsp;*in;myFopen(in);然后我们修改输入参数的值stream,而不是stream&nbsp;指向stream的值,因此更改对值的影响没有影响in;&nbsp;为了使其工作,我们必须传入一个指针指针:int&nbsp;myFopen(FILE&nbsp;**stream)&nbsp;{*stream&nbsp;=&nbsp;fopen("myFile.dat",&nbsp;"r");&nbsp;}...FILE&nbsp;*in;myFopen(&in);再次,阵列投入了一些猴子扳手。将数组表达式传递给函数时,函数接收的是指针。由于如何定义数组下标,您可以在指针上使用下标运算符,就像在数组上使用它一样:int&nbsp;arr[N];init(arr,&nbsp;N);...void&nbsp;init(int&nbsp;*arr,&nbsp;int&nbsp;N)&nbsp;{size_t&nbsp;i;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;N;&nbsp;i++)&nbsp;arr[i]&nbsp;=&nbsp;i*i;}请注意,可能未分配数组对象;&nbsp;即,你不能做类似的事情int&nbsp;a[10],&nbsp;b[10];...a&nbsp;=&nbsp;b;所以当你处理指向数组的指针时要小心;&nbsp;就像是void&nbsp;(int&nbsp;(*foo)[N]){ &nbsp;&nbsp;... &nbsp;&nbsp;*foo&nbsp;=&nbsp;...;}不行。

四季花海

我正在翻阅所有罗嗦的解释,所以转向新南威尔士大学的视频进行救援。这里有一个简单的解释:如果我们有一个具有地址x和价值的单元格7,那么询问价值地址的间接方式7是&7和间接的方式,要求在地址值x是*x。所以(cell: x , value: 7) == (cell: &7 , value: *x)。另一个方式来调查一下:John在坐7th seat.The&nbsp;*7th seat将指向John并&John会给address/位置7th seat。这个简单的解释对我有所帮助,并希望它也能帮助其他人。以下是优秀视频的链接:点击此处。这是另一个例子:#include&nbsp;<stdio.h>int&nbsp;main(){&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;x;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;A&nbsp;normal&nbsp;integer*/ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;*p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;A&nbsp;pointer&nbsp;to&nbsp;an&nbsp;integer&nbsp;("*p"&nbsp;is&nbsp;an&nbsp;integer,&nbsp;so&nbsp;p &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;must&nbsp;be&nbsp;a&nbsp;pointer&nbsp;to&nbsp;an&nbsp;integer)&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;&x;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Read&nbsp;it,&nbsp;"assign&nbsp;the&nbsp;address&nbsp;of&nbsp;x&nbsp;to&nbsp;p"&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;scanf(&nbsp;"%d",&nbsp;&x&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Put&nbsp;a&nbsp;value&nbsp;in&nbsp;x,&nbsp;we&nbsp;could&nbsp;also&nbsp;use&nbsp;p&nbsp;here&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;printf(&nbsp;"%d\n",&nbsp;*p&nbsp;);&nbsp;/*&nbsp;Note&nbsp;the&nbsp;use&nbsp;of&nbsp;the&nbsp;*&nbsp;to&nbsp;get&nbsp;the&nbsp;value&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;getchar();}附加组件:&nbsp;在使用之前始终初始化指针。如果没有,指针将指向任何东西,这可能导致程序崩溃,因为操作系统将阻止您访问它知道您不拥有的内存。但是简单地放&nbsp;p = &x;,我们正在为指针指定一个特定的位置。
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答