1. 程式人生 > >函式指標作為引數

函式指標作為引數

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
void func(int *p)
{
    p = (int *)malloc(sizeof(int) * 10);
    memset(p, 0, sizeof(p));
    p[0] = 1;
}
int main()
{
    int *p = NULL;
    func(p);
    cout << p[0] << endl;
    return 0;
}

一個很簡單的函式,就是給*p

在函式中分配空間並將p[0]置成1,最後列印輸出p[0]。但是執行的結果卻是segmengt fault

我們通過檢視這段程式的彙編程式碼來分析一下出現段錯誤的原因。

Dump of assembler code for function func(int*):
   0x00000000004008cd <+0>:     push   %rbp
   0x00000000004008ce <+1>:     mov    %rsp,%rbp
   0x00000000004008d1 <+4>:     sub    $0x20,%rsp
   0x00000000004008d5 <+8>:     mov    %rdi,-0x18(%rbp)
   0x00000000004008d9 <+12>:    mov    $0x28,%eax
   0x00000000004008de <+17>:    mov    %rax,%rdi
   0x00000000004008e1 <+20>:    callq  0x400780 <
[email protected]
> 0x00000000004008e6 <+25>: mov %rax,-0x8(%rbp) 0x00000000004008ea <+29>: mov -0x8(%rbp),%rax 0x00000000004008ee <+33>: mov $0x8,%edx 0x00000000004008f3 <+38>: mov $0x0,%esi 0x00000000004008f8 <+43>: mov %rax,%rdi 0x00000000004008fb <+46>: callq 0x400750 <[email protected]
> 0x0000000000400900 <+51>: mov -0x8(%rbp),%rax 0x0000000000400904 <+55>: movl $0x1,(%rax) 0x000000000040090a <+61>: leaveq 0x000000000040090b <+62>: retq End of assembler dump.

重點放在

    sub $0x20,%rbp
    mov %rdi,-0x18(%rbp)

這兩句彙編程式碼上。

sub $0x20,%rbp的意思是給棧分配0x20大小的空間。

mov %rdi,-0x18(%rbp)的意思是把函式的第一個引數的值壓入棧中儲存。 
這說明了什麼?說明了函式中的*p其實是一個臨時變數,和主函式並不是同一個*p了。給臨時變數申請記憶體並賦值當前不能反映到主函式的*p上,所以主函式的*p還是個空指標,而列印空指標當然就段錯誤了。

下面介紹兩種解決方法: 
1.函式返回臨時指標的地址

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
int* func(int *p)
{
    //此時的p是個臨時指標
    p = (int *)malloc(sizeof(int) * 10);
    memset(p, 0, sizeof(p));
    p[0] = 1;
    return p;  //返回地址
}
int main()
{
    int *p = NULL;
    p = func(p);
    cout << p[0] << endl;
    return 0;
}

2.傳入指向指標的指標

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
//*p儲存的是main函式*ptr的地址
void func(int **p)
{
    *p = (int *)malloc(sizeof(int) * 10);
    memset(*p, 0, sizeof(*p));
    *p[0] = 1;
}
int main()
{
    int *ptr = NULL;
    func(&ptr);
    cout << ptr[0] << endl;
    return 0;
}

相關推薦

C語言之最好理解的通過函式指標作為引數實現回撥函式

1、函式指標回撥解釋 回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式 2、程式碼實現 #i

函式指標作為引數

#include <iostream> using namespace std; #include <stdlib.h> #include <string.h> void func(int *p) { p = (int *)mall

函式指標作為某個函式引數及定義函式指標(回撥函式

轉載於:http://blog.csdn.net/vlily/article/details/7244682 轉載於:http://blog.csdn.net/shengnan_wu/article/details/8116935 轉載於:http://blog.csdn

函式指標作為某個函式引數

   函式指標變數是一個變數,可以作為某個函式的引數來使用的。     一個例項: 設計一個 CallMyFun 函式,這個函式可以通過引數中的函式指標值不同來分別呼叫 MyFun1、MyFun2、MyFun3 這三個函式(注:這三個函式的定義格式應相同)。  點選(此處)摺疊或開啟 #inc

函式指標作為函式引數函式作為函式引數

轉載於:http://blog.csdn.net/vlily/article/details/7244682 轉載於:http://blog.csdn.net/shengnan_wu/article/details/8116935 轉載於:http://blog.csdn.net/callm

指標作為引數的申請記憶體函式

如果函式的引數是一個指標,不要指望用該指標去申請動態記憶體。 示例程式1: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(char) * num); } void Test

