C 程序打印我想要的结果,除了在一个地方我得到内存地址而不是地址的值。
基本上,本练习说创建一个函数,该函数将数组及其大小作为参数,并返回一个新数组,其中包含作为参数给出的数组的三个最大值。所以我认为我将获取数组并在函数中对其排序,然后将3个最高值赋给一个新数组并返回它。这是我的密码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
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 )
{
...
}