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

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

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

什么时候应该使用&*


慕丝7291255
浏览 715回答 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;...;}不行。
打开App,查看更多内容
随时随地看视频慕课网APP