char数组和char指针之间的冲突点,返回地址

时间:2019-02-16 14:34:20

标签: c arrays function pointers char

我的主要目的是创建某种形式的字符串,它应该返回一个地址,方法是使用main中的字符串返回地址。 但是我实际上是出于相同的目的而学习了char数组和char指针。

如果我们认为自己具有这些能力,

char *arrchar 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;
}

5 个答案:

答案 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的答案中所述完美运行