I am trying to understanding the passing of string to a called function and modifying the elements of the array inside the called function.
我试图理解将字符串传递给被调用的函数并修改被调用函数内的数组元素。
void foo(char p[]){
p[0] = 'a';
printf("%s",p);
}
void main(){
char p[] = "jkahsdkjs";
p[0] = 'a';
printf("%s",p);
foo("fgfgf");
}
Above code returns an exception. I know that string in C is immutable, but would like to know what is there is difference between modifying in main and modifying the calling function. What happens in case of other date types?
上面的代码返回一个异常。我知道C中的字符串是不可变的,但是想知道在main中修改和修改调用函数之间有什么区别。其他日期类型会发生什么?
3 个解决方案
#1
1
I know that string in C is immutable
我知道C中的字符串是不可变的
That's not true. The correct version is: modifying string literals in C are undefined behaviors.
这不是真的。正确的版本是:修改C中的字符串文字是未定义的行为。
In main()
, you defined the string as:
在main()中,您将字符串定义为:
char p[] = "jkahsdkjs";
which is a non-literal character array, so you can modify it. But what you passed to foo
is "fgfgf"
, which is a string literal.
这是一个非文字字符数组,因此您可以修改它。但你传递给foo的是“fgfgf”,这是一个字符串文字。
Change it to:
将其更改为:
char str[] = "fgfgf";
foo(str);
would be fine.
没关系。
#2
0
In the first case:
在第一种情况下:
char p[] = "jkahsdkjs";
p
is an array that is initialized with a copy of the string literal. Since you don't specify the size it will determined by the length of the string literal plus the null terminating character. This is covered in the draft C99 standard section 6.7.8
Initialization paragraph 14:
p是使用字符串文字的副本初始化的数组。由于您未指定大小,因此将根据字符串文字的长度加上空终止字符来确定。这在C99标准第6.7.8节初始化第14段草案中有所涉及:
An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
字符类型数组可以由字符串文字初始化,可选地用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素。
in the second case:
在第二种情况下:
foo("fgfgf");
you are attempting to modify a string literal which is undefined behavior, which means the behavior of program is unpredictable, and an exception is one possibility. From the C99 draft standard section 6.4.5
String literals paragraph 6 (emphasis mine):
您正在尝试修改未定义行为的字符串文字,这意味着程序的行为是不可预测的,并且例外是一种可能性。从C99标准草案第6.4.5节字符串文字第6段(强调我的):
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。如果程序试图修改此类数组,则行为未定义。
#3
0
The difference is in how you are initializing p[].
不同之处在于你如何初始化p []。
char p[] = "jkahsdkjs";
This initializas a writeable array called p, auto-sized to be large enough to contain your string and stored on the stack at runtime.
这初始化为一个名为p的可写数组,自动调整大小足以包含字符串并在运行时存储在堆栈中。
However, in the case of:
但是,在以下情况下:
foo("fgfgf");
You are passing in a pointer to the actual string literal, which are usually enforced as read-only in most compilers.
您正在传递指向实际字符串文字的指针,这些指针通常在大多数编译器中强制为只读。
What happens in case of other date types?
其他日期类型会发生什么?
String literals are a very special case. Other data types, such as int, etc do not have an issue that is analogous to this, since they are stored strictly by value.
字符串文字是一种非常特殊的情况。其他数据类型(如int等)没有类似于此的问题,因为它们严格按值存储。
#1
1
I know that string in C is immutable
我知道C中的字符串是不可变的
That's not true. The correct version is: modifying string literals in C are undefined behaviors.
这不是真的。正确的版本是:修改C中的字符串文字是未定义的行为。
In main()
, you defined the string as:
在main()中,您将字符串定义为:
char p[] = "jkahsdkjs";
which is a non-literal character array, so you can modify it. But what you passed to foo
is "fgfgf"
, which is a string literal.
这是一个非文字字符数组,因此您可以修改它。但你传递给foo的是“fgfgf”,这是一个字符串文字。
Change it to:
将其更改为:
char str[] = "fgfgf";
foo(str);
would be fine.
没关系。
#2
0
In the first case:
在第一种情况下:
char p[] = "jkahsdkjs";
p
is an array that is initialized with a copy of the string literal. Since you don't specify the size it will determined by the length of the string literal plus the null terminating character. This is covered in the draft C99 standard section 6.7.8
Initialization paragraph 14:
p是使用字符串文字的副本初始化的数组。由于您未指定大小,因此将根据字符串文字的长度加上空终止字符来确定。这在C99标准第6.7.8节初始化第14段草案中有所涉及:
An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
字符类型数组可以由字符串文字初始化,可选地用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素。
in the second case:
在第二种情况下:
foo("fgfgf");
you are attempting to modify a string literal which is undefined behavior, which means the behavior of program is unpredictable, and an exception is one possibility. From the C99 draft standard section 6.4.5
String literals paragraph 6 (emphasis mine):
您正在尝试修改未定义行为的字符串文字,这意味着程序的行为是不可预测的,并且例外是一种可能性。从C99标准草案第6.4.5节字符串文字第6段(强调我的):
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。如果程序试图修改此类数组,则行为未定义。
#3
0
The difference is in how you are initializing p[].
不同之处在于你如何初始化p []。
char p[] = "jkahsdkjs";
This initializas a writeable array called p, auto-sized to be large enough to contain your string and stored on the stack at runtime.
这初始化为一个名为p的可写数组,自动调整大小足以包含字符串并在运行时存储在堆栈中。
However, in the case of:
但是,在以下情况下:
foo("fgfgf");
You are passing in a pointer to the actual string literal, which are usually enforced as read-only in most compilers.
您正在传递指向实际字符串文字的指针,这些指针通常在大多数编译器中强制为只读。
What happens in case of other date types?
其他日期类型会发生什么?
String literals are a very special case. Other data types, such as int, etc do not have an issue that is analogous to this, since they are stored strictly by value.
字符串文字是一种非常特殊的情况。其他数据类型(如int等)没有类似于此的问题,因为它们严格按值存储。