我的主要目的是创建某种形式的字符串,它应该返回一个地址,方法是使用main中的字符串返回地址。 但是我实际上是出于相同的目的而学习了char数组和char指针。
如果我们认为自己具有这些能力,
char *arr
和char arr[10]
,*(arr+9)=arr[10]
是吗?
代码“ 1”不起作用。
代码“ 2”有效。
为什么?
代码“ 1”:
#include <stdio.h>
char *foo(char arr[]);
int main(){
char example[10];
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char arr[])
{
arr[10]="attempt";
return arr;
}
代码“ 2”:
#include <stdio.h>
char *foo(char*);
int main()
{
char *example;
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char* arr)
{
arr="attempt";
return arr;
}
答案 0 :(得分:2)
您的代码将在两个段中调用 undefined behavior 。 (即使您已经观察到 2
代码有效,但它似乎只有 起作用。实际上, failure is lurking ,并且可以显示而不会发出警告。)
进行这些更正以解决该问题,并查看注释以获取解释:
在 代码1 中:
//int main(void){
int main(void){//int main(void) is minimum prototype for main function.
//char example[10]; // this will invoke undefined behavior
char example[10] = {"something"}; // 'example' initialized with content,
// thus averting undefined behavior
//example=foo(example);
strcpy (example, foo(example)); // char array is not assignable using `=`
// use strcpy to transfer result of "foo"
printf("%s\n",example);
return 0;
}
char *foo(char arr[]) //note: char arr[] decays into char *arr
{
//char arr[10]="attempt"; // Error: redefinition of 'arr' with a
// different type: char[10] vs char *
arr = "attempt"; //because char [] decays into char *, 'arr' is usable as is.
return arr;
}
要在评论中回答您的问题:为什么使用strcpy函数 [变量后 示例 初始化] 不是未定义的行为。
首先,了解C字符串的定义很重要。 ( C string definition is found here 。)
原始形式的变量example
,即已初始化:
char example[10];
可以包含任何内容。例如:
|%|h|8|\#|d|o|-|~|*|U|?|?|?|?|
// ^end of memory for 'example`
// note that the character in example[9] == 'U', not NULL, therefore, not a C string.
这将导致功能strcpy()
失败。初始化保证可预期的结果:
char example[10] = {"something"};//properly initialized
|s|o|m|e|t|h|i|n|g|0|?|?|?|?|
// ^end of memory for 'example`
//or
char example[10] = {0}; //also properly initialized
|0|0|0|0|0|0|0|0|0|0|?|?|?|?|
// ^end of memory for 'example`
(This would require an extra step to place proper content.):
strcpy(example, "something");
对 代码2 的唯一必需的调整是在使用之前初始化指针:(请参阅必须初始化 here 。)
char *foo(char*);
//int main(void){
int main(void){//int main(void) is minimum prototype for main function.
{
//char *example; // passing this will envoke undefined behavior
char *example = NULL;// must initialize before using
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char* arr)
{
arr="attempt";
return arr;
}
答案 1 :(得分:1)
由于不同的原因,两者都不“起作用”。
第一个是未定义行为(UB),因为代码尝试分配example[10]
范围之外的元素。
arr[0]='\0';
的值, arr[9]='\0';
或foo()
就可以了。
将字符串文字 "attempt"
的地址转换为char
也不是很好的代码。启用良好的编译器将警告此基本编码失效。 @f3rmat example
char *foo(char arr[]) {
arr[10]="attempt"; <-- UB
return arr;
}
char example[10];
example=foo(example);
第二个是UB,因为代码试图在传递指针时使用未初始化的值。这种“有效”之处在于,传递未初始化指针的UB通常是良性的。由于foo()
不使用此“垃圾”值,并且剩余的物品都得到了很好的定义,因此它“有效”。
char *foo(char* arr) {
arr="attempt";
return arr;
}
char *example;
example=foo(example); // UB - likely a garbage value is passed to `foo()`.
printf("%s\n",example); // `example` is now pointing to `"attempt"`.
我实际上是出于相同的目的而学习了char数组和char指针。
指针和数组相关,但有所不同。避免“实际上使用相同目的”的想法。
阵列就像一条街道上的一排房屋。指针 是写在手中的房子的地址。房屋≠废纸。您可以通过地址来引用房子,甚至可以通过第一所房子的地址来引用一排房子,但是房子和它的地址是不同的。
答案 2 :(得分:0)
我尝试编译代码'1'并收到以下错误:
prog.c: In function ‘main’:
prog.c:8:12: error: assignment to expression with array type
example=foo(example);
prog.c: In function ‘foo’:
prog.c:14:12: warning: assignment makes integer from pointer without a cast [-
Wint-conversion]
arr[10]="attempt\n";
^
您得到error: assignment to expression with array type example=foo(example);
的原因是,在您的左侧,您使用的是不可分配的数组类型。赋值运算符(=)的左操作数必须具有可修改的左值。
您得到一个warning: assignment makes integer from pointer without a cast [Wint-conversion] arr[10]="attempt\n";
,因为此作业的左侧和右侧具有不同的类型。
答案 3 :(得分:0)
指针和数组不相同。
char *arr = "attempt"
这里您要创建一个字符串常量"attempt"
并将其地址分配给有效的arr
char arr[10];
arr = "attempt";
这无效。
您可以通过以下方法将元素添加到数组中。
char arr[10] = "attempt";
char arr[10] = {'a', 't', 't', 'e', 'm', 'p', 't'};
arr[0] = 'a';
arr[1] = 't'; // and so on.
当您将数组作为参数传递给另一个函数时
arr = foo(arr);
您正在传递数组arr[0]
中的第零个元素的地址
希望有帮助。
答案 4 :(得分:0)
Char数组可以初始化,但不能分配。
char example[10]="attempt";
有效。
但是
char example[10];
example="attempt"
无效。
更多详细信息here
您的第二个示例有效,因为您将未初始化的指针传递给函数并返回字符串文字attempt
的地址
可以按照chux的答案中所述完美运行