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