程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C語言常量與指針

C語言常量與指針

編輯:C++入門知識

C語言功能強大而豐富,還表現在const與指針的結合使用上,對不同的問題,它提供不同的保護,特別有用的是指向常量的指針

本文地址:http://www.cnblogs.com/archimedes/p/c-const-point.html,轉載請注明源地址。

指向常量的指針

可以將指針指向常量,這就意味著不能通過指針修改它所引用的值

int num = 5;
const int limit = 500;
int *pi;
const int *pci;
pi = #    //指向整數
pci = &limit; //指向整數常量

下面的代碼會打印這些變量的地址和值:

#include <stdio.h>
int main(void)
{
    int num = 5;
    const int limit = 500;
    int *pi;
    const int *pci;
    pi = &num;    //指向整數
    pci = &limit; //指向整數常量
    printf("  num - Address:%p   value:%d\n", &num, num);
    printf("limit - Address:%p   value:%d\n", &limit, limit);
    printf("   pi - Address:%p   value:%p\n", &pi, pi);
    printf("  pci - Address:%p   value:%p\n", &pci, pci);
    return 0;
}

不能解引指向常量的指針並改變指針所引用的值,但是指針的值不是常量,可以改變指針,指針可以改為引用另一個整數常量或普通整數

把pci聲明為指向整數常量的指針意味著:

  • pci可以被修改為指向不同的整數常量

  • pci可以被修改為指向不同的非整數常量

  • 可以解引pci以讀取數據

  • 不能解引pci從而修改它指向的數據

注意:數據類型和const的順序無關緊要,可以互換

const int *pci = int const *pci

指向非常量的常量指針

指針不可變,但是它指向的數據可變

int num;
int *const cpi = &num;

如果將cpi初始化為指向常量limit將產生錯誤,因為cpi指向的數據可以修改,但是常量是不能被修改的

const int limit = 500;
int * const cpi = &limit;

指向常量的常量指針

這種類型的指針很少使用,這種指針不能修改,它指向的數據也不能通過它來修改,下面是一個例子:

const int * const cpci = &limit;

不一定只能將常量的地址賦給cpci,如下:

int num;
const int * const cpci = &num;

聲明此類指針的時候必須進行初始化

指向“指向常量的常量指針”的指針

#include <stdio.h>
int main(void)
{    
    const int limit = 500;
    const int * const cpci = &limit;
    const int * const * pcpci = &cpci;
    printf("%d\n", *cpci);
    printf("%d\n", **pcpci);
    return 0;
}

下表總結所討論的四種指針:

指針類型 指針是否可修改 指向指針的數據是否可修改 指向非常量的指針 是 是 指向常量的指針 是 否 指向非常量的常量指針 否 是 指向常量的常量指針 否 否

舉例說明

下面的例子中,function函數返回一個指向結構體常量的指針,意味著結構體中的值是只讀的,限定符很有用,因為它告訴我們一些不能進行的操作

#include<stdio.h>
#include<stdlib.h>
struct a
{
    int x;
};
const struct a * function(void)
{
    struct a *ptr;
    if((ptr = (struct a *)malloc(sizeof(struct a))) == NULL)
        exit(1);
    ptr->x = 0;
    return ptr;
}
int main(void)
{    
    int y;
    const struct a *ptr;
    ptr = function();
    y = ptr->x;
    return 0;
}

如果我們試圖修改,我們將得到一個gcc error

int main(void)
{    
    int y;
    const struct a *ptr;
    ptr = function();
    ptr->x = 1;
    return 0;
}

error: assignment of read-only location ‘*ptr’
如果將值賦值給一個非結構體常量,我們將得到gcc的警告

int main(void)
{    
    int y;
    struct a *ptr;
    ptr = function();
    ptr->x = 1;
    return 0;
}

warning: assignment discards qualifiers from pointer target type

如果使用類型轉換將可以成功運行

int main(void)
{
    struct a *ptr;
    ptr = (struct a *) function();
    ptr->x = 1;
    return 0;
}

結構體常量指針作為參數

#include<stdio.h>
#include<stdlib.h>
struct a
{
    int x;
};
struct b
{
    const struct a *nested_ptr;
};
const struct a * function(void)
{
    struct a *ptr;
    if((ptr = (struct a *) malloc(sizeof(struct a))) == NULL){
        exit(1);
    }
    ptr->x = 0;
    return ptr;
}
void do_something(const struct b *ptr)
{
    const struct a *x = ptr->nested_ptr;
}
int main(void)
{
    struct b b_obj;
    b_obj.nested_ptr = function();
    do_something(&b_obj);
    return 0;
}

常量指針

將一個指針指定為常量的,const關鍵字放在"*"的後面,就像上面的do_something()原型可以改寫為下面的形式,所有的都不可以修改,ptr變量通過調用傳遞參數初始化,以後就不能修改

void do_something(const struct b * const ptr);

常量初始化延伸

一個結構體常量可以像下面這樣初始化:

int main(void)
{
    const struct a obj = [ 5 ];
    return obj.x;
}

一個指向結構體常量的指針可以像下面這樣初始化:

int main(void)
{
    const struct a obj = [ 5 ];
    const struct a *ptr_a = &obj;
    const struct a *ptr_b = function();
    return ptr_a->x;
}

返回常量指針

const struct a * const function(void);

傳遞指向常量指針的指針

一個常見傳遞二重指針的原因就是需要修改指針值,看下面的例子:

void fill_in(const struct a **location)
{
    *location = function();
}
int main(void)
{
    const struct a *ptr;
    fill_in(&ptr);
    return 0;
}

再看下面的代碼,在location前面加上const

void fill_in(const struct a ** const location)
{
    *location = function();
}

解釋如下:

1、結構體是常量的,內容不能修改

2、指向該結構體的指針,通過location指向,*location不是常量,可以修改

3、變量location是常量的,意味著不能被修改

還可以添加一個const:

void fill_in(const struct a * const * const location)
{
    *location = function();
}

error: assignment of read-only location ‘*location’ (由於*location也是常量,所以會得到gcc error)

下面的代碼不是操作結構體的內容,也不是指向結構體的指針,而是允許函數通過傳遞的參數操作它自身的局部變量

void make_use_of(const struct a * const *location)
{
    const struct a * const ptr_a = *location;
    const struct a *ptr_b = *location;
    ptr_b = NULL;
    location = NULL;
}

解釋如下:

1、結構體是常量的,內容不能修改

2、指向該結構體的指針,通過location指向,*location也是常量,不可以修改

3、變量location是非常量,意味著可以被修改

4、局部變量ptr_a是常量,不可以被修改

4、局部變量ptr_a不是常量,可以被修改

參考資料

維基百科

《C和指針》

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved