C指针

数据的存储

  • 计算机将内存分隔为字节(byte),每个字节可存储8位(bit)的二进制信息。每个字节都有唯一的地址,用来和内存中其他字节相区别。一个字节称为一个存储单元(内存单元)。
  • 为了正确访问内存单元,每个内存单元都有一个编号,内存单元的编号称为地址。
  • 内存单元中的内容是我们关注的数据
数据的存储

访问方式

  • 数据访问分为直接访问和间接访问
  • 直接访问指的是直接访问内存单元中的内容,间接访问时通过内存单元编号(地址)以及数据所占字节数来访问内存中的数据。
  • 间接访问在程序中随处可见,指针是间接访问的常用方式。

指针变量

  • 理解指针的第一步是在机器级别上观察指针表示的内容,指针是内存中数据的内存地址。
  • 指针就是地址,而指针变量就是存储地址的变量。
指针变量
  • 通过&符号取变量的地址
int a = 20;
printf("%p", &a);// %p打印内存地址
int *p = &a;
  • 与普通变量不同的是,定义指针变量的时候,前面需要加上*

  • 使用*操作符访问内存编号里对应的内容

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int a = 100;
    int *p = NULL;// NULL恒等于0
    p = &a;// 指针变量是存放地址的变量
    //printf("%d\n", *p);// *和&是配套的操作符
    //printf("%p\n%p\n%d", &a, p, *p);
    printf("%p\n%p\n%d\n%d\n", &a, p, *p, *&a);//0061FF28 0061FF28 100 100
    return 0;
}
  • 指针的重指向,指针变量的赋值意味着重指向。
#include <stdio.h>

int main(int argc, const char * argv[])
{
    int a = 100, b = 200;
    int *p = &a;
    p = &b;// 指针变量的赋值意味着重指向
    printf("%p\n%d\n",p,*p);// 0061FF24 200
    return 0;
}

指针变量初始化

  • 如果指针变量没有初始化,那么视图使用指针变量的值将会导致未定义的行为。
#include <stdio.h>

int main(int argc, const char * argv[])
{
    int *p;
    printf("%d\n", *p);

    return 0;
}

给指针变量赋值尤其危险

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int *p;
    *p = 1;//如赋值改变的内存属于该程序则导致不规律的行为,若改变的内存属于操作系统则很可能导致系统崩溃。
    printf("%d\n", *p);

    return 0;
}

指针的类型

  • 因为内存地址只跟操作系统有关,所以指针变量所占内存大小取决于操作系统位数。即32位系统指针占4个字节,64位操作系统指针占8个字节。
  • 指针可分为 int *pidouble *pdchar *pc
#include <stdio.h>

int main(int argc, const char * argv[])
{
    int *pi = NULL;
    double *pd = NULL;
    char *pc = NULL;

    printf("%d %d %d", sizeof(int *), sizeof(double *), sizeof(char *));//4 4 4

    return 0;
}

注意事项

  • 指针变量定义 int *p=NULL;此时的*只起到修饰作用,告诉编译器,p是个指针。
  • p=&a; *p=20//此时的*是取内容操作符,将内存地址为p的存储区域中存入数据20。

指针赋值

C语言允许使用赋值运算符进行指针的赋值,前提是两个指针具有相同的数据类型。

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int i, *p, *q;

    p = &i;
    q = p;// q和p存储都是i的地址
    printf("%d %d %d\n", i, *p, *q);// 0 0 0
    *p = 1;// 改变i的值为1
    printf("%d %d %d\n", i, *p, *q);// 1 1 1
    *q = 2;// 改变i的值为2
    printf("%d %d %d\n", i, *p, *q);// 2 2 2

    return 0;
}
#include <stdio.h>

int main(int argc, const char * argv[])
{
    int i, j, *p, *q;

    p = &i;//p指向i
    q = &j;//q指向j
    
    i = 1;
    *q = *p;//将p指向的值"复制"给q指向的值
    printf("%d %d %d %d\n", i, j, *p, *q);// 1 1 1 1

    return 0;
}

指针作为参数

  • 指针到底对什么有益呢?
  • 定义个交换两个整型变量的值的函数
#include <stdio.h>

void swap(int i, int j);

int main(int argc, const char * argv[])
{
    int i=1, j=2;
    swap(i,j);// 函数传参的过程,是把实际参数的值拷贝到形参中。
    printf("%d %d\n", i, j);// 1 2

    return 0;
}

void swap(int i, int j)
{
    int tmp = i;
    j = i;
    tmp = j;
}
#include <stdio.h>