函式指標作為函式引數,實現氣泡排序的升序排序和降序排序

#include<stdio.h> #define N 10//定義陣列元素個數 int Ascending(int a,int b);//升序排列的函式宣告 int Descendin

指標作為引數傳入函式的陷阱

下面以一個例子來引出這種錯誤: #include <iostream> using namespace std; #include <stdlib.h> #include &l

函式指標作為函式引數

指向函式的指標變數 作為函式的形式引數時,可以把相應函式的入口地址作為實參傳遞給函式。當函式指標所指向的目標不同時,在函式中就可以呼叫不同的函式,且不需要對函式體作任何修改。# include <

c++ 物件作為引數,指標作為引數,引用作為引數

c++ 引數傳遞方式有三種,分別為:傳物件,傳引用和傳指標,那這三種傳遞方式之間到底有什麼區別呢? 傳物件:是將實參物件的值傳遞給形參物件,是單項傳遞,在函式中修改形參的值時,不會影響到原來實參的值 傳引用:把實參物件名傳給形參物件名,形參物件名就成為實參物件名的別名,實參和形參

連結串列頭節點問題(指標作為引數傳遞不能為NULL)

真是腦殘,以前沒有注意過這個問題,今天噁心了我好一會。做個記錄,以後不要再犯。  這樣在main函式裡面定義一個指標變數然後傳進函式裡面在申請空間的做法是錯誤的。 void creat(node* head) { if(head==NULL){ head=(node*)mal

c指標作為引數傳遞以及指標指標

#include "stdio.h" void pointer(int *p) { int a = 11; printf("\n\nEnter function"); printf("\nthe p is point to %p , addr is %X, *p is %d",p ,

函式可以作為引數使用

//函式可以作為引數使用,如果一個函式作為引數,那麼我們可以叫這個函式為回撥函式//也就是說:只要是看見一個函式為引數了,那就是回撥函式function sayHi(fn) { console.log("你好,世界"); fn();//}function sayYes() { console

C++傳入任意的函式型別作為引數

C++程式設計中,有些時候需要傳入函式作為引數,這在STL中作為謂詞經常用到。傳入的可以是函式、函式物件和lambda表示式。程式設計的時候,把它當成一個模板型別傳入即可。以下給出一個簡單的例子: #include <iostream> #include <util

C語言:通過函式指標引數來呼叫函式

C語言可以通過函式指標來呼叫函式,可以將要呼叫的函式名儲存到陣列中。這樣我們可以通過引數來直接呼叫函數了。 #include <stdio.h> #define FUNCTIONSIZE 2 typedef unsigned char uint8_t;

Delphi 呼叫 c編寫的動態連結庫,結構體指標作為引數

折騰了一天終於把 結構體指標作為在delphi和c動態連結庫之間函式引數傳遞的問題徹底解決了,花了一天時間的主要原因是沒有領會引數傳遞的精髓。現在把c程式碼和delphi程式碼粘上來,以供後來者學習參考。 delphi程式程式碼: unit Unit3; interfac

函式指標作為結構體的成員

我發一個執行過的原始碼。 在.h檔案中,有如下程式碼: //TVM控制狀態 typedef struct _m_TVM_CTRL {  u32(*get_coin_totval)(void); //得到此次投入硬幣總金額  u32(*get_coin_totcnt)(vo

go語言結構體陣列的指標作為引數。。。

package main import ( "fmt" ) type XCDataStu struct { Id int `json:"id" xorm:"id"` Name s

C++模板程式設計->成員函式指標模板引數

class some_value; typename int (some_value::*some_value_mfp)(int); template<some_value_mfp func> int call(some_value &value ,

陣列傳參,指標作為引數

目錄 總結: 一、陣列傳參 1.一維陣列作為引數(形參) 一維陣列作為引數(形參)傳參時——>可用一維陣列來接收(實參) void test(int[10]) { ; } int main() { int arr [10