Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 程序打印我想要的结果,除了在一个地方我得到内存地址而不是地址的值。_C_Arrays_Sorting_Pointers - Fatal编程技术网

C 程序打印我想要的结果,除了在一个地方我得到内存地址而不是地址的值。

C 程序打印我想要的结果,除了在一个地方我得到内存地址而不是地址的值。,c,arrays,sorting,pointers,C,Arrays,Sorting,Pointers,基本上,本练习说创建一个函数,该函数将数组及其大小作为参数,并返回一个新数组,其中包含作为参数给出的数组的三个最大值。所以我认为我将获取数组并在函数中对其排序,然后将3个最高值赋给一个新数组并返回它。这是我的密码 int *function(int *A, int k){ int B[3],i,j,temp; //Sorting for(i=k-1;i>0;i--){ for(j=1;j<=i;j++){ if(A[j

基本上,本练习说创建一个函数,该函数将数组及其大小作为参数,并返回一个新数组,其中包含作为参数给出的数组的三个最大值。所以我认为我将获取数组并在函数中对其排序,然后将3个最高值赋给一个新数组并返回它。这是我的密码

int *function(int *A, int k){
    int B[3],i,j,temp;

    //Sorting
    for(i=k-1;i>0;i--){
        for(j=1;j<=i;j++){
            if(A[j-1] > A[j])
            {
                temp = A[j-1];
                A[j-1] = A[j];
                A[j] = temp;
            }
        }
    }
    i = 0;
    while(i < 3){
        B[i]= A[k-1];
        i++;
        k--;
    }
    return B;   
} 

int main (int argc, const char * argv[]) {
   int A[5] = {1,8,7,4,6};
    int size = 5;
    int *func,i;

    func = function(A,size);
    for(i=0;i<3;i++)
        printf("%d ",func[i]); 
    return 0;
}

因此,我应该得到876,但我得到了8-1073743756。我找不到错误。当我想返回B时,我也会得到一个警告。它表示函数返回局部变量的地址。也许这和这个问题有关。有什么想法吗?

函数返回后,int B[3]等自动存储对象将被销毁,因此引用它们是非法的。实际上,由于写入堆栈的各种内容,您将获得意外的值:

你可以:

给B静态存储 使用malloc和更高版本免费 使用完全不同的方法,例如让调用者负责传递B
B是一个局部变量,当函数退出时它会消失

在函数外部声明B,并通过指针将其传递给函数。

B[]数组仅在函数运行时有效,它是本地的。返回后,将取消引用它

如果你的任务文本被精确引用,那么你似乎必须深入研究malloc。现在我要说:

不要施放malloc 完成后免费 使用malloc的原因如下:

返回一个新数组

只接受数组和计数器,不接受第三个参数或重复使用

并且不要受到使用全局数组的诱惑;,你可能被允许使用静态的吗-编辑:@Clifford对为什么不这么做有很好的看法

祝你好运

编辑: 另外:您不会获得内存地址而不是值

调用该函数时,会给它一个返回位置的地址。其次,在该函数中,局部变量的内存是保留的,它们的名称是给定地址的。例如:

/* assuming 4 byte int */
[ 0xA4 ... 0xAF ] <-- int B[3]  -- 3 * 4 = 12 bytes
[ 0xB0 ... 0xB4 ] <-- int i     -- 4 bytes
[ 0xB5 ... 0xB9 ] <-- int j     -- 4 bytes
[ 0xBA ... 0xBE ] <-- int temp  -- 4 bytes
返回main,fun[2]->[0xC 0xD 0xE 0xF]

在其他地方,一个函数定义一个char 1字节并获取现在的空闲地址0xD 它将值123写入该地址

现在我们有:

fun[2]:

Address: 0xAC 0xAD 0xAE 0xAF       As bit sequence
Value  :    6  123    0    0  ==> [0000 0110 0111 1011 0000 0000]
或者如果我们在一个小的endian系统上,比如我的系统,把它转换成一个整数,我们就得到了

          +--------- Least significant byte
          |
Address: 0xAC 0xAD 0xAE 0xAF
Value  :    6  123    0    0  ( == 0x06 0x7B 0x00 0x00 )

Sort to "human Anglo left right order"
0 0 123 6 => 0x00007B06 == 31494 (int, "normal human number"), and the number
                                       you print when doing the for() loop in 
                                       main.
也可能是所讨论的字节被用作

                   +----- bytes of fun[2]
                   |
          _________+_________
         [                   ]
char foo 0xAC                |
int  bar       0xAD 0xAE 0xAF  0xB0
               [____+______________]
                    |
                    +---- bytes of bar
数字1和2是正确的这一事实既不能保证字节没有被更改。可以将相同的值写入该位置。0可能已写入int等的字节2

胡佛将展示:

*作为半注释,只是为了进一步混淆,它可能是一个地址,但可能是该地址的整数表示。事实上,这并不是不可能的。。。它可能是某个操作的返回地址,您将其解释为int*


希望你至少能从中得到1%。我自己也在积极学习,解释也经常学习:

变量B的“生存期”是在声明它的函数的持续时间内。当它超出范围时,它就不再存在,并且它的内存可以被重新用于其他目的。您应该将所有编译器警告视为错误-它们通常是语义错误,而不是语法错误;也就是说,编译器理解代码,但它不太可能是您想要的,或者可能具有非预期或未定义的行为

在这种情况下,编译器会准确地告诉您问题所在。您需要问的也许是如何最好地解决错误

当调用者要求函数填充数组时,通常使用的模式是调用者向函数提供数组。因为数组在传递给函数时会“衰减”到指针,所以传递长度也是正常的,这有助于避免缓冲区溢出。您可以让函数知道,在您的情况下,缓冲区长度始终为3,但它的可维护性和安全性较差

通常,这样的函数返回一个指向调用方缓冲区的指针,或者在失败时返回NULL,因此它可以用于错误检查或用作另一个函数的参数

例如:

int* fn( int* caller_buffer, int caller_buffer_length )
{
    int i ;
    for( i = 0; i < caller_buffer_length; i++ )
    {
        caller_buffer[i] = ... ;
    }
}
可以通过静态、全局或动态分配B来解决问题。所有这些解决方案我都认为既快又脏。它们可以解决这个特定的问题,但不是一种可以很好地扩展到更复杂和更大应用程序的通用模式

函数中的本地动态内存分配回避了这样一个问题:谁负责释放分配的内存

本地静态分配可以工作,但是如果您再次调用该函数,以前的数据将丢失,这可能并不总是可以接受的。它也是不可重入的,这会在多线程应用程序或递归算法中造成潜在问题

全局数据是静态分配的,但作为
e另外一个问题是全局可见,因此不再由一个函数单独控制。

因此我做了一些更改。我做了int*B,然后B=int*malloc3*sizeofint,程序运行了,警告也不再存在了。但是写B[3]和用malloc写数组B有什么区别呢?当我们从一开始就不知道数组的大小时,我们不是使用malloc吗?在这个例子中,我从一开始就知道数组B的大小为3。这些建议不符合可取的顺序;我会把清单颠倒过来。
int* fn( int* caller_buffer, int caller_buffer_length )
{
    int i ;
    for( i = 0; i < caller_buffer_length; i++ )
    {
        caller_buffer[i] = ... ;
    }
}
int my_buffer[3] = {0} ;
int my_buffer_length = sizeof(my_buffer) / sizeof(*my_buffer) ;
int* error_check = 0 ;

...

error_check = fn( my_buffer, my_buffer_length ) ;
if( error_check != 0 )
{
    ...
}