提问人:th3 wolf 提问时间:11/4/2023 最后编辑:Vlad from Moscowth3 wolf 更新时间:11/5/2023 访问量:123
由 value 传递的结构在 c 中的函数中被修改
Struct passed by value is modified in function in c
问:
我有这个代码,我需要在不修改它的情况下对结构数组进行排序。我按值传递了结构数组,并使用带有索引的 int 数组对结构进行排序。要对数组进行排序,我还需要对结构进行排序,该结构在函数中按值传递,如果我没记错的话,如果您在函数中修改按值传递的值,它在 main 中仍然相同,但在 main 中它会发生变化,当我尝试使用排序后的索引数组打印结构数组时,它不会打印它排序,因为结构数组是sorted(正如我之前所说,要对索引进行排序,我需要修改结构体的数组)。
我希望如果我将结构数组作为值传递,则不会被修改。
这是函数,之后将是我使用该函数的代码块。
void Opartenza(struct Corse c[], int d, int **O)
{
int temp = 0;
O[0] = (int *)malloc(d * sizeof(int));
for(int i = 0; i < d; i++)
O[0][i] = i;
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d - 1; j++)
{
if(strcmp(c[j].partenza, c[j + 1].partenza) > 0)
{
temp = O[0][j];
O[0][j] = O[0][j + 1];
O[0][j + 1] = temp;
c[d] = c[j];
c[j] = c[j + 1];
c[j + 1] = c[d];
}
}
}
}
case r_o_partenza:
Opartenza(corse, dim, &Ordinamento);
for(int i = 0; i < dim; i++)
printf("%s\n", corse[i].partenza);
break;
如您所见,我尝试打印结构数组,并将其排序为索引数组。
答:
在 C 语言中,数组总是通过引用传递,无论如何,因为在内部索引数组会编译为指针算术。这意味着,传递带有数组表示法的数组或指向数组的指针,实际上归结为同一件事。如果你真的希望你的数组不被修改,请先复制它。
评论
在 C 语言中,通过引用传递意味着通过指向对象的指针间接传递对象。因此,取消引用传递的指针,您可以直接访问指针指向的对象。 这是一个演示程序
#include <stdio.h>
enum { N = 10 };
void f( int ( *pa )[N] )
{
printf( "The size of the passed array is %zu\n", sizeof( *pa ) );
}
int main( void )
{
int a[N];
f( &a );
}
程序输出可能如下所示
The size of the passed array is 40
在 C 中,数组是不可修改的左值。因此,即使您将通过引用传递数组,也无法更改它。您只能更改其元素。也就是说,没有为数组定义赋值运算符。
例如,你不能写
char a[1] = { 'a' };
char b[1] = { 'b' };
a = b;
从 C 标准 (6.3.2.1 左值、数组和函数指示符
1 左值是一个表达式(对象类型不是 void) 可能指定一个对象;65) 如果左值没有 指定一个对象 在计算时,行为是未定义的。 当一个对象被说成具有特定类型时,该类型是 由用于指定对象的 lValue 指定。可修改的 lvalue 是一个没有数组类型的 lvalue,没有 不完整类型,没有 const 限定类型,如果它是 结构或联合,没有任何成员(包括递归地, 所有包含的集合体或联合体的任何成员或元素),并带有 常量限定类型。
另一方面,如果数组不是常量限定的,则可以更改数组的元素。
表达式中使用的数组指示符(极少数例外)被隐式转换为指向其第一个元素的指针。
从 C 标准 (6.3.2.1 左值、数组和函数指示符
3 除非它是 sizeof 运算符的操作数,或一元 & 运算符,或者是用于初始化数组的字符串文字,一个 类型为“array of type”的表达式将转换为表达式 类型为“pointer to type”,指向 数组对象,并且不是左值。如果数组对象有寄存器 存储类,则行为未定义。
因此,当您按值传递数组,然后用作参数表达式时,它会隐式转换为指向其第一个元素的指针。
此外,具有数组类型的函数参数也由编译器调整为指向数组元素类型的指针。
例如,这些函数声明
void f( int a[100] );
void f( int a[10] );
void f( int a[1] );
void f( int a[] );
void f( int *a );
是等价的,并声明相同的一个函数。
因此,如果您将按值传递一个数组,那么它将被隐式转换为指向其第一个元素的指针,并且使用指向传递数组的第一个元素的指针和指针算术,您可以更改传递数组的任何元素。
评论
c
struct Corse c[]
struct Corse *c
c
struct Corse
c
d
O