關(guān)于指針

簡介

  • c語言之所以強(qiáng)大,以及其自由性,很大部分體現(xiàn)在其靈活的指針運(yùn)用上。因此,說指針是c語言的靈魂,一點(diǎn)都不為過。

一級指針

* 數(shù)組做函數(shù)參數(shù)時沒有副本機(jī)制,只是一個地址,因此傳入數(shù)組參數(shù)時需要傳入數(shù)組的大小

void fun(char str[][5], int len)
{
    printf("sizeof str: %d\n", sizeof(str));
    for(int i = 0; i < len; ++i)
    {
        printf("strlen str[%d]: %d\tsizeof str[%d]: %d\n", i, strlen(str[i]), i, sizeof(str[i]));
    }
}

輸出結(jié)果:
sizeof str: 4
循環(huán)輸出的strlen為每個字符串的長度
循環(huán)輸出的sizeof為5(原因見函數(shù)實參類型)

* 函數(shù)改變外部變量

void modifyvariable(int *src, int value)
{
    *src = value;
}

int main()
{
    int a = 100;
    printf("a: %d\n", a);
    modifyvariable(&a, 200);
    printf("a: %d\n", a);
}

輸出結(jié)果:
a: 100
a: 200

* 跨進(jìn)程改變變量(外掛)

* 采用微軟的`detours`庫

* 將程序編譯成動態(tài)鏈接庫DLL

* 將DLL注入到目標(biāo)線程中,實現(xiàn)修改某地址的數(shù)據(jù),或者攔截函數(shù)

* 做函數(shù)形參,數(shù)組做參數(shù)時會退化為一個一級指針,即其內(nèi)存空間大小為4

void fun(char str[][5], int len)
{
    printf("sizeof str: %d\n", sizeof(str));
}
輸出結(jié)果:
sizeof str: 4

* 儲存數(shù)組的首地址,指針數(shù)組

char str[][6] = { "eth8", "eth1", "eth6", "eth3", "eth4" };
char *pstr[5] = { NULL, NULL, NULL, NULL, NULL };

for (int i = 0; i < 5; ++i)
{
    pstr[i] = str[i];
}

char *p = NULL;

for (int i = 1; i < 5; ++i)
{
    for (int j = 0; j < i; ++j)
    {
        if (strcmp(pstr[i], pstr[j]) < 0)
        {
            p = pstr[i];
            pstr[i] = pstr[j];
            pstr[j] = p;
        }
    }
}

for (int i = 0; i < 5; ++i)
{
    printf("%s\n", pstr[i]);
}

輸出結(jié)果:
eth1
eth3
eth4
eth6
eth8

* return 有副本機(jī)制

* 其值存放在寄存器中,不能取地址

* 如果返回一個在棧上聲明的變量,兩次輸出return的值可能不同

* 如果立馬輸出,由于寄存器還未被其他變量使用,則可能返回正確值;

* 如果延時輸出(幾條IO輸出語句即可),則返回錯誤值;

* 作為函數(shù)的返回地址(不能返回指向棧上的內(nèi)容)

* 具體原因見上一條

* 存儲常量字符串的首地址,不能修改其值

* 間接訪問結(jié)構(gòu)體,創(chuàng)建堆上的變量

* 通過`->`運(yùn)算符訪問結(jié)構(gòu)體中聲明的變量

* 通過`malloc`、`calloc`、`realloc`、`new`等函數(shù)在堆上開辟內(nèi)存空間

* #的作用,無論類型,直接加"",可用于獲取函數(shù)名變量名等