void swap(int *i, int *j);

int main(int argc, const char * argv[])
{
    int i=1, j=2;
    swap(&i,&j);
    printf("%d %d\n", i, j);// 2 1

    return 0;
}

void swap(int *i, int *j)
{
    int tmp = *i;//将i变量中存储的地址中的内容赋值给tmp
    *i = *j;//将j变量存储地址上的值存储到i变量存储地址的值
    *j = tmp;
}

  • 由编译器自动分配和释放
  • 在函数体中定义的变量通常在栈内存空间上
  • 栈中的变量是先进后出
  • 栈中的变量一般出了函数就会被释放掉
#include <stdio.h>
int *fn(void);

int main(int argc, const char * argv[])
{
    int *pi = fn();
    printf("%d\n", *pi);// 1
    printf("%d\n", *pi);// 1521606922
    return 0;
}

int *fn(void)
{
    int num = 1;
    int *p = &num;
    return p;
}

静态区

  • 全局变量和静态变量的存储是放在一块的,存储在静态区。
  • 静态区中的变量在程序结束后立即被释放
#include <stdio.h>
int *fn(void);

int main(int argc, const char * argv[])
{
    int *pi = fn();
    printf("%d\n", *pi);// 1
    printf("%d\n", *pi);// 1
    return 0;
}

int *fn(void)
{
    static int num = 1; // 静态变量
    int *p = &num;
    return p;
}

小结:

  • 不仅可为函数传递指针还可编写返回指针的函数
  • 函数可以返回指向外部变量或指向声明为static的局部变量的指针
  • 永远不要返回指向自动局部变量的指针,因为函数结束后局部变量就不存在了,所以指向局部变量的指针是无效的。

结构体指针

  • 指向结构体变量的指针称为结构体指针
#include <stdio.h>

// 定义结构体
typedef struct {
    char name[20];
    int age;
    char sex;
} Student;

int main(int argc, const char * argv[])
{
    Student stu = {0};
    Student *p = &stu;// 定义结构体指针
    (*p).age = 10;//使用结构体指针访问成员
    printf("%d\n", p->age);// 10
    p->age = 20;
    printf("%d\n", p->age);// 20

    return 0;
}

结构体数组与指针的关系

#include <stdio.h>

// 定义结构体
typedef struct {
    char name[20];
    int age;
    char sex;
} Student;

int main(int argc, const char * argv[])
{
    Student stu[5] = {0};//定义结构体数组
    Student *p = stu;// 定义结构体指针
    p[0].age = 10;//使用结构体指针访问成员
    p[0].sex = 'm';
    printf("%d %c\n", p[0].age, p[0].sex);// 10 m

    return 0;
}

结构体内包含指针

#include <stdio.h>
#include <string.h>

// 定义结构体
typedef struct {
    char nickname[20];
    char *username;
} Student;

int main(int argc, const char * argv[])
{
    Student stu = {0};//定义结构体数组
    strcpy(stu.nickname, "alice");//数组名是一个常量指针,不可以改变其值。
    //warning: ISO C++ forbids converting a string constant to 'char*'
    stu.username = "bob";//字符指针是一个指针变量可重新赋值
    printf("%s %s\n", stu.nickname, stu.username);// alice bob

    return 0;
}

数组作为参数

  • 取一个数组中的最大元素
  • 有一个整型数组,将数组元素大于27的清零。
  • 数组作为参数,形参仅代表数组首元素地址,需传入元素个数。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,113评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,644评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,340评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,449评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,445评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,166评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,442评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,105评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,601评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,066评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,161评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,792评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,351评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,352评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,584评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,618评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,916评论 2 344

推荐阅读更多精彩内容

  • 转自:http://blog.csdn.net/soonfly/article/details/51131141 ...
    zwithz阅读 1,020评论 0 13
  • C语言指针的总结 1. 变量 不同类型的变量在内存中占据不同的字节空间。 内存中存储数据的最小基本单位是字节,每一...
    xx_cc阅读 3,691评论 11 39
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,424评论 3 44
  • 我一直以为人是慢慢变老的,其实不是,人是一瞬间变老的。——村上春树《舞!舞!舞!》。前两天听李源说书,讲到...
    可可惜阅读 239评论 0 2
  • 我:要是我有文笔写点文章赚赚外快也好… 你:这是可怕的工作。 灵感一来,通宵达旦,废寝忘食。 闭门不出,浪费的不只...
    乔和阅读 144评论 0 0