#define funname(fun)    \
{           \
    printf("%s\n", #fun);       \
}
void modifyvariable(int *src, int value)
{
    *src = value;
}
int main()
{
    funname(modifyvariable);
    return 0;
}
輸出結(jié)果:
modifyvariable

指針數(shù)組

  • 批量管理地址
char str[][6] = { "eth8", "eth1", "eth6", "eth3", "eth4" };
char *pstr[5] = { NULL, NULL, NULL, NULL, NULL };

for (int i = 0; i < 5; ++i)
{
    pstr[i] = str[i];
}

char *p = NULL;

for (int i = 1; i < 5; ++i)
{
    for (int j = 0; j < i; ++j)
    {
        if (strcmp(pstr[i], pstr[j]) < 0)
        {
            p = pstr[i];
            pstr[i] = pstr[j];
            pstr[j] = p;
        }
    }
}

for (int i = 0; i < 5; ++i)
{
    printf("%s\n", pstr[i]);
}

輸出結(jié)果:
eth1
eth3
eth4
eth6
eth8

函數(shù)指針

  • 函數(shù)名等價于常指針
  • 函數(shù)指針數(shù)組:int (*p[2])(int a, int b) = {add, sub};
int add(int x, int y)
{
    return x + y;
}

int sub(int x, int y)
{
    return x - y;
}

int main()
{
    int(*fun[2])(int, int) = { add, sub };
    for (int i = 0; i < 2; ++i)
    {
        printf("%d\n", fun[i](100, 50));
    }

    return 0;
}
輸出結(jié)果:
150
50

malloc,realloc,calloc

  • malloccalloc區(qū)別:
    • malloc在堆上開辟一塊內(nèi)存,不會對內(nèi)存進(jìn)行清零操作
      • eg: int *p = (int *)malloc(sizeof(int) * 10);
    • calloc在堆上開辟一塊內(nèi)存,并且執(zhí)行內(nèi)存清零操作
      • eg: int *p = (int *)calloc(10, sizeof(int));
  • realloc重新分配內(nèi)存,新增加的內(nèi)存不會置零

關(guān)于指針類型

  • 根據(jù)指針的內(nèi)存大小來判定指針的類型
void getaddress(char str[][6])
{
    printf("In Function: \n");
    printf("str:\t\t%p\tsizeof: %d\n", str, sizeof(str));
    printf("str[0]:\t\t%p\tsizeof: %d\n", str[0], sizeof(str[0]));
    printf("str[0][0]:\t%p\tsizeof: %d\n", &str[0][0], sizeof(str[0][0]));
}

int main()
{
    char str[][6] = { "eth8", "eth1", "eth6", "eth3", "eth4" };
    {
        printf("In Main: \n");
        printf("str:\t\t%p\tsizeof: %d\n", str, sizeof(str));
        printf("str[0]:\t\t%p\tsizeof: %d\n", str[0], sizeof(str[0]));
        printf("str[0][0]:\t%p\tsizeof: %d\n", &str[0][0], sizeof(str[0][0]));
    }
    getaddress(str);
    return 0;
}

輸出結(jié)果:
In Main:
str:            0043FC04        sizeof: 30
str[0]:         0043FC04        sizeof: 6
str[0][0]:      0043FC04        sizeof: 1
In Function:
str:            0043FC04        sizeof: 4
str[0]:         0043FC04        sizeof: 6
str[0][0]:      0043FC04        sizeof: 1

關(guān)于指針的遍歷

  • 無論多少級指針,其遍歷方法都類似
int main()
{
    int num[4][3] = { {1, 2, 3}, {2, 3, 4}, { 3, 4, 5}, {4, 5, 6} };
    for (int i = 0; i < 4; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            printf("%d\t", num[i][j]);
        }
        putchar('\n');
    }

    putchar('\n');
    putchar('\n');
    for (int i = 0; i < 4; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            printf("%d\t", *(*(num + i) + j));
        }
        putchar('\n');
    }
    return 0;
}
輸出結(jié)果:
1       2       3
2       3       4
3       4       5
4       5       6


1       2       3
2       3       4
3       4       5
4       5       6

NOTE

  • printf不會進(jìn)行類型轉(zhuǎn)換,即占位符是什么類型,就按什么類型輸出
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容